mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-25 04:17:15 +00:00
feat(sub): client-side balancers for the JSON subscription (#6243)
* feat(sub): add SubBalancer model and migration Client-side JSON-subscription balancer row: remark, strategy, member inbound ids, sort order, enabled. Registered in allModels and migrationModels so AutoMigrate and SQLite->Postgres copy pick it up. * feat(sub): add SubBalancer service List/Get/Create/Update/Delete over the sub_balancers table with remark trim, strategy allowlist (leastLoad/leastPing/random) and sort-order floor. Rows are read per request by the subscription builder, so mutations need no xray restart. * feat(sub): add SubBalancer API controller and routes GET/POST /panel/api/sub-balancers, POST /:id (update), DELETE /:id and POST /:id/del alias. inboundIds bind from repeated form keys. Mounted under the /panel/api group so the existing API token + CSRF middleware cover it. * feat(sub): emit client-side balancers in JSON subscription For each enabled balancer, append one config document whose outbounds are the selected inbounds' proxy outbounds retagged under a per-balancer prefix, with routing.balancers + burstObservatory selecting it. Balancer entries interleave with inbound entries by sort order; on equal numbers the balancer follows the inbound. Skipped when disabled or no member outbound is present. * test(sub): cover SubBalancer service and JSON output Service: validation gates (remark/strategy/inbound ids/sort order) and CRUD round-trip. JSON: balancer document shape, sort interleaving with inbounds, disabled/empty skip, and member tag dedup. * feat(sub): add sub-balancers i18n keys pages.settings.subBalancers.* block (menu, title, add, desc, field labels, strategy names, sort-order help, validation messages) added to all 13 locales. * feat(sub): add SubBalancer schema and API queries Zod schema (entity + form, strategy enum, validation messages wired to i18n keys), react-query hooks for list/create/update/delete, and the sub-balancers query key. * feat(sub): add subscription balancers settings tab SubscriptionBalancersTab lists balancers (sort order, remark, strategy, inbound count, enabled toggle, edit/delete) with a form modal (remark, strategy, sort order, multi-select inbounds filtered to multi-client protocols, enabled). Wired into SettingsPage under #subscription-balancers, and the sidebar shows the entry only when JSON subscription is enabled. * test(sub): add SubBalancer form modal test Covers add-mode (no validation errors, confirm with parsed values) and edit-mode (seeds from the balancer, preserves strategy/sort order/enabled). * feat(sub): register sub-balancers in API docs and OpenAPI Adds the sub-balancers endpoint group to endpoints.ts (list/create/update/delete + POST del alias) and regenerates frontend/public/openapi.json from it. * docs: sync openapi.json with frontend docs/public/openapi.json had fallen behind frontend/public/openapi.json (fewer paths/schemas). Copy the current frontend spec so the docs site renders the full API. * docs: add subscription balancers API reference Registers the sub-balancers page (generated MDX) and adds the sub-balancers paths to docs/public/openapi.json so the page renders the list/create/update/delete operations. * feat(sub): accept roundRobin balancer strategy Add roundRobin to the model oneof tag and the service strategy allowlist, alongside leastLoad/leastPing/random. Covered by a service-level create test that fails on the old allowlist. * feat(sub): add roundRobin strategy label pages.settings.subBalancers.strategyRoundRobin added to all 13 locales. * feat(sub): expose roundRobin in balancer form Zod strategy enum, form modal label key, and table strategy colour for roundRobin. * docs(sub): list roundRobin in strategy description The create/update strategy param description now mentions roundRobin alongside the other three. * feat(sub): add subJsonObservatory setting Panel-wide JSON string carrying the burstObservatory ping config (destination, connectivity, interval, sampling, timeout, httpMethod) emitted into client-side balancer docs. Stored like subJsonMux/Rules/FinalMask. * feat(sub): wire observatory config through sub controller WithSUBJsonObservatory option; the controller calls SubJsonService.SetObservatoryConfig after construction. * feat(sub): emit observatory conditionally with configurable probes burstObservatory is emitted only for leastPing/leastLoad; random/roundRobin get none (no fallback, so an observatory would only probe for nothing). Probe params come from the subJsonObservatory setting, falling back to the built-in defaults when empty or partial. Test covers the conditional emit and the override. * feat(sub): add subJsonObservatory to AllSetting model Frontend AllSetting model and Zod schema carry the new panel-wide observatory config string. * feat(sub): add balancer observatory config card New Sub Formats tab editing destination/connectivity/interval/sampling/timeout/httpMethod, stored as JSON in subJsonObservatory. Toggle off clears the setting; the backend then falls back to defaults. * fix(sub): hide save/restart header on sub-balancers tab Sub-balancer mutations are incremental (own CRUD API, no Save, no restart), so the page-wide 'every change needs to be saved / restart the panel' banner is misleading there. The in-tab alert already explains it correctly. * feat(sub): add observatory config i18n keys pages.settings.subBalancers.observatory.* (title, desc, probe field labels and help texts) added to all 13 locales. * feat(sub): regenerate openapi for subJsonObservatory openapigen picks up the new AllSetting field; openapi.json synced into docs. * feat(sub): add observatory tab to sub-balancers Mirrors the Xray Balancers page: two tabs (Balancers + Observatory). Wires allSetting/updateSetting into the tab and adds tabBalancers / tabObservatory labels to all locales. The page Save header is shown again on this tab so the observatory config can be saved. * refactor(sub): drop observatory tab from sub-formats Now that the observatory config lives under sub-balancers, remove the duplicate tab plus its state and defaults from sub-formats. * fix(sub): add missing inboundsCount i18n key The sub-balancers table rendered the raw key path in the Inbounds column because pages.settings.subBalancers.inboundsCount was not defined. Added it to all 13 locales. * test(sub): pin disabled-inbound exclusion from balancer The balancer builds its members from the subscriber's already-filtered entry set, so an inbound disabled for that user can never surface as a member. Adds tests for both shapes (one of several disabled, and the only selected one disabled). * fix(sub): make observatory toggle honest, default connectivity off, add balancer fallback Three coupled defects on the balancer observatory surface, flagged in PR review: - The Observatory Switch wrote '' which the Go side treats as "use built-in defaults", so leastPing/leastLoad still shipped a burstObservatory the admin could no longer see or edit. The observatory is mandatory for these strategies (Xray refuses to start leastPing/leastLoad without one — verified against Xray 26.7), so the switch is relabelled to "customise probe parameters vs built-in defaults" rather than on/off: '' keeps the defaults, a stored JSON overrides them. An info Alert explains this. - Connectivity defaulted to http://www.google.com/generate_204 and an explicit {"connectivity":""} restored it, so the UI's "Leave empty to skip" was unreachable and the direct pre-check was dead on arrival on censored client networks. Default to "" and honour an explicit empty value. - routing.balancers had no fallbackTag, so a leastPing/leastLoad balancer whose probes all fail selects nothing and dispatch fails. Emit fallbackTag pointing at the first member so a probe outage degrades instead of breaking. Also skip balancer entries (kind!=0) in the member scan so a balancer can never match another balancer's row id. Tests cover each fix and fail without it. * fix(sub-balancer): localize controller toasts and reject malformed ids Route the new controller's user-facing messages through I18nWeb so non-English admins get localized toasts like every other controller, and switch parseID to strconv.Atoi rejecting ids < 1 so "12abc" and negative ids no longer coerce to a silent no-op delete that reports success. * fix(sub-balancer): enforce remark length cap server-side The model's validate:"max=256" tag was never enforced (parseSubBalancerForm binds an ad-hoc struct without validate.Struct), so a scripted API client could store an unbounded remark that is emitted verbatim as the remarks field of every affected subscriber's config. Reject len > 256 in validate() to match the frontend Zod cap. * fix(sub-balancer): exclude mtproto from balancer member picker SubJsonService.getConfig has no mtproto case, so an mtproto inbound's first outbound is "direct" and the buildBalancerConfig "tag != proxy" guard drops it — an admin could select it, save without error, and get a balancer that silently omits it (or no document at all). Drop it from the picker and fix the comment. * docs(sub-balancers): add nav entry, fix tab pointer, note mirror scope - Add "subscription-balancers" to the en reference/api meta.json pages array so the new MDX page is reachable from the sidebar (fa/ru/zh have no MDX — gen-openapi.ts emits into en only). - Fix the endpoints.ts section description from "Settings -> Subscription" to "Settings -> Sub Balancers" (the feature's own tab) and regenerate the OpenAPI spec + MDX. - Note in docs/lib/xray/subscription.ts that balancer documents are intentionally out of scope for that mirror. * style(model): trim SubBalancer comment to 2-line cap CLAUDE.md caps committed Go comment blocks at 2 lines; this one was 3. * fix(sub-balancer): parse enabled explicitly and preserve it on partial update parseSubBalancerForm treated any non-"false" value as true (so "bogus" silently enabled) and always overwrote Enabled on update, so a PATCH that omitted the toggle reset a disabled balancer back to enabled. Parse the field with strconv.ParseBool and return *bool: absent means "no change" on update and "true" on create; a malformed value is rejected as 400. Update keeps the stored Enabled when the pointer is nil. * fix(sub-balancer): clear deleted inbound from sub_balancers.InboundIds DelInbound cascaded hosts but left the deleted inbound id in every sub_balancers.InboundIds, so the balancer kept emitting a member no subscriber could resolve — a dangling outbound tag with no proxy behind it. Strip the id inside the existing delete transaction (same shape as the hosts cascade, #5648); with the last member gone the balancer stops emitting. * fix(sub-balancer): return not-found when deleting a missing balancer Delete returned the gorm result error only, which is nil when no row matched, so the controller reported success:true for an id that never existed — a stale UI row looked like a clean delete. Check RowsAffected and return a not-found error on 0 so the toast reflects reality. * style(sub): shorten leastPing/leastLoad observatory comments The observatory-emission guard comment and its test comment ran a few lines long; trim them to a couple of lines each without dropping the invariant that leastPing/leastLoad require a burst observatory. * fix(sub): validate observatory setting instead of silently dropping it SetObservatoryConfig applied whatever survived json.Unmarshal with no checks, so a bad probe URL ("not-a-url"), non-duration interval/timeout, or even unparseable JSON was either silently applied or silently ignored. Validate each field: parse durations with time.ParseDuration, require http(s) URLs for destination/connectivity, and log a warning naming the field and the bad value on every fallback — including the unmarshal error, which was a quiet return. Bad values now keep the built-in defaults instead of leaking into the emitted burstObservatory. * fix(sub): deduplicate burst-observatory defaults across Go and frontend The burst-observatory ping defaults lived in three places that had drifted: Go defaultSubBalancerObservatoryConfig (http probe, sampling 3), the Zod PingConfigSchema, and DEFAULT_BURST_OBSERVATORY (both with a connectivity pre-check URL). Align them to one set: https probe destination, sampling 2, and empty connectivity (skip the direct pre-check). The settings tab now parses the stored JSON through PingConfigSchema and seeds its default from DEFAULT_BURST_OBSERVATORY instead of carrying its own literal. * refactor(sub): extract proxy outbounds once before the balancer loop buildBalancerConfig unmarshalled every inbound document and re-extracted its first outbound on each balancer, so with B balancers and N inbound docs the same document was parsed B*N times. Pull each doc's proxy outbound in a single pre-pass over the entries and cache it per entry; buildBalancerConfig now clones the cached map before retagging, so one parse serves every balancer. Output is byte-for-byte unchanged. * fix(sub): form balancer member tags from the inbound protocol, not tcp→vless balancerTransport derived the bal-N tag suffix from the outbound's transport network and hard-coded tcp→vless, so a vmess/tcp or trojan/tcp member was mislabelled "vless" in every client config — the tag lied about the proxy type. Use the outbound's real protocol as the suffix (bal-1-vmess, bal-1-vless, bal-1-trojan, …) so the tag names the actual proxy; the selector prefix and dedup suffix are unchanged. Update the existing tag assertions and add a vmess case that fails under the old mapping. * fix(sub-balancer): default strategy to random in the create form The create-balancer form seeded strategy to 'leastLoad', but the service validate() defaults an empty strategy to 'random' and the API docs say the default is 'random' — so a freshly opened form showed leastLoad while saving without touching the field silently stored random. Align the form default to 'random' so what the admin sees is what gets persisted. * feat(api-docs): document the SubBalancer response schema The five sub-balancer endpoints carried no responseSchema, so the API docs page rendered them without a typed example. Add example: tags to every SubBalancer field, allow the struct through openapigen, and point the list (responseSchemaArray) and single-row endpoints at 'SubBalancer'. Regenerate the Zod/JSON schemas and OpenAPI doc and mirror openapi.json into docs/. * style(sub-balancer): drop whitespace-only separator lines, add final newline subBalancer.ts and SubBalancerFormModal.tsx used single-space blank lines as separators between statements and had no trailing newline. Replace them with clean empty blank lines and end each file with a newline. * fix(i18n): translate sub-balancer toasts and observatory note The sub-balancer toast messages (list/create/update/delete/invalidId) and the observatory note were left in English across 11 non-English locales (ar, es, fa, id, ja, pt-BR, tr, uk, vi, zh-CN, zh-TW) while every other key in the subBalancers block was already translated. Translate them to match the meaning and terminology of the surrounding keys in each file; the JSON structure and keys are unchanged. * fix(sub-balancer): hide disabled inbounds from the member picker The picker offered every protocol-eligible inbound regardless of its enable flag, but getInboundsBySubId filters `AND inbounds.enable = true`. A disabled member is therefore dropped from every subscriber's entries, and when it was the balancer's only member the balancer document silently stops being emitted — with nothing in the UI explaining why. TestSubJson_BalancerSkippedWhenAll MembersDisabled already documents that backend behavior. Filter the way the sibling client picker has since #5645: hide disabled inbounds, but keep one that is already selected so editing an existing balancer cannot silently drop a member. Drop the `?? []` on the useWatch result so the new useMemo dependency stays referentially stable. * style(sub): trim the balancerMemberSuffix comment to the 2-line cap Comment blocks in committed Go are capped at 2 lines; the name already carries what the function picks, so keep only the why. --------- Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,12 +1,8 @@
|
||||
---
|
||||
title: API Tokens
|
||||
description: 'Manage Bearer tokens used for programmatic auth (bots, central
|
||||
panels acting on this node, CI). Each token has a unique name and an enabled
|
||||
flag — disable to revoke without deleting, delete to revoke permanently.
|
||||
Tokens are stored as SHA-256 hashes and the plaintext is returned only once,
|
||||
in the create response — it cannot be retrieved afterwards, so copy it then.
|
||||
Send one as <code>Authorization: Bearer <token></code> on any
|
||||
/panel/api/* request — the token is a full-admin credential.'
|
||||
description: Manage scoped Bearer tokens for programmatic auth. Tokens grant
|
||||
admin, monitor, or node-sync access, may expire, and are stored as SHA-256
|
||||
hashes. The plaintext is returned only once at creation.
|
||||
full: true
|
||||
_openapi:
|
||||
preload:
|
||||
|
||||
@@ -14,18 +14,24 @@ _openapi:
|
||||
JSON-encoded-string form is still accepted on write).
|
||||
url: '#list-every-client-with-its-attached-inbound-ids-and-traffic-record-the-reverse-field-if-set-is-returned-as-a-nested-json-object-legacy-json-encoded-string-form-is-still-accepted-on-write'
|
||||
- depth: 2
|
||||
title: Filter, sort, and paginate clients on the server. Each item is a slim row
|
||||
(no uuid/password/auth/flow/security/reverse/tgId) so the clients page
|
||||
can ship 25-ish rows in a few KB instead of the full table. The response
|
||||
also includes a summary computed across the full DB row set so dashboard
|
||||
counters stay stable as the user paginates or filters. Page size capped
|
||||
at 200; fetch /get/:email to obtain the full per-client payload for an
|
||||
edit/info modal.
|
||||
url: '#filter-sort-and-paginate-clients-on-the-server-each-item-is-a-slim-row-no-uuidpasswordauthflowsecurityreversetgid-so-the-clients-page-can-ship-25-ish-rows-in-a-few-kb-instead-of-the-full-table-the-response-also-includes-a-summary-computed-across-the-full-db-row-set-so-dashboard-counters-stay-stable-as-the-user-paginates-or-filters-page-size-capped-at-200-fetch-getemail-to-obtain-the-full-per-client-payload-for-an-editinfo-modal'
|
||||
title: 'Filter, sort, and paginate clients on the server. Each item is a slim
|
||||
row (no uuid/password/auth/flow/security/reverse/tgId) so the clients
|
||||
page can ship 25-ish rows in a few KB instead of the full table. The
|
||||
response also includes a summary computed across the full DB row set so
|
||||
dashboard counters stay stable as the user paginates or filters: the
|
||||
*Count fields are exact, while the email arrays beside them stop at 200
|
||||
entries so the payload does not grow with the panel. Page size capped at
|
||||
200; fetch /get/:email to obtain the full per-client payload for an
|
||||
edit/info modal.'
|
||||
url: '#filter-sort-and-paginate-clients-on-the-server-each-item-is-a-slim-row-no-uuidpasswordauthflowsecurityreversetgid-so-the-clients-page-can-ship-25-ish-rows-in-a-few-kb-instead-of-the-full-table-the-response-also-includes-a-summary-computed-across-the-full-db-row-set-so-dashboard-counters-stay-stable-as-the-user-paginates-or-filters-the-count-fields-are-exact-while-the-email-arrays-beside-them-stop-at-200-entries-so-the-payload-does-not-grow-with-the-panel-page-size-capped-at-200-fetch-getemail-to-obtain-the-full-per-client-payload-for-an-editinfo-modal'
|
||||
- depth: 2
|
||||
title: Fetch one client by email, including the inbound IDs and external config
|
||||
IDs it is attached to.
|
||||
url: '#fetch-one-client-by-email-including-the-inbound-ids-and-external-config-ids-it-is-attached-to'
|
||||
- depth: 2
|
||||
title: Fetch clients by Telegram user ID. Returns an array since multiple
|
||||
clients can share the same Telegram ID.
|
||||
url: '#fetch-clients-by-telegram-user-id-returns-an-array-since-multiple-clients-can-share-the-same-telegram-id'
|
||||
- depth: 2
|
||||
title: Create a new client and attach it to one or more inbounds in a single
|
||||
call. Body is JSON. Per-protocol secrets are generated server-side when
|
||||
@@ -48,10 +54,10 @@ _openapi:
|
||||
title: Detach a client from one or more inbounds without deleting the client.
|
||||
url: '#detach-a-client-from-one-or-more-inbounds-without-deleting-the-client'
|
||||
- depth: 2
|
||||
title: Replace a client's external links (per-client share links and remote
|
||||
subscription URLs surfaced in their subscription). Sends the full set;
|
||||
the server replaces all rows.
|
||||
url: '#replace-a-clients-external-links-per-client-share-links-and-remote-subscription-urls-surfaced-in-their-subscription-sends-the-full-set-the-server-replaces-all-rows'
|
||||
title: Replace a client's external links and external subscriptions. Sends the
|
||||
full set; the server replaces all rows. Disabled rows stay saved for
|
||||
editing but are not emitted in generated subscriptions.
|
||||
url: '#replace-a-clients-external-links-and-external-subscriptions-sends-the-full-set-the-server-replaces-all-rows-disabled-rows-stay-saved-for-editing-but-are-not-emitted-in-generated-subscriptions'
|
||||
- depth: 2
|
||||
title: Reset the up/down counters for every client globally. Quotas and expiry
|
||||
are not affected. Triggers an Xray restart if any counter actually
|
||||
@@ -64,10 +70,10 @@ _openapi:
|
||||
url: '#delete-every-client-whose-traffic-quota-is-exhausted-used--total-when-reset-is-disabled-or-whose-expiry-has-passed-returns-the-deleted-count-and-triggers-an-xray-restart-when-any-client-was-on-a-running-inbound'
|
||||
- depth: 2
|
||||
title: Delete every client that is not attached to any inbound, along with its
|
||||
traffic record, IP log, and external links. Useful for clearing clients
|
||||
left unattached after their inbounds were removed. Returns the deleted
|
||||
count. Cannot be undone.
|
||||
url: '#delete-every-client-that-is-not-attached-to-any-inbound-along-with-its-traffic-record-ip-log-and-external-links-useful-for-clearing-clients-left-unattached-after-their-inbounds-were-removed-returns-the-deleted-count-cannot-be-undone'
|
||||
traffic record, IP log, HWID devices, and external links. Useful for
|
||||
clearing clients left unattached after their inbounds were removed.
|
||||
Returns the deleted count. Cannot be undone.
|
||||
url: '#delete-every-client-that-is-not-attached-to-any-inbound-along-with-its-traffic-record-ip-log-hwid-devices-and-external-links-useful-for-clearing-clients-left-unattached-after-their-inbounds-were-removed-returns-the-deleted-count-cannot-be-undone'
|
||||
- depth: 2
|
||||
title: Return every client as a {client, inboundIds} array — the same shape
|
||||
/bulkCreate and /import accept — so the payload round-trips straight
|
||||
@@ -88,12 +94,16 @@ _openapi:
|
||||
title: 'Shift expiry and/or traffic quota for many clients in one call.
|
||||
addDays/addBytes may be negative. Clients with unlimited expiry
|
||||
(expiryTime=0) or unlimited traffic (totalGB=0) are skipped for the
|
||||
corresponding field — bulk extend never converts unlimited to limited.
|
||||
The optional flow directive sets the XTLS flow on every client: "none"
|
||||
clears it, "xtls-rprx-vision"/"xtls-rprx-vision-udp443" set it where the
|
||||
inbound supports it (omit or "" to leave it unchanged). Returns the
|
||||
adjusted count and per-email skip reasons.'
|
||||
url: '#shift-expiry-andor-traffic-quota-for-many-clients-in-one-call-adddaysaddbytes-may-be-negative-clients-with-unlimited-expiry-expirytime0-or-unlimited-traffic-totalgb0-are-skipped-for-the-corresponding-field--bulk-extend-never-converts-unlimited-to-limited-the-optional-flow-directive-sets-the-xtls-flow-on-every-client-none-clears-it-xtls-rprx-visionxtls-rprx-vision-udp443-set-it-where-the-inbound-supports-it-omit-or--to-leave-it-unchanged-returns-the-adjusted-count-and-per-email-skip-reasons'
|
||||
corresponding field — bulk extend never converts unlimited to limited. A
|
||||
client that was auto-disabled solely because it was depleted (expired or
|
||||
over quota) is automatically re-enabled — locally and on its node — when
|
||||
the adjustment lifts it out of depletion; a manually-disabled or
|
||||
still-depleted client is left disabled. The optional flow directive sets
|
||||
the XTLS flow on every client: "none" clears it,
|
||||
"xtls-rprx-vision"/"xtls-rprx-vision-udp443" set it where the inbound
|
||||
supports it (omit or "" to leave it unchanged). Returns the adjusted
|
||||
count and per-email skip reasons.'
|
||||
url: '#shift-expiry-andor-traffic-quota-for-many-clients-in-one-call-adddaysaddbytes-may-be-negative-clients-with-unlimited-expiry-expirytime0-or-unlimited-traffic-totalgb0-are-skipped-for-the-corresponding-field--bulk-extend-never-converts-unlimited-to-limited-a-client-that-was-auto-disabled-solely-because-it-was-depleted-expired-or-over-quota-is-automatically-re-enabled--locally-and-on-its-node--when-the-adjustment-lifts-it-out-of-depletion-a-manually-disabled-or-still-depleted-client-is-left-disabled-the-optional-flow-directive-sets-the-xtls-flow-on-every-client-none-clears-it-xtls-rprx-visionxtls-rprx-vision-udp443-set-it-where-the-inbound-supports-it-omit-or--to-leave-it-unchanged-returns-the-adjusted-count-and-per-email-skip-reasons'
|
||||
- depth: 2
|
||||
title: Enable many clients in one call. Emails are grouped by inbound and
|
||||
applied with a single read-modify-write per inbound; the running Xray
|
||||
@@ -188,6 +198,13 @@ _openapi:
|
||||
after filtering by group for that. Returns the count of clients whose
|
||||
label was cleared.
|
||||
url: '#remove-a-group-deletes-the-client_groups-row-and-clears-the-group-label-from-every-matching-client-both-clientsgroup_name-and-the-inbound-settings-json-the-clients-themselves-are-not-deleted--use-bulkdel-after-filtering-by-group-for-that-returns-the-count-of-clients-whose-label-was-cleared'
|
||||
- depth: 2
|
||||
title: Reset only the group-level traffic counter shown on the groups page.
|
||||
Snapshots the current up/down sum of the group's members as a baseline
|
||||
so the group total reads zero, while leaving each client's own counters
|
||||
(and their quotas) untouched. No Xray restart is triggered. Creates the
|
||||
client_groups row if the group exists only as a derived label.
|
||||
url: '#reset-only-the-group-level-traffic-counter-shown-on-the-groups-page-snapshots-the-current-updown-sum-of-the-groups-members-as-a-baseline-so-the-group-total-reads-zero-while-leaving-each-clients-own-counters-and-their-quotas-untouched-no-xray-restart-is-triggered-creates-the-client_groups-row-if-the-group-exists-only-as-a-derived-label'
|
||||
- depth: 2
|
||||
title: Zero out a single client’s up/down counters. Re-enables the client across
|
||||
every attached inbound and pushes the change to Xray (or the remote
|
||||
@@ -204,6 +221,17 @@ _openapi:
|
||||
- depth: 2
|
||||
title: Reset the recorded IP list for a client.
|
||||
url: '#reset-the-recorded-ip-list-for-a-client'
|
||||
- depth: 2
|
||||
title: List registered HWID devices for a client. Hashes are not exposed.
|
||||
url: '#list-registered-hwid-devices-for-a-client-hashes-are-not-exposed'
|
||||
- depth: 2
|
||||
title: Clear all registered HWID devices for a client so new devices can
|
||||
register again.
|
||||
url: '#clear-all-registered-hwid-devices-for-a-client-so-new-devices-can-register-again'
|
||||
- depth: 2
|
||||
title: Remove a single registered HWID device by its id, freeing one slot under
|
||||
the HWID limit.
|
||||
url: '#remove-a-single-registered-hwid-device-by-its-id-freeing-one-slot-under-the-hwid-limit'
|
||||
- depth: 2
|
||||
title: List the emails of currently connected clients (last seen within the
|
||||
heartbeat window), deduped across every node.
|
||||
@@ -248,34 +276,28 @@ _openapi:
|
||||
Protocols without a URL form (socks, http, mixed, wireguard, dokodemo,
|
||||
tunnel) contribute nothing.'
|
||||
url: '#return-every-url-for-one-client-across-all-attached-inbounds--the-same-strings-the-copy-url-button-copies-in-the-panel-ui-supported-protocols-vmess-vless-trojan-shadowsocks-hysteria-if-streamsettingsexternalproxy-is-set-returns-one-url-per-external-proxy-protocols-without-a-url-form-socks-http-mixed-wireguard-dokodemo-tunnel-contribute-nothing'
|
||||
- depth: 2
|
||||
title: List registered HWID devices for a client. Hashes are not exposed.
|
||||
url: '#list-registered-hwid-devices-for-a-client-hashes-are-not-exposed'
|
||||
- depth: 2
|
||||
title: Clear all registered HWID devices for a client so new devices can
|
||||
register again.
|
||||
url: '#clear-all-registered-hwid-devices-for-a-client-so-new-devices-can-register-again'
|
||||
- depth: 2
|
||||
title: Remove a single registered HWID device by its id, freeing one slot under
|
||||
the HWID limit.
|
||||
url: '#remove-a-single-registered-hwid-device-by-its-id-freeing-one-slot-under-the-hwid-limit'
|
||||
structuredData:
|
||||
headings:
|
||||
- content: List every client with its attached inbound IDs and traffic record. The
|
||||
reverse field, if set, is returned as a nested JSON object (legacy
|
||||
JSON-encoded-string form is still accepted on write).
|
||||
id: list-every-client-with-its-attached-inbound-ids-and-traffic-record-the-reverse-field-if-set-is-returned-as-a-nested-json-object-legacy-json-encoded-string-form-is-still-accepted-on-write
|
||||
- content: Filter, sort, and paginate clients on the server. Each item is a slim
|
||||
- content: 'Filter, sort, and paginate clients on the server. Each item is a slim
|
||||
row (no uuid/password/auth/flow/security/reverse/tgId) so the clients
|
||||
page can ship 25-ish rows in a few KB instead of the full table. The
|
||||
response also includes a summary computed across the full DB row set
|
||||
so dashboard counters stay stable as the user paginates or filters.
|
||||
Page size capped at 200; fetch /get/:email to obtain the full
|
||||
per-client payload for an edit/info modal.
|
||||
id: filter-sort-and-paginate-clients-on-the-server-each-item-is-a-slim-row-no-uuidpasswordauthflowsecurityreversetgid-so-the-clients-page-can-ship-25-ish-rows-in-a-few-kb-instead-of-the-full-table-the-response-also-includes-a-summary-computed-across-the-full-db-row-set-so-dashboard-counters-stay-stable-as-the-user-paginates-or-filters-page-size-capped-at-200-fetch-getemail-to-obtain-the-full-per-client-payload-for-an-editinfo-modal
|
||||
so dashboard counters stay stable as the user paginates or filters:
|
||||
the *Count fields are exact, while the email arrays beside them stop
|
||||
at 200 entries so the payload does not grow with the panel. Page size
|
||||
capped at 200; fetch /get/:email to obtain the full per-client payload
|
||||
for an edit/info modal.'
|
||||
id: filter-sort-and-paginate-clients-on-the-server-each-item-is-a-slim-row-no-uuidpasswordauthflowsecurityreversetgid-so-the-clients-page-can-ship-25-ish-rows-in-a-few-kb-instead-of-the-full-table-the-response-also-includes-a-summary-computed-across-the-full-db-row-set-so-dashboard-counters-stay-stable-as-the-user-paginates-or-filters-the-count-fields-are-exact-while-the-email-arrays-beside-them-stop-at-200-entries-so-the-payload-does-not-grow-with-the-panel-page-size-capped-at-200-fetch-getemail-to-obtain-the-full-per-client-payload-for-an-editinfo-modal
|
||||
- content: Fetch one client by email, including the inbound IDs and external
|
||||
config IDs it is attached to.
|
||||
id: fetch-one-client-by-email-including-the-inbound-ids-and-external-config-ids-it-is-attached-to
|
||||
- content: Fetch clients by Telegram user ID. Returns an array since multiple
|
||||
clients can share the same Telegram ID.
|
||||
id: fetch-clients-by-telegram-user-id-returns-an-array-since-multiple-clients-can-share-the-same-telegram-id
|
||||
- content: Create a new client and attach it to one or more inbounds in a single
|
||||
call. Body is JSON. Per-protocol secrets are generated server-side
|
||||
when omitted, so callers can send only the universal fields.
|
||||
@@ -293,10 +315,10 @@ _openapi:
|
||||
id: attach-an-existing-client-to-one-or-more-additional-inbounds-body-is-json
|
||||
- content: Detach a client from one or more inbounds without deleting the client.
|
||||
id: detach-a-client-from-one-or-more-inbounds-without-deleting-the-client
|
||||
- content: Replace a client's external links (per-client share links and remote
|
||||
subscription URLs surfaced in their subscription). Sends the full set;
|
||||
the server replaces all rows.
|
||||
id: replace-a-clients-external-links-per-client-share-links-and-remote-subscription-urls-surfaced-in-their-subscription-sends-the-full-set-the-server-replaces-all-rows
|
||||
- content: Replace a client's external links and external subscriptions. Sends the
|
||||
full set; the server replaces all rows. Disabled rows stay saved for
|
||||
editing but are not emitted in generated subscriptions.
|
||||
id: replace-a-clients-external-links-and-external-subscriptions-sends-the-full-set-the-server-replaces-all-rows-disabled-rows-stay-saved-for-editing-but-are-not-emitted-in-generated-subscriptions
|
||||
- content: Reset the up/down counters for every client globally. Quotas and expiry
|
||||
are not affected. Triggers an Xray restart if any counter actually
|
||||
moved.
|
||||
@@ -307,10 +329,10 @@ _openapi:
|
||||
running inbound.
|
||||
id: delete-every-client-whose-traffic-quota-is-exhausted-used--total-when-reset-is-disabled-or-whose-expiry-has-passed-returns-the-deleted-count-and-triggers-an-xray-restart-when-any-client-was-on-a-running-inbound
|
||||
- content: Delete every client that is not attached to any inbound, along with its
|
||||
traffic record, IP log, and external links. Useful for clearing
|
||||
clients left unattached after their inbounds were removed. Returns the
|
||||
deleted count. Cannot be undone.
|
||||
id: delete-every-client-that-is-not-attached-to-any-inbound-along-with-its-traffic-record-ip-log-and-external-links-useful-for-clearing-clients-left-unattached-after-their-inbounds-were-removed-returns-the-deleted-count-cannot-be-undone
|
||||
traffic record, IP log, HWID devices, and external links. Useful for
|
||||
clearing clients left unattached after their inbounds were removed.
|
||||
Returns the deleted count. Cannot be undone.
|
||||
id: delete-every-client-that-is-not-attached-to-any-inbound-along-with-its-traffic-record-ip-log-hwid-devices-and-external-links-useful-for-clearing-clients-left-unattached-after-their-inbounds-were-removed-returns-the-deleted-count-cannot-be-undone
|
||||
- content: Return every client as a {client, inboundIds} array — the same shape
|
||||
/bulkCreate and /import accept — so the payload round-trips straight
|
||||
back through /import. Clients with no inbound attachment are included
|
||||
@@ -329,11 +351,15 @@ _openapi:
|
||||
addDays/addBytes may be negative. Clients with unlimited expiry
|
||||
(expiryTime=0) or unlimited traffic (totalGB=0) are skipped for the
|
||||
corresponding field — bulk extend never converts unlimited to limited.
|
||||
The optional flow directive sets the XTLS flow on every client: "none"
|
||||
A client that was auto-disabled solely because it was depleted
|
||||
(expired or over quota) is automatically re-enabled — locally and on
|
||||
its node — when the adjustment lifts it out of depletion; a
|
||||
manually-disabled or still-depleted client is left disabled. The
|
||||
optional flow directive sets the XTLS flow on every client: "none"
|
||||
clears it, "xtls-rprx-vision"/"xtls-rprx-vision-udp443" set it where
|
||||
the inbound supports it (omit or "" to leave it unchanged). Returns
|
||||
the adjusted count and per-email skip reasons.'
|
||||
id: shift-expiry-andor-traffic-quota-for-many-clients-in-one-call-adddaysaddbytes-may-be-negative-clients-with-unlimited-expiry-expirytime0-or-unlimited-traffic-totalgb0-are-skipped-for-the-corresponding-field--bulk-extend-never-converts-unlimited-to-limited-the-optional-flow-directive-sets-the-xtls-flow-on-every-client-none-clears-it-xtls-rprx-visionxtls-rprx-vision-udp443-set-it-where-the-inbound-supports-it-omit-or--to-leave-it-unchanged-returns-the-adjusted-count-and-per-email-skip-reasons
|
||||
id: shift-expiry-andor-traffic-quota-for-many-clients-in-one-call-adddaysaddbytes-may-be-negative-clients-with-unlimited-expiry-expirytime0-or-unlimited-traffic-totalgb0-are-skipped-for-the-corresponding-field--bulk-extend-never-converts-unlimited-to-limited-a-client-that-was-auto-disabled-solely-because-it-was-depleted-expired-or-over-quota-is-automatically-re-enabled--locally-and-on-its-node--when-the-adjustment-lifts-it-out-of-depletion-a-manually-disabled-or-still-depleted-client-is-left-disabled-the-optional-flow-directive-sets-the-xtls-flow-on-every-client-none-clears-it-xtls-rprx-visionxtls-rprx-vision-udp443-set-it-where-the-inbound-supports-it-omit-or--to-leave-it-unchanged-returns-the-adjusted-count-and-per-email-skip-reasons
|
||||
- content: Enable many clients in one call. Emails are grouped by inbound and
|
||||
applied with a single read-modify-write per inbound; the running Xray
|
||||
(local or remote node) is updated to add each user. Note that enabling
|
||||
@@ -417,6 +443,13 @@ _openapi:
|
||||
/bulkDel after filtering by group for that. Returns the count of
|
||||
clients whose label was cleared.
|
||||
id: remove-a-group-deletes-the-client_groups-row-and-clears-the-group-label-from-every-matching-client-both-clientsgroup_name-and-the-inbound-settings-json-the-clients-themselves-are-not-deleted--use-bulkdel-after-filtering-by-group-for-that-returns-the-count-of-clients-whose-label-was-cleared
|
||||
- content: Reset only the group-level traffic counter shown on the groups page.
|
||||
Snapshots the current up/down sum of the group's members as a baseline
|
||||
so the group total reads zero, while leaving each client's own
|
||||
counters (and their quotas) untouched. No Xray restart is triggered.
|
||||
Creates the client_groups row if the group exists only as a derived
|
||||
label.
|
||||
id: reset-only-the-group-level-traffic-counter-shown-on-the-groups-page-snapshots-the-current-updown-sum-of-the-groups-members-as-a-baseline-so-the-group-total-reads-zero-while-leaving-each-clients-own-counters-and-their-quotas-untouched-no-xray-restart-is-triggered-creates-the-client_groups-row-if-the-group-exists-only-as-a-derived-label
|
||||
- content: Zero out a single client’s up/down counters. Re-enables the client
|
||||
across every attached inbound and pushes the change to Xray (or the
|
||||
remote node) so depleted users can connect again immediately.
|
||||
@@ -429,6 +462,14 @@ _openapi:
|
||||
id: list-source-ips-that-have-connected-with-the-given-clients-credentials-returns-an-array-of-ip-timestamp-strings
|
||||
- content: Reset the recorded IP list for a client.
|
||||
id: reset-the-recorded-ip-list-for-a-client
|
||||
- content: List registered HWID devices for a client. Hashes are not exposed.
|
||||
id: list-registered-hwid-devices-for-a-client-hashes-are-not-exposed
|
||||
- content: Clear all registered HWID devices for a client so new devices can
|
||||
register again.
|
||||
id: clear-all-registered-hwid-devices-for-a-client-so-new-devices-can-register-again
|
||||
- content: Remove a single registered HWID device by its id, freeing one slot
|
||||
under the HWID limit.
|
||||
id: remove-a-single-registered-hwid-device-by-its-id-freeing-one-slot-under-the-hwid-limit
|
||||
- content: List the emails of currently connected clients (last seen within the
|
||||
heartbeat window), deduped across every node.
|
||||
id: list-the-emails-of-currently-connected-clients-last-seen-within-the-heartbeat-window-deduped-across-every-node
|
||||
@@ -466,14 +507,6 @@ _openapi:
|
||||
proxy. Protocols without a URL form (socks, http, mixed, wireguard,
|
||||
dokodemo, tunnel) contribute nothing.'
|
||||
id: return-every-url-for-one-client-across-all-attached-inbounds--the-same-strings-the-copy-url-button-copies-in-the-panel-ui-supported-protocols-vmess-vless-trojan-shadowsocks-hysteria-if-streamsettingsexternalproxy-is-set-returns-one-url-per-external-proxy-protocols-without-a-url-form-socks-http-mixed-wireguard-dokodemo-tunnel-contribute-nothing
|
||||
- content: List registered HWID devices for a client. Hashes are not exposed.
|
||||
id: list-registered-hwid-devices-for-a-client-hashes-are-not-exposed
|
||||
- content: Clear all registered HWID devices for a client so new devices can
|
||||
register again.
|
||||
id: clear-all-registered-hwid-devices-for-a-client-so-new-devices-can-register-again
|
||||
- content: Remove a single registered HWID device by its id, freeing one slot
|
||||
under the HWID limit.
|
||||
id: remove-a-single-registered-hwid-device-by-its-id-freeing-one-slot-under-the-hwid-limit
|
||||
contents:
|
||||
- content: >-
|
||||
Fields the server fills in when they are omitted — a valid value sent
|
||||
@@ -536,7 +569,7 @@ export default function Layout(props) {
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/clients/list","method":"get"},{"path":"/panel/api/clients/list/paged","method":"get"},{"path":"/panel/api/clients/get/{email}","method":"get"},{"path":"/panel/api/clients/add","method":"post"},{"path":"/panel/api/clients/update/{email}","method":"post"},{"path":"/panel/api/clients/del/{email}","method":"post"},{"path":"/panel/api/clients/{email}/attach","method":"post"},{"path":"/panel/api/clients/{email}/detach","method":"post"},{"path":"/panel/api/clients/{email}/externalLinks","method":"post"},{"path":"/panel/api/clients/resetAllTraffics","method":"post"},{"path":"/panel/api/clients/delDepleted","method":"post"},{"path":"/panel/api/clients/delOrphans","method":"post"},{"path":"/panel/api/clients/export","method":"get"},{"path":"/panel/api/clients/import","method":"post"},{"path":"/panel/api/clients/bulkAdjust","method":"post"},{"path":"/panel/api/clients/bulkEnable","method":"post"},{"path":"/panel/api/clients/bulkDisable","method":"post"},{"path":"/panel/api/clients/bulkDel","method":"post"},{"path":"/panel/api/clients/bulkCreate","method":"post"},{"path":"/panel/api/clients/groups/bulkAdd","method":"post"},{"path":"/panel/api/clients/groups/bulkRemove","method":"post"},{"path":"/panel/api/clients/bulkAttach","method":"post"},{"path":"/panel/api/clients/bulkDetach","method":"post"},{"path":"/panel/api/clients/bulkResetTraffic","method":"post"},{"path":"/panel/api/clients/groups","method":"get"},{"path":"/panel/api/clients/groups/{name}/emails","method":"get"},{"path":"/panel/api/clients/groups/create","method":"post"},{"path":"/panel/api/clients/groups/rename","method":"post"},{"path":"/panel/api/clients/groups/delete","method":"post"},{"path":"/panel/api/clients/resetTraffic/{email}","method":"post"},{"path":"/panel/api/clients/updateTraffic/{email}","method":"post"},{"path":"/panel/api/clients/ips/{email}","method":"post"},{"path":"/panel/api/clients/clearIps/{email}","method":"post"},{"path":"/panel/api/clients/onlines","method":"post"},{"path":"/panel/api/clients/onlinesByGuid","method":"post"},{"path":"/panel/api/clients/clientIpsByGuid","method":"post"},{"path":"/panel/api/clients/activeInbounds","method":"post"},{"path":"/panel/api/clients/lastOnline","method":"post"},{"path":"/panel/api/clients/traffic/{email}","method":"get"},{"path":"/panel/api/clients/subLinks/{subId}","method":"get"},{"path":"/panel/api/clients/links/{email}","method":"get"},{"path":"/panel/api/clients/hwids/{email}","method":"post"},{"path":"/panel/api/clients/hwids/{email}","method":"delete"},{"path":"/panel/api/clients/hwids/{email}/{id}","method":"delete"}]} showTitle />
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/clients/list","method":"get"},{"path":"/panel/api/clients/list/paged","method":"get"},{"path":"/panel/api/clients/get/{email}","method":"get"},{"path":"/panel/api/clients/get/tgId/{tgId}","method":"get"},{"path":"/panel/api/clients/add","method":"post"},{"path":"/panel/api/clients/update/{email}","method":"post"},{"path":"/panel/api/clients/del/{email}","method":"post"},{"path":"/panel/api/clients/{email}/attach","method":"post"},{"path":"/panel/api/clients/{email}/detach","method":"post"},{"path":"/panel/api/clients/{email}/externalLinks","method":"post"},{"path":"/panel/api/clients/resetAllTraffics","method":"post"},{"path":"/panel/api/clients/delDepleted","method":"post"},{"path":"/panel/api/clients/delOrphans","method":"post"},{"path":"/panel/api/clients/export","method":"get"},{"path":"/panel/api/clients/import","method":"post"},{"path":"/panel/api/clients/bulkAdjust","method":"post"},{"path":"/panel/api/clients/bulkEnable","method":"post"},{"path":"/panel/api/clients/bulkDisable","method":"post"},{"path":"/panel/api/clients/bulkDel","method":"post"},{"path":"/panel/api/clients/bulkCreate","method":"post"},{"path":"/panel/api/clients/groups/bulkAdd","method":"post"},{"path":"/panel/api/clients/groups/bulkRemove","method":"post"},{"path":"/panel/api/clients/bulkAttach","method":"post"},{"path":"/panel/api/clients/bulkDetach","method":"post"},{"path":"/panel/api/clients/bulkResetTraffic","method":"post"},{"path":"/panel/api/clients/groups","method":"get"},{"path":"/panel/api/clients/groups/{name}/emails","method":"get"},{"path":"/panel/api/clients/groups/create","method":"post"},{"path":"/panel/api/clients/groups/rename","method":"post"},{"path":"/panel/api/clients/groups/delete","method":"post"},{"path":"/panel/api/clients/groups/resetTraffic","method":"post"},{"path":"/panel/api/clients/resetTraffic/{email}","method":"post"},{"path":"/panel/api/clients/updateTraffic/{email}","method":"post"},{"path":"/panel/api/clients/ips/{email}","method":"post"},{"path":"/panel/api/clients/clearIps/{email}","method":"post"},{"path":"/panel/api/clients/hwids/{email}","method":"post"},{"path":"/panel/api/clients/hwids/{email}","method":"delete"},{"path":"/panel/api/clients/hwids/{email}/{id}","method":"delete"},{"path":"/panel/api/clients/onlines","method":"post"},{"path":"/panel/api/clients/onlinesByGuid","method":"post"},{"path":"/panel/api/clients/clientIpsByGuid","method":"post"},{"path":"/panel/api/clients/activeInbounds","method":"post"},{"path":"/panel/api/clients/lastOnline","method":"post"},{"path":"/panel/api/clients/traffic/{email}","method":"get"},{"path":"/panel/api/clients/subLinks/{subId}","method":"get"},{"path":"/panel/api/clients/links/{email}","method":"get"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -13,66 +13,65 @@ _openapi:
|
||||
sort order.
|
||||
url: '#list-every-host-across-all-inbounds-grouped-by-inbound-then-ordered-by-sort-order'
|
||||
- depth: 2
|
||||
title: Fetch a single host by ID.
|
||||
url: '#fetch-a-single-host-by-id'
|
||||
title: Fetch a single host group by Group ID.
|
||||
url: '#fetch-a-single-host-group-by-group-id'
|
||||
- depth: 2
|
||||
title: Fetch one inbound's hosts, ordered by sort order then id.
|
||||
url: '#fetch-one-inbounds-hosts-ordered-by-sort-order-then-id'
|
||||
title: Fetch one inbound's hosts, grouped by host group.
|
||||
url: '#fetch-one-inbounds-hosts-grouped-by-host-group'
|
||||
- depth: 2
|
||||
title: Distinct, sorted set of tags used across all hosts.
|
||||
url: '#distinct-sorted-set-of-tags-used-across-all-hosts'
|
||||
- depth: 2
|
||||
title: Create a host on an inbound. inboundId and remark are required; security
|
||||
defaults to "same" (inherit the inbound).
|
||||
url: '#create-a-host-on-an-inbound-inboundid-and-remark-are-required-security-defaults-to-same-inherit-the-inbound'
|
||||
title: Create a host group on inbounds.
|
||||
url: '#create-a-host-group-on-inbounds'
|
||||
- depth: 2
|
||||
title: Replace a host’s content. The inbound and sort order are immutable here
|
||||
(use /reorder for ordering).
|
||||
url: '#replace-a-hosts-content-the-inbound-and-sort-order-are-immutable-here-use-reorder-for-ordering'
|
||||
title: Replace a host group’s content.
|
||||
url: '#replace-a-host-groups-content'
|
||||
- depth: 2
|
||||
title: Delete a host.
|
||||
url: '#delete-a-host'
|
||||
title: Delete a host group.
|
||||
url: '#delete-a-host-group'
|
||||
- depth: 2
|
||||
title: Enable or disable a single host (disabled hosts are skipped in
|
||||
subscriptions).
|
||||
url: '#enable-or-disable-a-single-host-disabled-hosts-are-skipped-in-subscriptions'
|
||||
title: Enable or disable a host group.
|
||||
url: '#enable-or-disable-a-host-group'
|
||||
- depth: 2
|
||||
title: Set host sort order by the position of each id in the array.
|
||||
url: '#set-host-sort-order-by-the-position-of-each-id-in-the-array'
|
||||
title: Set host group sort order by the position of each groupId in the array.
|
||||
url: '#set-host-group-sort-order-by-the-position-of-each-groupid-in-the-array'
|
||||
- depth: 2
|
||||
title: Enable or disable many hosts in one call.
|
||||
url: '#enable-or-disable-many-hosts-in-one-call'
|
||||
title: Add a host group to inbounds (same as /add).
|
||||
url: '#add-a-host-group-to-inbounds-same-as-add'
|
||||
- depth: 2
|
||||
title: Delete many hosts in one call.
|
||||
url: '#delete-many-hosts-in-one-call'
|
||||
title: Enable or disable many host groups in one call.
|
||||
url: '#enable-or-disable-many-host-groups-in-one-call'
|
||||
- depth: 2
|
||||
title: Delete many host groups in one call.
|
||||
url: '#delete-many-host-groups-in-one-call'
|
||||
structuredData:
|
||||
headings:
|
||||
- content: List every host across all inbounds, grouped by inbound then ordered by
|
||||
sort order.
|
||||
id: list-every-host-across-all-inbounds-grouped-by-inbound-then-ordered-by-sort-order
|
||||
- content: Fetch a single host by ID.
|
||||
id: fetch-a-single-host-by-id
|
||||
- content: Fetch one inbound's hosts, ordered by sort order then id.
|
||||
id: fetch-one-inbounds-hosts-ordered-by-sort-order-then-id
|
||||
- content: Fetch a single host group by Group ID.
|
||||
id: fetch-a-single-host-group-by-group-id
|
||||
- content: Fetch one inbound's hosts, grouped by host group.
|
||||
id: fetch-one-inbounds-hosts-grouped-by-host-group
|
||||
- content: Distinct, sorted set of tags used across all hosts.
|
||||
id: distinct-sorted-set-of-tags-used-across-all-hosts
|
||||
- content: Create a host on an inbound. inboundId and remark are required;
|
||||
security defaults to "same" (inherit the inbound).
|
||||
id: create-a-host-on-an-inbound-inboundid-and-remark-are-required-security-defaults-to-same-inherit-the-inbound
|
||||
- content: Replace a host’s content. The inbound and sort order are immutable here
|
||||
(use /reorder for ordering).
|
||||
id: replace-a-hosts-content-the-inbound-and-sort-order-are-immutable-here-use-reorder-for-ordering
|
||||
- content: Delete a host.
|
||||
id: delete-a-host
|
||||
- content: Enable or disable a single host (disabled hosts are skipped in
|
||||
subscriptions).
|
||||
id: enable-or-disable-a-single-host-disabled-hosts-are-skipped-in-subscriptions
|
||||
- content: Set host sort order by the position of each id in the array.
|
||||
id: set-host-sort-order-by-the-position-of-each-id-in-the-array
|
||||
- content: Enable or disable many hosts in one call.
|
||||
id: enable-or-disable-many-hosts-in-one-call
|
||||
- content: Delete many hosts in one call.
|
||||
id: delete-many-hosts-in-one-call
|
||||
- content: Create a host group on inbounds.
|
||||
id: create-a-host-group-on-inbounds
|
||||
- content: Replace a host group’s content.
|
||||
id: replace-a-host-groups-content
|
||||
- content: Delete a host group.
|
||||
id: delete-a-host-group
|
||||
- content: Enable or disable a host group.
|
||||
id: enable-or-disable-a-host-group
|
||||
- content: Set host group sort order by the position of each groupId in the array.
|
||||
id: set-host-group-sort-order-by-the-position-of-each-groupid-in-the-array
|
||||
- content: Add a host group to inbounds (same as /add).
|
||||
id: add-a-host-group-to-inbounds-same-as-add
|
||||
- content: Enable or disable many host groups in one call.
|
||||
id: enable-or-disable-many-host-groups-in-one-call
|
||||
- content: Delete many host groups in one call.
|
||||
id: delete-many-host-groups-in-one-call
|
||||
contents: []
|
||||
---
|
||||
|
||||
@@ -85,7 +84,7 @@ export default function Layout(props) {
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/hosts/list","method":"get"},{"path":"/panel/api/hosts/get/{id}","method":"get"},{"path":"/panel/api/hosts/byInbound/{inboundId}","method":"get"},{"path":"/panel/api/hosts/tags","method":"get"},{"path":"/panel/api/hosts/add","method":"post"},{"path":"/panel/api/hosts/update/{id}","method":"post"},{"path":"/panel/api/hosts/del/{id}","method":"post"},{"path":"/panel/api/hosts/setEnable/{id}","method":"post"},{"path":"/panel/api/hosts/reorder","method":"post"},{"path":"/panel/api/hosts/bulk/setEnable","method":"post"},{"path":"/panel/api/hosts/bulk/del","method":"post"}]} showTitle />
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/hosts/list","method":"get"},{"path":"/panel/api/hosts/get/{groupId}","method":"get"},{"path":"/panel/api/hosts/byInbound/{inboundId}","method":"get"},{"path":"/panel/api/hosts/tags","method":"get"},{"path":"/panel/api/hosts/add","method":"post"},{"path":"/panel/api/hosts/update/{groupId}","method":"post"},{"path":"/panel/api/hosts/del/{groupId}","method":"post"},{"path":"/panel/api/hosts/setEnable/{groupId}","method":"post"},{"path":"/panel/api/hosts/reorder","method":"post"},{"path":"/panel/api/hosts/bulk/add","method":"post"},{"path":"/panel/api/hosts/bulk/setEnable","method":"post"},{"path":"/panel/api/hosts/bulk/del","method":"post"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -33,6 +33,15 @@ _openapi:
|
||||
clientStats so the payload stays small even on panels with thousands of
|
||||
clients.
|
||||
url: '#lightweight-picker-projection-of-the-authenticated-users-inbounds-returns-id-remark-tag-protocol-port-a-server-computed-tlsflowcapable-flag-true-for-vless-on-tcp-with-tls-or-reality-or-on-xhttp-with-vless-encryption--vlessenc-enabled-and-ssmethod-the-shadowsocks-cipher-empty-for-non-shadowsocks-inbounds--used-by-the-client-ui-to-generate-a-valid-shadowsocks-2022-psk-use-this-for-dropdowns-and-attach-pickers--it-skips-settings-streamsettings-and-clientstats-so-the-payload-stays-small-even-on-panels-with-thousands-of-clients'
|
||||
- depth: 2
|
||||
title: Return every protocol URL (vless://, vmess://, trojan://, ss://,
|
||||
hysteria://, mtproto) across all inbounds and all of their clients.
|
||||
Links are rendered through the subscription engine, so the configured
|
||||
remark template (name-only display part) is applied per client — the
|
||||
same output the client info/QR pages use. Protocols without a URL form
|
||||
(socks, http, mixed, wireguard, dokodemo, tunnel) contribute nothing.
|
||||
Used by the panel’s "Export all inbound links" action.
|
||||
url: '#return-every-protocol-url-vless-vmess-trojan-ss-hysteria-mtproto-across-all-inbounds-and-all-of-their-clients-links-are-rendered-through-the-subscription-engine-so-the-configured-remark-template-name-only-display-part-is-applied-per-client--the-same-output-the-client-infoqr-pages-use-protocols-without-a-url-form-socks-http-mixed-wireguard-dokodemo-tunnel-contribute-nothing-used-by-the-panels-export-all-inbound-links-action'
|
||||
- depth: 2
|
||||
title: Fetch a single inbound by numeric ID.
|
||||
url: '#fetch-a-single-inbound-by-numeric-id'
|
||||
@@ -59,6 +68,10 @@ _openapi:
|
||||
title: Toggle only the enable flag without serialising the whole settings JSON.
|
||||
Recommended for UI switches on large inbounds.
|
||||
url: '#toggle-only-the-enable-flag-without-serialising-the-whole-settings-json-recommended-for-ui-switches-on-large-inbounds'
|
||||
- depth: 2
|
||||
title: Set only the subscription sort order. Reads the stored inbound, so a
|
||||
reorder cannot carry a stale client list over a concurrent edit.
|
||||
url: '#set-only-the-subscription-sort-order-reads-the-stored-inbound-so-a-reorder-cannot-carry-a-stale-client-list-over-a-concurrent-edit'
|
||||
- depth: 2
|
||||
title: Zero out upload + download counters for a single inbound. Does not touch
|
||||
per-client counters.
|
||||
@@ -94,10 +107,6 @@ _openapi:
|
||||
title: Replace the entire fallback list for a master inbound. Body is JSON.
|
||||
Triggers an Xray restart.
|
||||
url: '#replace-the-entire-fallback-list-for-a-master-inbound-body-is-json-triggers-an-xray-restart'
|
||||
- depth: 2
|
||||
title: Set only the subscription sort order. Reads the stored inbound, so a
|
||||
reorder cannot carry a stale client list over a concurrent edit.
|
||||
url: '#set-only-the-subscription-sort-order-reads-the-stored-inbound-so-a-reorder-cannot-carry-a-stale-client-list-over-a-concurrent-edit'
|
||||
structuredData:
|
||||
headings:
|
||||
- content: List every inbound owned by the authenticated user, including each
|
||||
@@ -121,6 +130,14 @@ _openapi:
|
||||
clientStats so the payload stays small even on panels with thousands
|
||||
of clients.
|
||||
id: lightweight-picker-projection-of-the-authenticated-users-inbounds-returns-id-remark-tag-protocol-port-a-server-computed-tlsflowcapable-flag-true-for-vless-on-tcp-with-tls-or-reality-or-on-xhttp-with-vless-encryption--vlessenc-enabled-and-ssmethod-the-shadowsocks-cipher-empty-for-non-shadowsocks-inbounds--used-by-the-client-ui-to-generate-a-valid-shadowsocks-2022-psk-use-this-for-dropdowns-and-attach-pickers--it-skips-settings-streamsettings-and-clientstats-so-the-payload-stays-small-even-on-panels-with-thousands-of-clients
|
||||
- content: Return every protocol URL (vless://, vmess://, trojan://, ss://,
|
||||
hysteria://, mtproto) across all inbounds and all of their clients.
|
||||
Links are rendered through the subscription engine, so the configured
|
||||
remark template (name-only display part) is applied per client — the
|
||||
same output the client info/QR pages use. Protocols without a URL form
|
||||
(socks, http, mixed, wireguard, dokodemo, tunnel) contribute nothing.
|
||||
Used by the panel’s "Export all inbound links" action.
|
||||
id: return-every-protocol-url-vless-vmess-trojan-ss-hysteria-mtproto-across-all-inbounds-and-all-of-their-clients-links-are-rendered-through-the-subscription-engine-so-the-configured-remark-template-name-only-display-part-is-applied-per-client--the-same-output-the-client-infoqr-pages-use-protocols-without-a-url-form-socks-http-mixed-wireguard-dokodemo-tunnel-contribute-nothing-used-by-the-panels-export-all-inbound-links-action
|
||||
- content: Fetch a single inbound by numeric ID.
|
||||
id: fetch-a-single-inbound-by-numeric-id
|
||||
- content: Create a new inbound. Send the full inbound payload (protocol, port,
|
||||
@@ -141,6 +158,9 @@ _openapi:
|
||||
- content: Toggle only the enable flag without serialising the whole settings
|
||||
JSON. Recommended for UI switches on large inbounds.
|
||||
id: toggle-only-the-enable-flag-without-serialising-the-whole-settings-json-recommended-for-ui-switches-on-large-inbounds
|
||||
- content: Set only the subscription sort order. Reads the stored inbound, so a
|
||||
reorder cannot carry a stale client list over a concurrent edit.
|
||||
id: set-only-the-subscription-sort-order-reads-the-stored-inbound-so-a-reorder-cannot-carry-a-stale-client-list-over-a-concurrent-edit
|
||||
- content: Zero out upload + download counters for a single inbound. Does not
|
||||
touch per-client counters.
|
||||
id: zero-out-upload--download-counters-for-a-single-inbound-does-not-touch-per-client-counters
|
||||
@@ -169,9 +189,6 @@ _openapi:
|
||||
- content: Replace the entire fallback list for a master inbound. Body is JSON.
|
||||
Triggers an Xray restart.
|
||||
id: replace-the-entire-fallback-list-for-a-master-inbound-body-is-json-triggers-an-xray-restart
|
||||
- content: Set only the subscription sort order. Reads the stored inbound, so a
|
||||
reorder cannot carry a stale client list over a concurrent edit.
|
||||
id: set-only-the-subscription-sort-order-reads-the-stored-inbound-so-a-reorder-cannot-carry-a-stale-client-list-over-a-concurrent-edit
|
||||
contents: []
|
||||
---
|
||||
|
||||
@@ -184,7 +201,7 @@ export default function Layout(props) {
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/inbounds/list","method":"get"},{"path":"/panel/api/inbounds/list/slim","method":"get"},{"path":"/panel/api/inbounds/options","method":"get"},{"path":"/panel/api/inbounds/get/{id}","method":"get"},{"path":"/panel/api/inbounds/add","method":"post"},{"path":"/panel/api/inbounds/del/{id}","method":"post"},{"path":"/panel/api/inbounds/bulkDel","method":"post"},{"path":"/panel/api/inbounds/update/{id}","method":"post"},{"path":"/panel/api/inbounds/setEnable/{id}","method":"post"},{"path":"/panel/api/inbounds/{id}/resetTraffic","method":"post"},{"path":"/panel/api/inbounds/{id}/delAllClients","method":"post"},{"path":"/panel/api/inbounds/resetAllTraffics","method":"post"},{"path":"/panel/api/inbounds/import","method":"post"},{"path":"/panel/api/inbounds/pushClientTraffics","method":"post"},{"path":"/panel/api/inbounds/{id}/fallbacks","method":"get"},{"path":"/panel/api/inbounds/{id}/fallbacks","method":"post"},{"path":"/panel/api/inbounds/{id}/subSortIndex","method":"post"}]} showTitle />
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/inbounds/list","method":"get"},{"path":"/panel/api/inbounds/list/slim","method":"get"},{"path":"/panel/api/inbounds/options","method":"get"},{"path":"/panel/api/inbounds/allLinks","method":"get"},{"path":"/panel/api/inbounds/get/{id}","method":"get"},{"path":"/panel/api/inbounds/add","method":"post"},{"path":"/panel/api/inbounds/del/{id}","method":"post"},{"path":"/panel/api/inbounds/bulkDel","method":"post"},{"path":"/panel/api/inbounds/update/{id}","method":"post"},{"path":"/panel/api/inbounds/setEnable/{id}","method":"post"},{"path":"/panel/api/inbounds/{id}/subSortIndex","method":"post"},{"path":"/panel/api/inbounds/{id}/resetTraffic","method":"post"},{"path":"/panel/api/inbounds/{id}/delAllClients","method":"post"},{"path":"/panel/api/inbounds/resetAllTraffics","method":"post"},{"path":"/panel/api/inbounds/import","method":"post"},{"path":"/panel/api/inbounds/pushClientTraffics","method":"post"},{"path":"/panel/api/inbounds/{id}/fallbacks","method":"get"},{"path":"/panel/api/inbounds/{id}/fallbacks","method":"post"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
"settings",
|
||||
"xray-settings",
|
||||
"subscription-server",
|
||||
"subscription-balancers",
|
||||
"hosts",
|
||||
"nodes",
|
||||
"backup",
|
||||
|
||||
@@ -22,6 +22,11 @@ _openapi:
|
||||
CA (from nodes/mtls/ca). An empty caCert disables it. A non-empty value
|
||||
must be a PEM certificate. Applied on the next panel restart.
|
||||
url: '#set-the-ca-certificate-this-panel-trusts-for-incoming-node-api-client-certificates-this-panel-acting-as-a-node-paste-the-managing-panels-ca-from-nodesmtlsca-an-empty-cacert-disables-it-a-non-empty-value-must-be-a-pem-certificate-applied-on-the-next-panel-restart'
|
||||
- depth: 2
|
||||
title: Validate the stored master mTLS client credential and invalidate cached
|
||||
transports. Each transport closes its old idle pool and rebuilds with
|
||||
the rotated certificate before its next request.
|
||||
url: '#validate-the-stored-master-mtls-client-credential-and-invalidate-cached-transports-each-transport-closes-its-old-idle-pool-and-rebuilds-with-the-rotated-certificate-before-its-next-request'
|
||||
- depth: 2
|
||||
title: Fetch a single node by ID.
|
||||
url: '#fetch-a-single-node-by-id'
|
||||
@@ -32,12 +37,15 @@ _openapi:
|
||||
panel.
|
||||
url: '#fetch-a-nodes-own-web-tls-certificatekey-file-paths-proxied-to-the-node-used-by-the-inbound-forms-set-cert-from-panel-so-a-node-assigned-inbound-gets-paths-that-exist-on-the-node-not-the-central-panel'
|
||||
- depth: 2
|
||||
title: Register a new remote node. Provide its URL, apiToken, and optional
|
||||
remark / allowPrivateAddress flag.
|
||||
url: '#register-a-new-remote-node-provide-its-url-apitoken-and-optional-remark--allowprivateaddress-flag'
|
||||
title: Register a new remote node. Provide its URL, write-only apiToken, and
|
||||
optional remark / allowPrivateAddress flag. Responses expose hasApiToken
|
||||
only.
|
||||
url: '#register-a-new-remote-node-provide-its-url-write-only-apitoken-and-optional-remark--allowprivateaddress-flag-responses-expose-hasapitoken-only'
|
||||
- depth: 2
|
||||
title: Replace a node’s connection details. Same body shape as /add.
|
||||
url: '#replace-a-nodes-connection-details-same-body-shape-as-add'
|
||||
title: 'Replace a node’s connection details. apiToken is write-only: omit it or
|
||||
send an empty string to keep the stored token; set clearApiToken=true to
|
||||
clear it.'
|
||||
url: '#replace-a-nodes-connection-details-apitoken-is-write-only-omit-it-or-send-an-empty-string-to-keep-the-stored-token-set-clearapitokentrue-to-clear-it'
|
||||
- depth: 2
|
||||
title: Delete a node. Inbounds bound to it are not auto-migrated.
|
||||
url: '#delete-a-node-inbounds-bound-to-it-are-not-auto-migrated'
|
||||
@@ -72,11 +80,6 @@ _openapi:
|
||||
title: Aggregated metric history for a node — same shape as /server/history,
|
||||
scoped to one node.
|
||||
url: '#aggregated-metric-history-for-a-node--same-shape-as-serverhistory-scoped-to-one-node'
|
||||
- depth: 2
|
||||
title: Validate the stored master mTLS client credential and invalidate cached
|
||||
transports. Each transport closes its old idle pool and rebuilds with
|
||||
the rotated certificate before its next request.
|
||||
url: '#validate-the-stored-master-mtls-client-credential-and-invalidate-cached-transports-each-transport-closes-its-old-idle-pool-and-rebuilds-with-the-rotated-certificate-before-its-next-request'
|
||||
structuredData:
|
||||
headings:
|
||||
- content: List every configured node with its connection details, health, and
|
||||
@@ -91,6 +94,10 @@ _openapi:
|
||||
CA (from nodes/mtls/ca). An empty caCert disables it. A non-empty
|
||||
value must be a PEM certificate. Applied on the next panel restart.
|
||||
id: set-the-ca-certificate-this-panel-trusts-for-incoming-node-api-client-certificates-this-panel-acting-as-a-node-paste-the-managing-panels-ca-from-nodesmtlsca-an-empty-cacert-disables-it-a-non-empty-value-must-be-a-pem-certificate-applied-on-the-next-panel-restart
|
||||
- content: Validate the stored master mTLS client credential and invalidate cached
|
||||
transports. Each transport closes its old idle pool and rebuilds with
|
||||
the rotated certificate before its next request.
|
||||
id: validate-the-stored-master-mtls-client-credential-and-invalidate-cached-transports-each-transport-closes-its-old-idle-pool-and-rebuilds-with-the-rotated-certificate-before-its-next-request
|
||||
- content: Fetch a single node by ID.
|
||||
id: fetch-a-single-node-by-id
|
||||
- content: Fetch a node's own web TLS certificate/key file paths (proxied to the
|
||||
@@ -98,11 +105,14 @@ _openapi:
|
||||
node-assigned inbound gets paths that exist on the node, not the
|
||||
central panel.
|
||||
id: fetch-a-nodes-own-web-tls-certificatekey-file-paths-proxied-to-the-node-used-by-the-inbound-forms-set-cert-from-panel-so-a-node-assigned-inbound-gets-paths-that-exist-on-the-node-not-the-central-panel
|
||||
- content: Register a new remote node. Provide its URL, apiToken, and optional
|
||||
remark / allowPrivateAddress flag.
|
||||
id: register-a-new-remote-node-provide-its-url-apitoken-and-optional-remark--allowprivateaddress-flag
|
||||
- content: Replace a node’s connection details. Same body shape as /add.
|
||||
id: replace-a-nodes-connection-details-same-body-shape-as-add
|
||||
- content: Register a new remote node. Provide its URL, write-only apiToken, and
|
||||
optional remark / allowPrivateAddress flag. Responses expose
|
||||
hasApiToken only.
|
||||
id: register-a-new-remote-node-provide-its-url-write-only-apitoken-and-optional-remark--allowprivateaddress-flag-responses-expose-hasapitoken-only
|
||||
- content: 'Replace a node’s connection details. apiToken is write-only: omit it
|
||||
or send an empty string to keep the stored token; set
|
||||
clearApiToken=true to clear it.'
|
||||
id: replace-a-nodes-connection-details-apitoken-is-write-only-omit-it-or-send-an-empty-string-to-keep-the-stored-token-set-clearapitokentrue-to-clear-it
|
||||
- content: Delete a node. Inbounds bound to it are not auto-migrated.
|
||||
id: delete-a-node-inbounds-bound-to-it-are-not-auto-migrated
|
||||
- content: Pause or resume traffic sync with this node.
|
||||
@@ -129,10 +139,6 @@ _openapi:
|
||||
- content: Aggregated metric history for a node — same shape as /server/history,
|
||||
scoped to one node.
|
||||
id: aggregated-metric-history-for-a-node--same-shape-as-serverhistory-scoped-to-one-node
|
||||
- content: Validate the stored master mTLS client credential and invalidate cached
|
||||
transports. Each transport closes its old idle pool and rebuilds with
|
||||
the rotated certificate before its next request.
|
||||
id: validate-the-stored-master-mtls-client-credential-and-invalidate-cached-transports-each-transport-closes-its-old-idle-pool-and-rebuilds-with-the-rotated-certificate-before-its-next-request
|
||||
contents: []
|
||||
---
|
||||
|
||||
@@ -145,7 +151,7 @@ export default function Layout(props) {
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/nodes/list","method":"get"},{"path":"/panel/api/nodes/mtls/ca","method":"post"},{"path":"/panel/api/nodes/mtls/trustCA","method":"post"},{"path":"/panel/api/nodes/get/{id}","method":"get"},{"path":"/panel/api/nodes/webCert/{id}","method":"get"},{"path":"/panel/api/nodes/add","method":"post"},{"path":"/panel/api/nodes/update/{id}","method":"post"},{"path":"/panel/api/nodes/del/{id}","method":"post"},{"path":"/panel/api/nodes/setEnable/{id}","method":"post"},{"path":"/panel/api/nodes/test","method":"post"},{"path":"/panel/api/nodes/certFingerprint","method":"post"},{"path":"/panel/api/nodes/inbounds","method":"post"},{"path":"/panel/api/nodes/probe/{id}","method":"post"},{"path":"/panel/api/nodes/updatePanel","method":"post"},{"path":"/panel/api/nodes/history/{id}/{metric}/{bucket}","method":"get"},{"path":"/panel/api/nodes/mtls/reloadClient","method":"post"}]} showTitle />
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/nodes/list","method":"get"},{"path":"/panel/api/nodes/mtls/ca","method":"post"},{"path":"/panel/api/nodes/mtls/trustCA","method":"post"},{"path":"/panel/api/nodes/mtls/reloadClient","method":"post"},{"path":"/panel/api/nodes/get/{id}","method":"get"},{"path":"/panel/api/nodes/webCert/{id}","method":"get"},{"path":"/panel/api/nodes/add","method":"post"},{"path":"/panel/api/nodes/update/{id}","method":"post"},{"path":"/panel/api/nodes/del/{id}","method":"post"},{"path":"/panel/api/nodes/setEnable/{id}","method":"post"},{"path":"/panel/api/nodes/test","method":"post"},{"path":"/panel/api/nodes/certFingerprint","method":"post"},{"path":"/panel/api/nodes/inbounds","method":"post"},{"path":"/panel/api/nodes/probe/{id}","method":"post"},{"path":"/panel/api/nodes/updatePanel","method":"post"},{"path":"/panel/api/nodes/history/{id}/{metric}/{bucket}","method":"get"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,12 @@ _openapi:
|
||||
preload:
|
||||
- ./public/openapi.json
|
||||
toc:
|
||||
- depth: 2
|
||||
title: Serve this API description as an OpenAPI 3 document — the same file that
|
||||
powers the API Docs page. Requires a session or Bearer token like the
|
||||
rest of /panel/api. Useful for generating clients or importing into API
|
||||
tooling.
|
||||
url: '#serve-this-api-description-as-an-openapi-3-document--the-same-file-that-powers-the-api-docs-page-requires-a-session-or-bearer-token-like-the-rest-of-panelapi-useful-for-generating-clients-or-importing-into-api-tooling'
|
||||
- depth: 2
|
||||
title: 'Real-time machine snapshot: CPU, memory, swap, disk, network IO, load
|
||||
averages, open connections, Xray state. Cached and refreshed every 2
|
||||
@@ -49,12 +55,19 @@ _openapi:
|
||||
- depth: 2
|
||||
title: Check whether a newer 3x-ui release is available on GitHub.
|
||||
url: '#check-whether-a-newer-3x-ui-release-is-available-on-github'
|
||||
- depth: 2
|
||||
title: Report the outcome of the most recently launched panel self-update (see
|
||||
POST updatePanel). Compare the returned runId against the one
|
||||
updatePanel returned to tell this run apart from a stale result.
|
||||
url: '#report-the-outcome-of-the-most-recently-launched-panel-self-update-see-post-updatepanel-compare-the-returned-runid-against-the-one-updatepanel-returned-to-tell-this-run-apart-from-a-stale-result'
|
||||
- depth: 2
|
||||
title: Return the assembled Xray config that’s currently running on this host.
|
||||
url: '#return-the-assembled-xray-config-thats-currently-running-on-this-host'
|
||||
- depth: 2
|
||||
title: Stream the SQLite database file as an attachment. Use as a manual backup.
|
||||
url: '#stream-the-sqlite-database-file-as-an-attachment-use-as-a-manual-backup'
|
||||
title: 'Stream a full database backup as an attachment: the SQLite .db file on
|
||||
SQLite panels, or a pg_dump custom-format archive (.dump) on PostgreSQL
|
||||
panels. Use as a manual backup.'
|
||||
url: '#stream-a-full-database-backup-as-an-attachment-the-sqlite-db-file-on-sqlite-panels-or-a-pg_dump-custom-format-archive-dump-on-postgresql-panels-use-as-a-manual-backup'
|
||||
- depth: 2
|
||||
title: 'Stream a cross-engine migration file as an attachment: a .dump (SQL
|
||||
text) on SQLite, or a .db SQLite database built from the live data on
|
||||
@@ -123,9 +136,12 @@ _openapi:
|
||||
title: Return the last N lines of the Xray process log.
|
||||
url: '#return-the-last-n-lines-of-the-xray-process-log'
|
||||
- depth: 2
|
||||
title: Restore the panel DB from an uploaded SQLite file (multipart form, field
|
||||
name "db"). The panel restarts after restore. Destructive.
|
||||
url: '#restore-the-panel-db-from-an-uploaded-sqlite-file-multipart-form-field-name-db-the-panel-restarts-after-restore-destructive'
|
||||
title: Restore the panel DB from an uploaded backup (multipart form, field name
|
||||
"db"). SQLite panels accept a SQLite database (.db) or a SQLite
|
||||
migration dump (.dump); PostgreSQL panels accept a pg_dump archive
|
||||
(.dump), a SQLite database (.db), or a SQLite migration dump. The panel
|
||||
restarts after restore. Destructive.
|
||||
url: '#restore-the-panel-db-from-an-uploaded-backup-multipart-form-field-name-db-sqlite-panels-accept-a-sqlite-database-db-or-a-sqlite-migration-dump-dump-postgresql-panels-accept-a-pg_dump-archive-dump-a-sqlite-database-db-or-a-sqlite-migration-dump-the-panel-restarts-after-restore-destructive'
|
||||
- depth: 2
|
||||
title: Generate a new ECH (Encrypted Client Hello) keypair and config list for
|
||||
the given SNI.
|
||||
@@ -139,6 +155,20 @@ _openapi:
|
||||
title: Run `xray tls ping` against a remote server and return its live
|
||||
leaf-certificate SHA-256 hash(es) for pinning (pinnedPeerCertSha256).
|
||||
url: '#run-xray-tls-ping-against-a-remote-server-and-return-its-live-leaf-certificate-sha-256-hashes-for-pinning-pinnedpeercertsha256'
|
||||
- depth: 2
|
||||
title: Run a live TLS 1.3 probe against a candidate REALITY target and return a
|
||||
feasibility verdict (TLS 1.3 + h2 + X25519 + trusted certificate) plus
|
||||
the certificate SAN DNS names. A target on a private/loopback address is
|
||||
reported with privateTarget=true and probed only when allowPrivate is
|
||||
set.
|
||||
url: '#run-a-live-tls-13-probe-against-a-candidate-reality-target-and-return-a-feasibility-verdict-tls-13--h2--x25519--trusted-certificate-plus-the-certificate-san-dns-names-a-target-on-a-privateloopback-address-is-reported-with-privatetargettrue-and-probed-only-when-allowprivate-is-set'
|
||||
- depth: 2
|
||||
title: Probe/discover REALITY targets and return each verdict ranked by
|
||||
feasibility then latency. Each comma-separated token may be a domain
|
||||
(validated with SNI), a bare IP, or a CIDR range (discovered without SNI
|
||||
by reading the certificate domain). When empty, a built-in seed list is
|
||||
probed.
|
||||
url: '#probediscover-reality-targets-and-return-each-verdict-ranked-by-feasibility-then-latency-each-comma-separated-token-may-be-a-domain-validated-with-sni-a-bare-ip-or-a-cidr-range-discovered-without-sni-by-reading-the-certificate-domain-when-empty-a-built-in-seed-list-is-probed'
|
||||
- depth: 2
|
||||
title: Fetch the fully aggregated inbound_client_ips database table. Used by
|
||||
nodes to sync recently active IPs across the cluster.
|
||||
@@ -149,6 +179,11 @@ _openapi:
|
||||
url: '#submit-a-list-of-recently-active-ip-timestamps-the-panel-merges-them-with-the-existing-database-to-maintain-a-unified-global-ip-limit-view'
|
||||
structuredData:
|
||||
headings:
|
||||
- content: Serve this API description as an OpenAPI 3 document — the same file
|
||||
that powers the API Docs page. Requires a session or Bearer token like
|
||||
the rest of /panel/api. Useful for generating clients or importing
|
||||
into API tooling.
|
||||
id: serve-this-api-description-as-an-openapi-3-document--the-same-file-that-powers-the-api-docs-page-requires-a-session-or-bearer-token-like-the-rest-of-panelapi-useful-for-generating-clients-or-importing-into-api-tooling
|
||||
- content: 'Real-time machine snapshot: CPU, memory, swap, disk, network IO, load
|
||||
averages, open connections, Xray state. Cached and refreshed every 2
|
||||
seconds in the background.'
|
||||
@@ -181,11 +216,16 @@ _openapi:
|
||||
id: list-xray-binary-versions-available-for-install-on-this-host
|
||||
- content: Check whether a newer 3x-ui release is available on GitHub.
|
||||
id: check-whether-a-newer-3x-ui-release-is-available-on-github
|
||||
- content: Report the outcome of the most recently launched panel self-update (see
|
||||
POST updatePanel). Compare the returned runId against the one
|
||||
updatePanel returned to tell this run apart from a stale result.
|
||||
id: report-the-outcome-of-the-most-recently-launched-panel-self-update-see-post-updatepanel-compare-the-returned-runid-against-the-one-updatepanel-returned-to-tell-this-run-apart-from-a-stale-result
|
||||
- content: Return the assembled Xray config that’s currently running on this host.
|
||||
id: return-the-assembled-xray-config-thats-currently-running-on-this-host
|
||||
- content: Stream the SQLite database file as an attachment. Use as a manual
|
||||
backup.
|
||||
id: stream-the-sqlite-database-file-as-an-attachment-use-as-a-manual-backup
|
||||
- content: 'Stream a full database backup as an attachment: the SQLite .db file on
|
||||
SQLite panels, or a pg_dump custom-format archive (.dump) on
|
||||
PostgreSQL panels. Use as a manual backup.'
|
||||
id: stream-a-full-database-backup-as-an-attachment-the-sqlite-db-file-on-sqlite-panels-or-a-pg_dump-custom-format-archive-dump-on-postgresql-panels-use-as-a-manual-backup
|
||||
- content: 'Stream a cross-engine migration file as an attachment: a .dump (SQL
|
||||
text) on SQLite, or a .db SQLite database built from the live data on
|
||||
PostgreSQL.'
|
||||
@@ -236,9 +276,12 @@ _openapi:
|
||||
id: return-the-last-n-lines-of-the-panels-own-log
|
||||
- content: Return the last N lines of the Xray process log.
|
||||
id: return-the-last-n-lines-of-the-xray-process-log
|
||||
- content: Restore the panel DB from an uploaded SQLite file (multipart form,
|
||||
field name "db"). The panel restarts after restore. Destructive.
|
||||
id: restore-the-panel-db-from-an-uploaded-sqlite-file-multipart-form-field-name-db-the-panel-restarts-after-restore-destructive
|
||||
- content: Restore the panel DB from an uploaded backup (multipart form, field
|
||||
name "db"). SQLite panels accept a SQLite database (.db) or a SQLite
|
||||
migration dump (.dump); PostgreSQL panels accept a pg_dump archive
|
||||
(.dump), a SQLite database (.db), or a SQLite migration dump. The
|
||||
panel restarts after restore. Destructive.
|
||||
id: restore-the-panel-db-from-an-uploaded-backup-multipart-form-field-name-db-sqlite-panels-accept-a-sqlite-database-db-or-a-sqlite-migration-dump-dump-postgresql-panels-accept-a-pg_dump-archive-dump-a-sqlite-database-db-or-a-sqlite-migration-dump-the-panel-restarts-after-restore-destructive
|
||||
- content: Generate a new ECH (Encrypted Client Hello) keypair and config list for
|
||||
the given SNI.
|
||||
id: generate-a-new-ech-encrypted-client-hello-keypair-and-config-list-for-the-given-sni
|
||||
@@ -249,6 +292,18 @@ _openapi:
|
||||
- content: Run `xray tls ping` against a remote server and return its live
|
||||
leaf-certificate SHA-256 hash(es) for pinning (pinnedPeerCertSha256).
|
||||
id: run-xray-tls-ping-against-a-remote-server-and-return-its-live-leaf-certificate-sha-256-hashes-for-pinning-pinnedpeercertsha256
|
||||
- content: Run a live TLS 1.3 probe against a candidate REALITY target and return
|
||||
a feasibility verdict (TLS 1.3 + h2 + X25519 + trusted certificate)
|
||||
plus the certificate SAN DNS names. A target on a private/loopback
|
||||
address is reported with privateTarget=true and probed only when
|
||||
allowPrivate is set.
|
||||
id: run-a-live-tls-13-probe-against-a-candidate-reality-target-and-return-a-feasibility-verdict-tls-13--h2--x25519--trusted-certificate-plus-the-certificate-san-dns-names-a-target-on-a-privateloopback-address-is-reported-with-privatetargettrue-and-probed-only-when-allowprivate-is-set
|
||||
- content: Probe/discover REALITY targets and return each verdict ranked by
|
||||
feasibility then latency. Each comma-separated token may be a domain
|
||||
(validated with SNI), a bare IP, or a CIDR range (discovered without
|
||||
SNI by reading the certificate domain). When empty, a built-in seed
|
||||
list is probed.
|
||||
id: probediscover-reality-targets-and-return-each-verdict-ranked-by-feasibility-then-latency-each-comma-separated-token-may-be-a-domain-validated-with-sni-a-bare-ip-or-a-cidr-range-discovered-without-sni-by-reading-the-certificate-domain-when-empty-a-built-in-seed-list-is-probed
|
||||
- content: Fetch the fully aggregated inbound_client_ips database table. Used by
|
||||
nodes to sync recently active IPs across the cluster.
|
||||
id: fetch-the-fully-aggregated-inbound_client_ips-database-table-used-by-nodes-to-sync-recently-active-ips-across-the-cluster
|
||||
@@ -267,7 +322,7 @@ export default function Layout(props) {
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/server/status","method":"get"},{"path":"/panel/api/server/fail2banStatus","method":"get"},{"path":"/panel/api/server/cpuHistory/{bucket}","method":"get"},{"path":"/panel/api/server/history/{metric}/{bucket}","method":"get"},{"path":"/panel/api/server/xrayMetricsState","method":"get"},{"path":"/panel/api/server/xrayMetricsHistory/{metric}/{bucket}","method":"get"},{"path":"/panel/api/server/xrayObservatory","method":"get"},{"path":"/panel/api/server/xrayObservatoryHistory/{tag}/{bucket}","method":"get"},{"path":"/panel/api/server/getXrayVersion","method":"get"},{"path":"/panel/api/server/getPanelUpdateInfo","method":"get"},{"path":"/panel/api/server/getConfigJson","method":"get"},{"path":"/panel/api/server/getDb","method":"get"},{"path":"/panel/api/server/getMigration","method":"get"},{"path":"/panel/api/server/getNewUUID","method":"get"},{"path":"/panel/api/server/getWebCertFiles","method":"get"},{"path":"/panel/api/server/descendants","method":"get"},{"path":"/panel/api/server/getNewX25519Cert","method":"get"},{"path":"/panel/api/server/getNewmldsa65","method":"get"},{"path":"/panel/api/server/getNewmlkem768","method":"get"},{"path":"/panel/api/server/getNewVlessEnc","method":"get"},{"path":"/panel/api/server/stopXrayService","method":"post"},{"path":"/panel/api/server/restartXrayService","method":"post"},{"path":"/panel/api/server/installXray/{version}","method":"post"},{"path":"/panel/api/server/updatePanel","method":"post"},{"path":"/panel/api/server/setUpdateChannel","method":"post"},{"path":"/panel/api/server/updateGeofile","method":"post"},{"path":"/panel/api/server/updateGeofile/{fileName}","method":"post"},{"path":"/panel/api/server/logs/{count}","method":"post"},{"path":"/panel/api/server/xraylogs/{count}","method":"post"},{"path":"/panel/api/server/importDB","method":"post"},{"path":"/panel/api/server/getNewEchCert","method":"post"},{"path":"/panel/api/server/getCertHash","method":"post"},{"path":"/panel/api/server/getRemoteCertHash","method":"post"},{"path":"/panel/api/server/clientIps","method":"get"},{"path":"/panel/api/server/clientIps","method":"post"}]} showTitle />
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/openapi.json","method":"get"},{"path":"/panel/api/server/status","method":"get"},{"path":"/panel/api/server/fail2banStatus","method":"get"},{"path":"/panel/api/server/cpuHistory/{bucket}","method":"get"},{"path":"/panel/api/server/history/{metric}/{bucket}","method":"get"},{"path":"/panel/api/server/xrayMetricsState","method":"get"},{"path":"/panel/api/server/xrayMetricsHistory/{metric}/{bucket}","method":"get"},{"path":"/panel/api/server/xrayObservatory","method":"get"},{"path":"/panel/api/server/xrayObservatoryHistory/{tag}/{bucket}","method":"get"},{"path":"/panel/api/server/getXrayVersion","method":"get"},{"path":"/panel/api/server/getPanelUpdateInfo","method":"get"},{"path":"/panel/api/server/getUpdateStatus","method":"get"},{"path":"/panel/api/server/getConfigJson","method":"get"},{"path":"/panel/api/server/getDb","method":"get"},{"path":"/panel/api/server/getMigration","method":"get"},{"path":"/panel/api/server/getNewUUID","method":"get"},{"path":"/panel/api/server/getWebCertFiles","method":"get"},{"path":"/panel/api/server/descendants","method":"get"},{"path":"/panel/api/server/getNewX25519Cert","method":"get"},{"path":"/panel/api/server/getNewmldsa65","method":"get"},{"path":"/panel/api/server/getNewmlkem768","method":"get"},{"path":"/panel/api/server/getNewVlessEnc","method":"get"},{"path":"/panel/api/server/stopXrayService","method":"post"},{"path":"/panel/api/server/restartXrayService","method":"post"},{"path":"/panel/api/server/installXray/{version}","method":"post"},{"path":"/panel/api/server/updatePanel","method":"post"},{"path":"/panel/api/server/setUpdateChannel","method":"post"},{"path":"/panel/api/server/updateGeofile","method":"post"},{"path":"/panel/api/server/updateGeofile/{fileName}","method":"post"},{"path":"/panel/api/server/logs/{count}","method":"post"},{"path":"/panel/api/server/xraylogs/{count}","method":"post"},{"path":"/panel/api/server/importDB","method":"post"},{"path":"/panel/api/server/getNewEchCert","method":"post"},{"path":"/panel/api/server/getCertHash","method":"post"},{"path":"/panel/api/server/getRemoteCertHash","method":"post"},{"path":"/panel/api/server/scanRealityTarget","method":"post"},{"path":"/panel/api/server/scanRealityTargets","method":"post"},{"path":"/panel/api/server/clientIps","method":"get"},{"path":"/panel/api/server/clientIps","method":"post"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -15,11 +15,21 @@ _openapi:
|
||||
title: Return the computed default settings based on the request host. Useful to
|
||||
preview what a fresh install would use.
|
||||
url: '#return-the-computed-default-settings-based-on-the-request-host-useful-to-preview-what-a-fresh-install-would-use'
|
||||
- depth: 2
|
||||
title: Return the shipped (factory) default value per browser-safe setting key,
|
||||
so clients can tell a stored value apart from the default it would fall
|
||||
back to. Per-install material (secret, panelGuid, mTLS keys) and
|
||||
credential fields are never included.
|
||||
url: '#return-the-shipped-factory-default-value-per-browser-safe-setting-key-so-clients-can-tell-a-stored-value-apart-from-the-default-it-would-fall-back-to-per-install-material-secret-panelguid-mtls-keys-and-credential-fields-are-never-included'
|
||||
- depth: 2
|
||||
title: Persist every setting at once. The body mirrors the shape returned by
|
||||
/all. Invalid values (bad ports, missing cert pairs, etc.) are rejected
|
||||
before write.
|
||||
url: '#persist-every-setting-at-once-the-body-mirrors-the-shape-returned-by-all-invalid-values-bad-ports-missing-cert-pairs-etc-are-rejected-before-write'
|
||||
- depth: 2
|
||||
title: Validate any regular expression with the backend Go RE2 compiler without
|
||||
saving it.
|
||||
url: '#validate-any-regular-expression-with-the-backend-go-re2-compiler-without-saving-it'
|
||||
- depth: 2
|
||||
title: Change the panel admin username and password. Requires the current
|
||||
credentials for verification. The session is refreshed with the new
|
||||
@@ -50,10 +60,18 @@ _openapi:
|
||||
- content: Return the computed default settings based on the request host. Useful
|
||||
to preview what a fresh install would use.
|
||||
id: return-the-computed-default-settings-based-on-the-request-host-useful-to-preview-what-a-fresh-install-would-use
|
||||
- content: Return the shipped (factory) default value per browser-safe setting
|
||||
key, so clients can tell a stored value apart from the default it
|
||||
would fall back to. Per-install material (secret, panelGuid, mTLS
|
||||
keys) and credential fields are never included.
|
||||
id: return-the-shipped-factory-default-value-per-browser-safe-setting-key-so-clients-can-tell-a-stored-value-apart-from-the-default-it-would-fall-back-to-per-install-material-secret-panelguid-mtls-keys-and-credential-fields-are-never-included
|
||||
- content: Persist every setting at once. The body mirrors the shape returned by
|
||||
/all. Invalid values (bad ports, missing cert pairs, etc.) are
|
||||
rejected before write.
|
||||
id: persist-every-setting-at-once-the-body-mirrors-the-shape-returned-by-all-invalid-values-bad-ports-missing-cert-pairs-etc-are-rejected-before-write
|
||||
- content: Validate any regular expression with the backend Go RE2 compiler
|
||||
without saving it.
|
||||
id: validate-any-regular-expression-with-the-backend-go-re2-compiler-without-saving-it
|
||||
- content: Change the panel admin username and password. Requires the current
|
||||
credentials for verification. The session is refreshed with the new
|
||||
values on success.
|
||||
@@ -83,7 +101,7 @@ export default function Layout(props) {
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/setting/all","method":"post"},{"path":"/panel/api/setting/defaultSettings","method":"post"},{"path":"/panel/api/setting/update","method":"post"},{"path":"/panel/api/setting/updateUser","method":"post"},{"path":"/panel/api/setting/restartPanel","method":"post"},{"path":"/panel/api/setting/testSmtp","method":"post"},{"path":"/panel/api/setting/testTgBot","method":"post"},{"path":"/panel/api/setting/getDefaultJsonConfig","method":"get"}]} showTitle />
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/setting/all","method":"post"},{"path":"/panel/api/setting/defaultSettings","method":"post"},{"path":"/panel/api/setting/factoryDefaults","method":"post"},{"path":"/panel/api/setting/update","method":"post"},{"path":"/panel/api/setting/validateRegex","method":"post"},{"path":"/panel/api/setting/updateUser","method":"post"},{"path":"/panel/api/setting/restartPanel","method":"post"},{"path":"/panel/api/setting/testSmtp","method":"post"},{"path":"/panel/api/setting/testTgBot","method":"post"},{"path":"/panel/api/setting/getDefaultJsonConfig","method":"get"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: Subscription Balancers
|
||||
description: 'Client-side balancers for the JSON subscription: each enabled
|
||||
balancer is emitted as one extra config document whose members are the proxy
|
||||
outbounds of the selected inbounds (routing.balancers + burstObservatory).
|
||||
Managed in Settings → Sub Balancers.'
|
||||
full: true
|
||||
_openapi:
|
||||
preload:
|
||||
- ./public/openapi.json
|
||||
toc:
|
||||
- depth: 2
|
||||
title: List all subscription balancers in sort order (sort_order asc, id asc).
|
||||
url: '#list-all-subscription-balancers-in-sort-order-sort_order-asc-id-asc'
|
||||
- depth: 2
|
||||
title: Create a subscription balancer. It appears in the JSON subscription of
|
||||
every client that sits on at least one selected inbound.
|
||||
url: '#create-a-subscription-balancer-it-appears-in-the-json-subscription-of-every-client-that-sits-on-at-least-one-selected-inbound'
|
||||
- depth: 2
|
||||
title: Update a balancer by id. Accepts the same form fields as create (full-row
|
||||
update, including the enabled toggle).
|
||||
url: '#update-a-balancer-by-id-accepts-the-same-form-fields-as-create-full-row-update-including-the-enabled-toggle'
|
||||
- depth: 2
|
||||
title: Delete a balancer by id.
|
||||
url: '#delete-a-balancer-by-id'
|
||||
- depth: 2
|
||||
title: Delete a balancer by id (POST alias of DELETE for clients that cannot
|
||||
send DELETE).
|
||||
url: '#delete-a-balancer-by-id-post-alias-of-delete-for-clients-that-cannot-send-delete'
|
||||
structuredData:
|
||||
headings:
|
||||
- content: List all subscription balancers in sort order (sort_order asc, id asc).
|
||||
id: list-all-subscription-balancers-in-sort-order-sort_order-asc-id-asc
|
||||
- content: Create a subscription balancer. It appears in the JSON subscription of
|
||||
every client that sits on at least one selected inbound.
|
||||
id: create-a-subscription-balancer-it-appears-in-the-json-subscription-of-every-client-that-sits-on-at-least-one-selected-inbound
|
||||
- content: Update a balancer by id. Accepts the same form fields as create
|
||||
(full-row update, including the enabled toggle).
|
||||
id: update-a-balancer-by-id-accepts-the-same-form-fields-as-create-full-row-update-including-the-enabled-toggle
|
||||
- content: Delete a balancer by id.
|
||||
id: delete-a-balancer-by-id
|
||||
- content: Delete a balancer by id (POST alias of DELETE for clients that cannot
|
||||
send DELETE).
|
||||
id: delete-a-balancer-by-id-post-alias-of-delete-for-clients-that-cannot-send-delete
|
||||
contents: []
|
||||
---
|
||||
|
||||
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
|
||||
|
||||
export default function Layout(props) {
|
||||
const { APIPage, OpenAPIPage } = props.components ?? {};
|
||||
// "APIPage" is the old name from v10, this allows both for backward compatibility
|
||||
const Comp = OpenAPIPage ?? APIPage;
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/sub-balancers","method":"get"},{"path":"/panel/api/sub-balancers","method":"post"},{"path":"/panel/api/sub-balancers/{id}","method":"post"},{"path":"/panel/api/sub-balancers/{id}","method":"delete"},{"path":"/panel/api/sub-balancers/{id}/del","method":"post"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -13,9 +13,10 @@ _openapi:
|
||||
- depth: 2
|
||||
title: 'Return base64-encoded subscription links for all enabled clients
|
||||
matching the subscription ID. When the request has an Accept: text/html
|
||||
header or ?html=1, renders a styled info page instead. Default path:
|
||||
/sub/:subid.'
|
||||
url: '#return-base64-encoded-subscription-links-for-all-enabled-clients-matching-the-subscription-id-when-the-request-has-an-accept-texthtml-header-or-html1-renders-a-styled-info-page-instead-default-path-subsubid'
|
||||
header or ?html=1, renders a styled info page instead. With
|
||||
?format=info, returns the page view-model as JSON (traffic, expiry,
|
||||
online status; no links) for live polling. Default path: /sub/:subid.'
|
||||
url: '#return-base64-encoded-subscription-links-for-all-enabled-clients-matching-the-subscription-id-when-the-request-has-an-accept-texthtml-header-or-html1-renders-a-styled-info-page-instead-with-formatinfo-returns-the-page-view-model-as-json-traffic-expiry-online-status-no-links-for-live-polling-default-path-subsubid'
|
||||
- depth: 2
|
||||
title: 'Return subscription as a JSON array of proxy configs (one per enabled
|
||||
client). Only when JSON subscription is enabled in settings. Default
|
||||
@@ -30,9 +31,10 @@ _openapi:
|
||||
headings:
|
||||
- content: 'Return base64-encoded subscription links for all enabled clients
|
||||
matching the subscription ID. When the request has an Accept:
|
||||
text/html header or ?html=1, renders a styled info page instead.
|
||||
Default path: /sub/:subid.'
|
||||
id: return-base64-encoded-subscription-links-for-all-enabled-clients-matching-the-subscription-id-when-the-request-has-an-accept-texthtml-header-or-html1-renders-a-styled-info-page-instead-default-path-subsubid
|
||||
text/html header or ?html=1, renders a styled info page instead. With
|
||||
?format=info, returns the page view-model as JSON (traffic, expiry,
|
||||
online status; no links) for live polling. Default path: /sub/:subid.'
|
||||
id: return-base64-encoded-subscription-links-for-all-enabled-clients-matching-the-subscription-id-when-the-request-has-an-accept-texthtml-header-or-html1-renders-a-styled-info-page-instead-with-formatinfo-returns-the-page-view-model-as-json-traffic-expiry-online-status-no-links-for-live-polling-default-path-subsubid
|
||||
- content: 'Return subscription as a JSON array of proxy configs (one per enabled
|
||||
client). Only when JSON subscription is enabled in settings. Default
|
||||
path: /json/:subid.'
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
title: Xray Settings
|
||||
description: >-
|
||||
Xray configuration template, outbound management, Warp/Nord/PIA integration, and
|
||||
config testing. All endpoints under /panel/api/xray.
|
||||
description: Xray configuration template, outbound management, Warp/Nord/PIA
|
||||
integration, and config testing. All endpoints under /panel/api/xray.
|
||||
full: true
|
||||
_openapi:
|
||||
preload:
|
||||
@@ -37,7 +36,8 @@ _openapi:
|
||||
title: Manage NordVPN integration. The action parameter selects the operation.
|
||||
url: '#manage-nordvpn-integration-the-action-parameter-selects-the-operation'
|
||||
- depth: 2
|
||||
title: Manage PIA WireGuard integration. The action parameter selects the operation.
|
||||
title: Manage PIA WireGuard integration. The action parameter selects the
|
||||
operation.
|
||||
url: '#manage-pia-wireguard-integration-the-action-parameter-selects-the-operation'
|
||||
- depth: 2
|
||||
title: Reset traffic counters for a specific outbound by tag.
|
||||
@@ -66,6 +66,25 @@ _openapi:
|
||||
title: Ask the running core which outbound its router would pick for a synthetic
|
||||
connection (RoutingService.TestRoute). No traffic is sent.
|
||||
url: '#ask-the-running-core-which-outbound-its-router-would-pick-for-a-synthetic-connection-routingservicetestroute-no-traffic-is-sent'
|
||||
- depth: 2
|
||||
title: List the geo databases (.dat files) in the Xray asset folder, with the
|
||||
layout detected from their contents, size, modification time and
|
||||
category count. A database that fails to parse is still listed, with the
|
||||
reason in "error".
|
||||
url: '#list-the-geo-databases-dat-files-in-the-xray-asset-folder-with-the-layout-detected-from-their-contents-size-modification-time-and-category-count-a-database-that-fails-to-parse-is-still-listed-with-the-reason-in-error'
|
||||
- depth: 2
|
||||
title: One page of a database's categories, each with its entry count and the
|
||||
attributes its domains carry (e.g. "ads", "cn").
|
||||
url: '#one-page-of-a-databases-categories-each-with-its-entry-count-and-the-attributes-its-domains-carry-eg-ads-cn'
|
||||
- depth: 2
|
||||
title: One page of the rules inside a category — domain rules typed as
|
||||
domain/full/keyword/regexp for geosite databases, CIDRs for geoip ones.
|
||||
url: '#one-page-of-the-rules-inside-a-category--domain-rules-typed-as-domainfullkeywordregexp-for-geosite-databases-cidrs-for-geoip-ones'
|
||||
- depth: 2
|
||||
title: 'Check routing tokens against the databases on disk and return only the
|
||||
ones that do not resolve. Plain domains and CIDRs are ignored. Each
|
||||
issue carries a reason: syntax, fileMissing or categoryMissing.'
|
||||
url: '#check-routing-tokens-against-the-databases-on-disk-and-return-only-the-ones-that-do-not-resolve-plain-domains-and-cidrs-are-ignored-each-issue-carries-a-reason-syntax-filemissing-or-categorymissing'
|
||||
- depth: 2
|
||||
title: List all outbound subscriptions (remote URLs that supply additional
|
||||
outbounds), newest first.
|
||||
@@ -83,9 +102,9 @@ _openapi:
|
||||
title: Delete an outbound subscription by id.
|
||||
url: '#delete-an-outbound-subscription-by-id'
|
||||
- depth: 2
|
||||
title: Delete an outbound subscription by id (POST alias of DELETE for
|
||||
axios-friendly clients).
|
||||
url: '#delete-an-outbound-subscription-by-id-post-alias-of-delete-for-axios-friendly-clients'
|
||||
title: Delete an outbound subscription by id (POST alias of DELETE for clients
|
||||
that cannot send DELETE).
|
||||
url: '#delete-an-outbound-subscription-by-id-post-alias-of-delete-for-clients-that-cannot-send-delete'
|
||||
- depth: 2
|
||||
title: Force an immediate re-fetch of the subscription and return the parsed
|
||||
outbounds. Signals Xray to reload.
|
||||
@@ -121,8 +140,7 @@ _openapi:
|
||||
id: manage-cloudflare-warp-integration-the-action-parameter-selects-the-operation
|
||||
- content: Manage NordVPN integration. The action parameter selects the operation.
|
||||
id: manage-nordvpn-integration-the-action-parameter-selects-the-operation
|
||||
- content: >-
|
||||
Manage PIA WireGuard integration. The action parameter selects the
|
||||
- content: Manage PIA WireGuard integration. The action parameter selects the
|
||||
operation.
|
||||
id: manage-pia-wireguard-integration-the-action-parameter-selects-the-operation
|
||||
- content: Reset traffic counters for a specific outbound by tag.
|
||||
@@ -147,6 +165,22 @@ _openapi:
|
||||
- content: Ask the running core which outbound its router would pick for a
|
||||
synthetic connection (RoutingService.TestRoute). No traffic is sent.
|
||||
id: ask-the-running-core-which-outbound-its-router-would-pick-for-a-synthetic-connection-routingservicetestroute-no-traffic-is-sent
|
||||
- content: List the geo databases (.dat files) in the Xray asset folder, with the
|
||||
layout detected from their contents, size, modification time and
|
||||
category count. A database that fails to parse is still listed, with
|
||||
the reason in "error".
|
||||
id: list-the-geo-databases-dat-files-in-the-xray-asset-folder-with-the-layout-detected-from-their-contents-size-modification-time-and-category-count-a-database-that-fails-to-parse-is-still-listed-with-the-reason-in-error
|
||||
- content: One page of a database's categories, each with its entry count and the
|
||||
attributes its domains carry (e.g. "ads", "cn").
|
||||
id: one-page-of-a-databases-categories-each-with-its-entry-count-and-the-attributes-its-domains-carry-eg-ads-cn
|
||||
- content: One page of the rules inside a category — domain rules typed as
|
||||
domain/full/keyword/regexp for geosite databases, CIDRs for geoip
|
||||
ones.
|
||||
id: one-page-of-the-rules-inside-a-category--domain-rules-typed-as-domainfullkeywordregexp-for-geosite-databases-cidrs-for-geoip-ones
|
||||
- content: 'Check routing tokens against the databases on disk and return only the
|
||||
ones that do not resolve. Plain domains and CIDRs are ignored. Each
|
||||
issue carries a reason: syntax, fileMissing or categoryMissing.'
|
||||
id: check-routing-tokens-against-the-databases-on-disk-and-return-only-the-ones-that-do-not-resolve-plain-domains-and-cidrs-are-ignored-each-issue-carries-a-reason-syntax-filemissing-or-categorymissing
|
||||
- content: List all outbound subscriptions (remote URLs that supply additional
|
||||
outbounds), newest first.
|
||||
id: list-all-outbound-subscriptions-remote-urls-that-supply-additional-outbounds-newest-first
|
||||
@@ -159,9 +193,9 @@ _openapi:
|
||||
id: update-an-existing-outbound-subscription-by-id-accepts-the-same-form-fields-as-create
|
||||
- content: Delete an outbound subscription by id.
|
||||
id: delete-an-outbound-subscription-by-id
|
||||
- content: Delete an outbound subscription by id (POST alias of DELETE for
|
||||
axios-friendly clients).
|
||||
id: delete-an-outbound-subscription-by-id-post-alias-of-delete-for-axios-friendly-clients
|
||||
- content: Delete an outbound subscription by id (POST alias of DELETE for clients
|
||||
that cannot send DELETE).
|
||||
id: delete-an-outbound-subscription-by-id-post-alias-of-delete-for-clients-that-cannot-send-delete
|
||||
- content: Force an immediate re-fetch of the subscription and return the parsed
|
||||
outbounds. Signals Xray to reload.
|
||||
id: force-an-immediate-re-fetch-of-the-subscription-and-return-the-parsed-outbounds-signals-xray-to-reload
|
||||
@@ -183,7 +217,7 @@ export default function Layout(props) {
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/xray/","method":"post"},{"path":"/panel/api/xray/getDefaultJsonConfig","method":"get"},{"path":"/panel/api/xray/getOutboundsTraffic","method":"get"},{"path":"/panel/api/xray/getXrayResult","method":"get"},{"path":"/panel/api/xray/update","method":"post"},{"path":"/panel/api/xray/warp/{action}","method":"post"},{"path":"/panel/api/xray/nord/{action}","method":"post"},{"path":"/panel/api/xray/pia/{action}","method":"post"},{"path":"/panel/api/xray/resetOutboundsTraffic","method":"post"},{"path":"/panel/api/xray/testOutbound","method":"post"},{"path":"/panel/api/xray/testOutbounds","method":"post"},{"path":"/panel/api/xray/balancerStatus","method":"post"},{"path":"/panel/api/xray/balancerOverride","method":"post"},{"path":"/panel/api/xray/routeTest","method":"post"},{"path":"/panel/api/xray/outbound-subs","method":"get"},{"path":"/panel/api/xray/outbound-subs","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"delete"},{"path":"/panel/api/xray/outbound-subs/{id}/del","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/refresh","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/move","method":"post"},{"path":"/panel/api/xray/outbound-subs/parse","method":"post"}]} showTitle />
|
||||
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/xray/","method":"post"},{"path":"/panel/api/xray/getDefaultJsonConfig","method":"get"},{"path":"/panel/api/xray/getOutboundsTraffic","method":"get"},{"path":"/panel/api/xray/getXrayResult","method":"get"},{"path":"/panel/api/xray/update","method":"post"},{"path":"/panel/api/xray/warp/{action}","method":"post"},{"path":"/panel/api/xray/nord/{action}","method":"post"},{"path":"/panel/api/xray/pia/{action}","method":"post"},{"path":"/panel/api/xray/resetOutboundsTraffic","method":"post"},{"path":"/panel/api/xray/testOutbound","method":"post"},{"path":"/panel/api/xray/testOutbounds","method":"post"},{"path":"/panel/api/xray/balancerStatus","method":"post"},{"path":"/panel/api/xray/balancerOverride","method":"post"},{"path":"/panel/api/xray/routeTest","method":"post"},{"path":"/panel/api/xray/geodata/files","method":"get"},{"path":"/panel/api/xray/geodata/categories","method":"get"},{"path":"/panel/api/xray/geodata/entries","method":"get"},{"path":"/panel/api/xray/geodata/validate","method":"post"},{"path":"/panel/api/xray/outbound-subs","method":"get"},{"path":"/panel/api/xray/outbound-subs","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"delete"},{"path":"/panel/api/xray/outbound-subs/{id}/del","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/refresh","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/move","method":"post"},{"path":"/panel/api/xray/outbound-subs/parse","method":"post"}]} showTitle />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user