1
0

clients.mdx 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. ---
  2. title: Clients
  3. description: Manage clients as first-class entities that can be attached to one
  4. or more inbounds. A single client row drives the settings.clients entry in
  5. every inbound it belongs to. Endpoints live under /panel/api/clients.
  6. full: true
  7. _openapi:
  8. preload:
  9. - ./public/openapi.json
  10. toc:
  11. - depth: 2
  12. title: List every client with its attached inbound IDs and traffic record. The
  13. reverse field, if set, is returned as a nested JSON object (legacy
  14. JSON-encoded-string form is still accepted on write).
  15. 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'
  16. - depth: 2
  17. title: 'Filter, sort, and paginate clients on the server. Each item is a slim
  18. row (no uuid/password/auth/flow/security/reverse/tgId) so the clients
  19. page can ship 25-ish rows in a few KB instead of the full table. The
  20. response also includes a summary computed across the full DB row set so
  21. dashboard counters stay stable as the user paginates or filters: the
  22. *Count fields are exact, while the email arrays beside them stop at 200
  23. entries so the payload does not grow with the panel. Page size capped at
  24. 200; fetch /get/:email to obtain the full per-client payload for an
  25. edit/info modal.'
  26. 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'
  27. - depth: 2
  28. title: Fetch one client by email, including the inbound IDs and external config
  29. IDs it is attached to.
  30. url: '#fetch-one-client-by-email-including-the-inbound-ids-and-external-config-ids-it-is-attached-to'
  31. - depth: 2
  32. title: Fetch clients by Telegram user ID. Returns an array since multiple
  33. clients can share the same Telegram ID.
  34. url: '#fetch-clients-by-telegram-user-id-returns-an-array-since-multiple-clients-can-share-the-same-telegram-id'
  35. - depth: 2
  36. title: Create a new client and attach it to one or more inbounds in a single
  37. call. Body is JSON. Per-protocol secrets are generated server-side when
  38. omitted, so callers can send only the universal fields.
  39. url: '#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'
  40. - depth: 2
  41. title: Update an existing client by email. Changes propagate to every attached
  42. inbound. Body is the JSON client payload — supply the full set of fields
  43. you want to keep (the server replaces the row, it does not patch).
  44. url: '#update-an-existing-client-by-email-changes-propagate-to-every-attached-inbound-body-is-the-json-client-payload--supply-the-full-set-of-fields-you-want-to-keep-the-server-replaces-the-row-it-does-not-patch'
  45. - depth: 2
  46. title: Delete a client by email. Removes it from every attached inbound and
  47. drops its traffic record unless keepTraffic=1 is passed.
  48. url: '#delete-a-client-by-email-removes-it-from-every-attached-inbound-and-drops-its-traffic-record-unless-keeptraffic1-is-passed'
  49. - depth: 2
  50. title: Attach an existing client to one or more additional inbounds. Body is
  51. JSON.
  52. url: '#attach-an-existing-client-to-one-or-more-additional-inbounds-body-is-json'
  53. - depth: 2
  54. title: Detach a client from one or more inbounds without deleting the client.
  55. url: '#detach-a-client-from-one-or-more-inbounds-without-deleting-the-client'
  56. - depth: 2
  57. title: Replace a client's external links and external subscriptions. Sends the
  58. full set; the server replaces all rows. Disabled rows stay saved for
  59. editing but are not emitted in generated subscriptions. The owning
  60. client's disabled or expired state also stops these rows from being
  61. emitted on future subscription fetches; credentials already imported by
  62. an app remain valid until the external provider revokes them.
  63. 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-the-owning-clients-disabled-or-expired-state-also-stops-these-rows-from-being-emitted-on-future-subscription-fetches-credentials-already-imported-by-an-app-remain-valid-until-the-external-provider-revokes-them'
  64. - depth: 2
  65. title: Reset the up/down counters for every client globally. Quotas and expiry
  66. are not affected. Triggers an Xray restart if any counter actually
  67. moved.
  68. url: '#reset-the-updown-counters-for-every-client-globally-quotas-and-expiry-are-not-affected-triggers-an-xray-restart-if-any-counter-actually-moved'
  69. - depth: 2
  70. title: Delete every client whose traffic quota is exhausted (used >= total, when
  71. reset is disabled) or whose expiry has passed. Returns the deleted count
  72. and triggers an Xray restart when any client was on a running inbound.
  73. 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'
  74. - depth: 2
  75. title: Delete every client that is not attached to any inbound, along with its
  76. traffic record, IP log, HWID devices, and external links. Useful for
  77. clearing clients left unattached after their inbounds were removed.
  78. Returns the deleted count. Cannot be undone.
  79. 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'
  80. - depth: 2
  81. title: Return every client as a {client, inboundIds} array — the same shape
  82. /bulkCreate and /import accept — so the payload round-trips straight
  83. back through /import. Clients with no inbound attachment are included
  84. with an empty inboundIds list. The UI shows this in a CodeMirror viewer
  85. (copy / download); programmatic callers get the array in obj.
  86. url: '#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-with-an-empty-inboundids-list-the-ui-shows-this-in-a-codemirror-viewer-copy--download-programmatic-callers-get-the-array-in-obj'
  87. - depth: 2
  88. title: 'Import clients from a JSON body { "data": "<json>" }, where data is a
  89. string-encoded array produced by /export ([{client, inboundIds}]). Items
  90. with inboundIds are created and attached to those inbounds; items with
  91. an empty inboundIds list are restored as unattached client records.
  92. Existing emails are never overwritten — they are returned in skipped.
  93. Triggers a single Xray restart at the end if any target inbound was
  94. running.'
  95. url: '#import-clients-from-a-json-body--data-json--where-data-is-a-string-encoded-array-produced-by-export-client-inboundids-items-with-inboundids-are-created-and-attached-to-those-inbounds-items-with-an-empty-inboundids-list-are-restored-as-unattached-client-records-existing-emails-are-never-overwritten--they-are-returned-in-skipped-triggers-a-single-xray-restart-at-the-end-if-any-target-inbound-was-running'
  96. - depth: 2
  97. title: 'Shift expiry and/or traffic quota for many clients in one call.
  98. addDays/addBytes may be negative. Clients with unlimited expiry
  99. (expiryTime=0) or unlimited traffic (totalGB=0) are skipped for the
  100. corresponding field — bulk extend never converts unlimited to limited. A
  101. client that was auto-disabled solely because it was depleted (expired or
  102. over quota) is automatically re-enabled — locally and on its node — when
  103. the adjustment lifts it out of depletion; a manually-disabled or
  104. still-depleted client is left disabled. The optional flow directive sets
  105. the XTLS flow on every client: "none" clears it,
  106. "xtls-rprx-vision"/"xtls-rprx-vision-udp443" set it where the inbound
  107. supports it (omit or "" to leave it unchanged). The optional limitHwid
  108. sets maximum registered devices (0 = unlimited). The optional adTag sets
  109. MTProto Telegram sponsor channel ("none" clears). Returns the adjusted
  110. count and per-email skip reasons.'
  111. 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-the-optional-limithwid-sets-maximum-registered-devices-0--unlimited-the-optional-adtag-sets-mtproto-telegram-sponsor-channel-none-clears-returns-the-adjusted-count-and-per-email-skip-reasons'
  112. - depth: 2
  113. title: Enable many clients in one call. Emails are grouped by inbound and
  114. applied with a single read-modify-write per inbound; the running Xray
  115. (local or remote node) is updated to add each user. Note that enabling a
  116. client whose quota is exhausted or whose expiry has passed only flips
  117. the flag — the traffic loop will disable it again on the next tick.
  118. Returns the changed count and per-email skip reasons.
  119. url: '#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-a-client-whose-quota-is-exhausted-or-whose-expiry-has-passed-only-flips-the-flag--the-traffic-loop-will-disable-it-again-on-the-next-tick-returns-the-changed-count-and-per-email-skip-reasons'
  120. - depth: 2
  121. title: Disable many clients in one call. Emails are grouped by inbound and
  122. applied with a single read-modify-write per inbound; the running Xray
  123. (local or remote node) is updated to remove each user. Returns the
  124. changed count and per-email skip reasons.
  125. url: '#disable-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-remove-each-user-returns-the-changed-count-and-per-email-skip-reasons'
  126. - depth: 2
  127. title: Delete many clients in one call. The server processes the list
  128. sequentially so each delete sees the committed state of the previous one
  129. — avoids the race the per-email fan-out had on the panel side. Pass
  130. keepTraffic=true to retain the xray_client_traffic rows after deletion.
  131. url: '#delete-many-clients-in-one-call-the-server-processes-the-list-sequentially-so-each-delete-sees-the-committed-state-of-the-previous-one--avoids-the-race-the-per-email-fan-out-had-on-the-panel-side-pass-keeptraffictrue-to-retain-the-xray_client_traffic-rows-after-deletion'
  132. - depth: 2
  133. title: Create many clients in one call. Body is a JSON array of {client,
  134. inboundIds} payloads — the same shape /add accepts. Items are processed
  135. sequentially; per-email skip reasons are returned for items that fail
  136. (e.g., duplicate email). Triggers a single Xray restart at the end if
  137. any inbound was running.
  138. url: '#create-many-clients-in-one-call-body-is-a-json-array-of-client-inboundids-payloads--the-same-shape-add-accepts-items-are-processed-sequentially-per-email-skip-reasons-are-returned-for-items-that-fail-eg-duplicate-email-triggers-a-single-xray-restart-at-the-end-if-any-inbound-was-running'
  139. - depth: 2
  140. title: Add many clients to a group in one call. Updates clients.group_name and
  141. patches the matching client entry inside every owning inbound's settings
  142. JSON in a single transaction. If the group name does not yet exist (in
  143. client_groups or as a derived label), it is auto-created as a persistent
  144. group. To clear the group label, use /groups/bulkRemove instead.
  145. url: '#add-many-clients-to-a-group-in-one-call-updates-clientsgroup_name-and-patches-the-matching-client-entry-inside-every-owning-inbounds-settings-json-in-a-single-transaction-if-the-group-name-does-not-yet-exist-in-client_groups-or-as-a-derived-label-it-is-auto-created-as-a-persistent-group-to-clear-the-group-label-use-groupsbulkremove-instead'
  146. - depth: 2
  147. title: Clear the group label on many clients in one call. Inverse of
  148. /groups/bulkAdd. Clients themselves are kept — only the group label is
  149. cleared from clients.group_name and from each owning inbound's settings
  150. JSON. Groups become empty if all their members are removed.
  151. url: '#clear-the-group-label-on-many-clients-in-one-call-inverse-of-groupsbulkadd-clients-themselves-are-kept--only-the-group-label-is-cleared-from-clientsgroup_name-and-from-each-owning-inbounds-settings-json-groups-become-empty-if-all-their-members-are-removed'
  152. - depth: 2
  153. title: Attach many existing clients to many inbounds in one call. Each client
  154. keeps its identity (email/UUID/password/subId) and a shared traffic row;
  155. all clients are added to a target inbound in a single AddInboundClient
  156. call. Clients already present on a target are reported under skipped.
  157. Returns per-email attached/skipped/errors lists and triggers a single
  158. Xray restart if any target inbound was running.
  159. url: '#attach-many-existing-clients-to-many-inbounds-in-one-call-each-client-keeps-its-identity-emailuuidpasswordsubid-and-a-shared-traffic-row-all-clients-are-added-to-a-target-inbound-in-a-single-addinboundclient-call-clients-already-present-on-a-target-are-reported-under-skipped-returns-per-email-attachedskippederrors-lists-and-triggers-a-single-xray-restart-if-any-target-inbound-was-running'
  160. - depth: 2
  161. title: "Mirror of bulkAttach: detach many existing clients from many inbounds in
  162. one call. For each email, intersects the client's current inbounds with
  163. the requested set and detaches from those only; (email, inbound) pairs
  164. where the client is not currently attached are silently no-ops. Emails
  165. not attached to any of the requested inbounds are reported under
  166. skipped. Client records are kept even if they become orphaned — use
  167. bulkDel for full removal. Returns per-email detached/skipped/errors
  168. lists and triggers a single Xray restart if any target inbound was
  169. running."
  170. url: '#mirror-of-bulkattach-detach-many-existing-clients-from-many-inbounds-in-one-call-for-each-email-intersects-the-clients-current-inbounds-with-the-requested-set-and-detaches-from-those-only-email-inbound-pairs-where-the-client-is-not-currently-attached-are-silently-no-ops-emails-not-attached-to-any-of-the-requested-inbounds-are-reported-under-skipped-client-records-are-kept-even-if-they-become-orphaned--use-bulkdel-for-full-removal-returns-per-email-detachedskippederrors-lists-and-triggers-a-single-xray-restart-if-any-target-inbound-was-running'
  171. - depth: 2
  172. title: Zero up/down counters for many clients in one call. Loops the
  173. single-reset path so each client is re-enabled across its attached
  174. inbounds and pushed to Xray/remote nodes. Returns the count of
  175. successfully reset clients.
  176. url: '#zero-updown-counters-for-many-clients-in-one-call-loops-the-single-reset-path-so-each-client-is-re-enabled-across-its-attached-inbounds-and-pushed-to-xrayremote-nodes-returns-the-count-of-successfully-reset-clients'
  177. - depth: 2
  178. title: List all client groups with their member counts. Merges persisted groups
  179. (rows in client_groups, including empty placeholders) with the distinct
  180. group_name values currently set on clients. Sorted alphabetically
  181. (case-insensitive).
  182. url: '#list-all-client-groups-with-their-member-counts-merges-persisted-groups-rows-in-client_groups-including-empty-placeholders-with-the-distinct-group_name-values-currently-set-on-clients-sorted-alphabetically-case-insensitive'
  183. - depth: 2
  184. title: Return just the email list of clients that currently belong to the given
  185. group. Useful for fanning a single bulk action over an entire group
  186. without round-tripping the full client list.
  187. url: '#return-just-the-email-list-of-clients-that-currently-belong-to-the-given-group-useful-for-fanning-a-single-bulk-action-over-an-entire-group-without-round-tripping-the-full-client-list'
  188. - depth: 2
  189. title: Create a new empty (placeholder) group. The group becomes selectable in
  190. client forms and the filter drawer even before any client is added to
  191. it. Errors if a group with the same name already exists.
  192. url: '#create-a-new-empty-placeholder-group-the-group-becomes-selectable-in-client-forms-and-the-filter-drawer-even-before-any-client-is-added-to-it-errors-if-a-group-with-the-same-name-already-exists'
  193. - depth: 2
  194. title: Rename a group. The new name is applied to the client_groups row AND
  195. propagated to every matching client (both clients.group_name and the
  196. client entry inside every owning inbound's settings JSON) in a single
  197. transaction. Returns the number of clients whose label was updated.
  198. url: '#rename-a-group-the-new-name-is-applied-to-the-client_groups-row-and-propagated-to-every-matching-client-both-clientsgroup_name-and-the-client-entry-inside-every-owning-inbounds-settings-json-in-a-single-transaction-returns-the-number-of-clients-whose-label-was-updated'
  199. - depth: 2
  200. title: Remove a group. Deletes the client_groups row and clears the group label
  201. from every matching client (both clients.group_name and the inbound
  202. settings JSON). The clients themselves are NOT deleted — use /bulkDel
  203. after filtering by group for that. Returns the count of clients whose
  204. label was cleared.
  205. 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'
  206. - depth: 2
  207. title: Reset only the group-level traffic counter shown on the groups page.
  208. Snapshots the current up/down sum of the group's members as a baseline
  209. so the group total reads zero, while leaving each client's own counters
  210. (and their quotas) untouched. No Xray restart is triggered. Creates the
  211. client_groups row if the group exists only as a derived label.
  212. 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'
  213. - depth: 2
  214. title: Zero out a single client’s up/down counters. Re-enables the client across
  215. every attached inbound and pushes the change to Xray (or the remote
  216. node) so depleted users can connect again immediately.
  217. url: '#zero-out-a-single-clients-updown-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'
  218. - depth: 2
  219. title: Manually adjust a client’s upload + download counters. Useful for
  220. migrations from external accounting systems.
  221. url: '#manually-adjust-a-clients-upload--download-counters-useful-for-migrations-from-external-accounting-systems'
  222. - depth: 2
  223. title: List source IPs that have connected with the given client’s credentials.
  224. Returns an array of "ip (timestamp)" strings.
  225. url: '#list-source-ips-that-have-connected-with-the-given-clients-credentials-returns-an-array-of-ip-timestamp-strings'
  226. - depth: 2
  227. title: Reset the recorded IP list for a client.
  228. url: '#reset-the-recorded-ip-list-for-a-client'
  229. - depth: 2
  230. title: List registered HWID devices for a client with a short fingerprint. Full hashes are not exposed.
  231. url: '#list-registered-hwid-devices-for-a-client-with-a-short-fingerprint-full-hashes-are-not-exposed'
  232. - depth: 2
  233. title: Clear all registered HWID devices for a client so new devices can
  234. register again.
  235. url: '#clear-all-registered-hwid-devices-for-a-client-so-new-devices-can-register-again'
  236. - depth: 2
  237. title: Remove a single registered HWID device by its id, freeing one slot under
  238. the HWID limit.
  239. url: '#remove-a-single-registered-hwid-device-by-its-id-freeing-one-slot-under-the-hwid-limit'
  240. - depth: 2
  241. title: List the emails of currently connected clients (last seen within the
  242. heartbeat window), deduped across every node.
  243. url: '#list-the-emails-of-currently-connected-clients-last-seen-within-the-heartbeat-window-deduped-across-every-node'
  244. - depth: 2
  245. title: Online client emails grouped by the panelGuid of the node that physically
  246. hosts each client. The local panel uses its own GUID; each node (at any
  247. depth in a chain) uses its GUID. Lets the inbounds page attribute online
  248. status to the real node instead of the intermediate one it syncs
  249. through.
  250. url: '#online-client-emails-grouped-by-the-panelguid-of-the-node-that-physically-hosts-each-client-the-local-panel-uses-its-own-guid-each-node-at-any-depth-in-a-chain-uses-its-guid-lets-the-inbounds-page-attribute-online-status-to-the-real-node-instead-of-the-intermediate-one-it-syncs-through'
  251. - depth: 2
  252. title: Per-client source IPs grouped by the panelGuid of the node that observed
  253. them. Lets the central panel attribute and enforce per-client IP limits
  254. using the real visitor IPs each node sees, instead of the address of the
  255. intermediate panel it syncs through.
  256. url: '#per-client-source-ips-grouped-by-the-panelguid-of-the-node-that-observed-them-lets-the-central-panel-attribute-and-enforce-per-client-ip-limits-using-the-real-visitor-ips-each-node-sees-instead-of-the-address-of-the-intermediate-panel-it-syncs-through'
  257. - depth: 2
  258. title: Inbound tags that carried traffic within the heartbeat window, grouped by
  259. the hosting node's panelGuid. Pairs with onlinesByGuid so the inbounds
  260. page only marks a multi-inbound client online on the inbounds it
  261. actually used. Nodes that do not report per-inbound activity are absent.
  262. url: '#inbound-tags-that-carried-traffic-within-the-heartbeat-window-grouped-by-the-hosting-nodes-panelguid-pairs-with-onlinesbyguid-so-the-inbounds-page-only-marks-a-multi-inbound-client-online-on-the-inbounds-it-actually-used-nodes-that-do-not-report-per-inbound-activity-are-absent'
  263. - depth: 2
  264. title: Map of client email → last-seen unix timestamp.
  265. url: '#map-of-client-email--last-seen-unix-timestamp'
  266. - depth: 2
  267. title: Traffic counters for a client identified by email.
  268. url: '#traffic-counters-for-a-client-identified-by-email'
  269. - depth: 2
  270. title: Return every protocol URL (vless://, vmess://, trojan://, ss://,
  271. hysteria://, hy2://) for clients matching the subscription ID. Same
  272. result set as the configured subPath endpoint, but as a JSON array — no
  273. base64. When an inbound has streamSettings.externalProxy set, one URL is
  274. emitted per external proxy. Empty array when the subId has no enabled
  275. clients.
  276. url: '#return-every-protocol-url-vless-vmess-trojan-ss-hysteria-hy2-for-clients-matching-the-subscription-id-same-result-set-as-the-configured-subpath-endpoint-but-as-a-json-array--no-base64-when-an-inbound-has-streamsettingsexternalproxy-set-one-url-is-emitted-per-external-proxy-empty-array-when-the-subid-has-no-enabled-clients'
  277. - depth: 2
  278. title: 'Return every URL for one client across all attached inbounds, one per
  279. advertised endpoint: the managed hosts of the inbound, else its
  280. streamSettings.externalProxy entries, else its own address. Supported
  281. protocols: vmess, vless, trojan, shadowsocks, hysteria, mtproto.
  282. Protocols without a URL form (socks, http, mixed, wireguard, dokodemo,
  283. tunnel) contribute nothing.'
  284. url: '#return-every-url-for-one-client-across-all-attached-inbounds-one-per-advertised-endpoint-the-managed-hosts-of-the-inbound-else-its-streamsettingsexternalproxy-entries-else-its-own-address-supported-protocols-vmess-vless-trojan-shadowsocks-hysteria-mtproto-protocols-without-a-url-form-socks-http-mixed-wireguard-dokodemo-tunnel-contribute-nothing'
  285. structuredData:
  286. headings:
  287. - content: List every client with its attached inbound IDs and traffic record. The
  288. reverse field, if set, is returned as a nested JSON object (legacy
  289. JSON-encoded-string form is still accepted on write).
  290. 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
  291. - content: 'Filter, sort, and paginate clients on the server. Each item is a slim
  292. row (no uuid/password/auth/flow/security/reverse/tgId) so the clients
  293. page can ship 25-ish rows in a few KB instead of the full table. The
  294. response also includes a summary computed across the full DB row set
  295. so dashboard counters stay stable as the user paginates or filters:
  296. the *Count fields are exact, while the email arrays beside them stop
  297. at 200 entries so the payload does not grow with the panel. Page size
  298. capped at 200; fetch /get/:email to obtain the full per-client payload
  299. for an edit/info modal.'
  300. 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
  301. - content: Fetch one client by email, including the inbound IDs and external
  302. config IDs it is attached to.
  303. id: fetch-one-client-by-email-including-the-inbound-ids-and-external-config-ids-it-is-attached-to
  304. - content: Fetch clients by Telegram user ID. Returns an array since multiple
  305. clients can share the same Telegram ID.
  306. id: fetch-clients-by-telegram-user-id-returns-an-array-since-multiple-clients-can-share-the-same-telegram-id
  307. - content: Create a new client and attach it to one or more inbounds in a single
  308. call. Body is JSON. Per-protocol secrets are generated server-side
  309. when omitted, so callers can send only the universal fields.
  310. id: 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
  311. - content: Update an existing client by email. Changes propagate to every attached
  312. inbound. Body is the JSON client payload — supply the full set of
  313. fields you want to keep (the server replaces the row, it does not
  314. patch).
  315. id: update-an-existing-client-by-email-changes-propagate-to-every-attached-inbound-body-is-the-json-client-payload--supply-the-full-set-of-fields-you-want-to-keep-the-server-replaces-the-row-it-does-not-patch
  316. - content: Delete a client by email. Removes it from every attached inbound and
  317. drops its traffic record unless keepTraffic=1 is passed.
  318. id: delete-a-client-by-email-removes-it-from-every-attached-inbound-and-drops-its-traffic-record-unless-keeptraffic1-is-passed
  319. - content: Attach an existing client to one or more additional inbounds. Body is
  320. JSON.
  321. id: attach-an-existing-client-to-one-or-more-additional-inbounds-body-is-json
  322. - content: Detach a client from one or more inbounds without deleting the client.
  323. id: detach-a-client-from-one-or-more-inbounds-without-deleting-the-client
  324. - content: Replace a client's external links and external subscriptions. Sends the
  325. full set; the server replaces all rows. Disabled rows stay saved for
  326. editing but are not emitted in generated subscriptions. The owning
  327. client's disabled or expired state also stops these rows from being
  328. emitted on future subscription fetches; credentials already imported
  329. by an app remain valid until the external provider revokes them.
  330. 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-the-owning-clients-disabled-or-expired-state-also-stops-these-rows-from-being-emitted-on-future-subscription-fetches-credentials-already-imported-by-an-app-remain-valid-until-the-external-provider-revokes-them
  331. - content: Reset the up/down counters for every client globally. Quotas and expiry
  332. are not affected. Triggers an Xray restart if any counter actually
  333. moved.
  334. id: reset-the-updown-counters-for-every-client-globally-quotas-and-expiry-are-not-affected-triggers-an-xray-restart-if-any-counter-actually-moved
  335. - content: Delete every client whose traffic quota is exhausted (used >= total,
  336. when reset is disabled) or whose expiry has passed. Returns the
  337. deleted count and triggers an Xray restart when any client was on a
  338. running inbound.
  339. 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
  340. - content: Delete every client that is not attached to any inbound, along with its
  341. traffic record, IP log, HWID devices, and external links. Useful for
  342. clearing clients left unattached after their inbounds were removed.
  343. Returns the deleted count. Cannot be undone.
  344. 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
  345. - content: Return every client as a {client, inboundIds} array — the same shape
  346. /bulkCreate and /import accept — so the payload round-trips straight
  347. back through /import. Clients with no inbound attachment are included
  348. with an empty inboundIds list. The UI shows this in a CodeMirror
  349. viewer (copy / download); programmatic callers get the array in obj.
  350. id: 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-with-an-empty-inboundids-list-the-ui-shows-this-in-a-codemirror-viewer-copy--download-programmatic-callers-get-the-array-in-obj
  351. - content: 'Import clients from a JSON body { "data": "<json>" }, where data is a
  352. string-encoded array produced by /export ([{client, inboundIds}]).
  353. Items with inboundIds are created and attached to those inbounds;
  354. items with an empty inboundIds list are restored as unattached client
  355. records. Existing emails are never overwritten — they are returned in
  356. skipped. Triggers a single Xray restart at the end if any target
  357. inbound was running.'
  358. id: import-clients-from-a-json-body--data-json--where-data-is-a-string-encoded-array-produced-by-export-client-inboundids-items-with-inboundids-are-created-and-attached-to-those-inbounds-items-with-an-empty-inboundids-list-are-restored-as-unattached-client-records-existing-emails-are-never-overwritten--they-are-returned-in-skipped-triggers-a-single-xray-restart-at-the-end-if-any-target-inbound-was-running
  359. - content: 'Shift expiry and/or traffic quota for many clients in one call.
  360. addDays/addBytes may be negative. Clients with unlimited expiry
  361. (expiryTime=0) or unlimited traffic (totalGB=0) are skipped for the
  362. corresponding field — bulk extend never converts unlimited to limited.
  363. A client that was auto-disabled solely because it was depleted
  364. (expired or over quota) is automatically re-enabled — locally and on
  365. its node — when the adjustment lifts it out of depletion; a
  366. manually-disabled or still-depleted client is left disabled. The
  367. optional flow directive sets the XTLS flow on every client: "none"
  368. clears it, "xtls-rprx-vision"/"xtls-rprx-vision-udp443" set it where
  369. the inbound supports it (omit or "" to leave it unchanged). The
  370. optional limitHwid sets maximum registered devices (0 = unlimited).
  371. The optional adTag sets MTProto Telegram sponsor channel ("none"
  372. clears). Returns the adjusted count and per-email skip reasons.'
  373. 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-the-optional-limithwid-sets-maximum-registered-devices-0--unlimited-the-optional-adtag-sets-mtproto-telegram-sponsor-channel-none-clears-returns-the-adjusted-count-and-per-email-skip-reasons
  374. - content: Enable many clients in one call. Emails are grouped by inbound and
  375. applied with a single read-modify-write per inbound; the running Xray
  376. (local or remote node) is updated to add each user. Note that enabling
  377. a client whose quota is exhausted or whose expiry has passed only
  378. flips the flag — the traffic loop will disable it again on the next
  379. tick. Returns the changed count and per-email skip reasons.
  380. id: 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-a-client-whose-quota-is-exhausted-or-whose-expiry-has-passed-only-flips-the-flag--the-traffic-loop-will-disable-it-again-on-the-next-tick-returns-the-changed-count-and-per-email-skip-reasons
  381. - content: Disable many clients in one call. Emails are grouped by inbound and
  382. applied with a single read-modify-write per inbound; the running Xray
  383. (local or remote node) is updated to remove each user. Returns the
  384. changed count and per-email skip reasons.
  385. id: disable-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-remove-each-user-returns-the-changed-count-and-per-email-skip-reasons
  386. - content: Delete many clients in one call. The server processes the list
  387. sequentially so each delete sees the committed state of the previous
  388. one — avoids the race the per-email fan-out had on the panel side.
  389. Pass keepTraffic=true to retain the xray_client_traffic rows after
  390. deletion.
  391. id: delete-many-clients-in-one-call-the-server-processes-the-list-sequentially-so-each-delete-sees-the-committed-state-of-the-previous-one--avoids-the-race-the-per-email-fan-out-had-on-the-panel-side-pass-keeptraffictrue-to-retain-the-xray_client_traffic-rows-after-deletion
  392. - content: Create many clients in one call. Body is a JSON array of {client,
  393. inboundIds} payloads — the same shape /add accepts. Items are
  394. processed sequentially; per-email skip reasons are returned for items
  395. that fail (e.g., duplicate email). Triggers a single Xray restart at
  396. the end if any inbound was running.
  397. id: create-many-clients-in-one-call-body-is-a-json-array-of-client-inboundids-payloads--the-same-shape-add-accepts-items-are-processed-sequentially-per-email-skip-reasons-are-returned-for-items-that-fail-eg-duplicate-email-triggers-a-single-xray-restart-at-the-end-if-any-inbound-was-running
  398. - content: Add many clients to a group in one call. Updates clients.group_name and
  399. patches the matching client entry inside every owning inbound's
  400. settings JSON in a single transaction. If the group name does not yet
  401. exist (in client_groups or as a derived label), it is auto-created as
  402. a persistent group. To clear the group label, use /groups/bulkRemove
  403. instead.
  404. id: add-many-clients-to-a-group-in-one-call-updates-clientsgroup_name-and-patches-the-matching-client-entry-inside-every-owning-inbounds-settings-json-in-a-single-transaction-if-the-group-name-does-not-yet-exist-in-client_groups-or-as-a-derived-label-it-is-auto-created-as-a-persistent-group-to-clear-the-group-label-use-groupsbulkremove-instead
  405. - content: Clear the group label on many clients in one call. Inverse of
  406. /groups/bulkAdd. Clients themselves are kept — only the group label is
  407. cleared from clients.group_name and from each owning inbound's
  408. settings JSON. Groups become empty if all their members are removed.
  409. id: clear-the-group-label-on-many-clients-in-one-call-inverse-of-groupsbulkadd-clients-themselves-are-kept--only-the-group-label-is-cleared-from-clientsgroup_name-and-from-each-owning-inbounds-settings-json-groups-become-empty-if-all-their-members-are-removed
  410. - content: Attach many existing clients to many inbounds in one call. Each client
  411. keeps its identity (email/UUID/password/subId) and a shared traffic
  412. row; all clients are added to a target inbound in a single
  413. AddInboundClient call. Clients already present on a target are
  414. reported under skipped. Returns per-email attached/skipped/errors
  415. lists and triggers a single Xray restart if any target inbound was
  416. running.
  417. id: attach-many-existing-clients-to-many-inbounds-in-one-call-each-client-keeps-its-identity-emailuuidpasswordsubid-and-a-shared-traffic-row-all-clients-are-added-to-a-target-inbound-in-a-single-addinboundclient-call-clients-already-present-on-a-target-are-reported-under-skipped-returns-per-email-attachedskippederrors-lists-and-triggers-a-single-xray-restart-if-any-target-inbound-was-running
  418. - content: "Mirror of bulkAttach: detach many existing clients from many inbounds
  419. in one call. For each email, intersects the client's current inbounds
  420. with the requested set and detaches from those only; (email, inbound)
  421. pairs where the client is not currently attached are silently no-ops.
  422. Emails not attached to any of the requested inbounds are reported
  423. under skipped. Client records are kept even if they become orphaned —
  424. use bulkDel for full removal. Returns per-email
  425. detached/skipped/errors lists and triggers a single Xray restart if
  426. any target inbound was running."
  427. id: mirror-of-bulkattach-detach-many-existing-clients-from-many-inbounds-in-one-call-for-each-email-intersects-the-clients-current-inbounds-with-the-requested-set-and-detaches-from-those-only-email-inbound-pairs-where-the-client-is-not-currently-attached-are-silently-no-ops-emails-not-attached-to-any-of-the-requested-inbounds-are-reported-under-skipped-client-records-are-kept-even-if-they-become-orphaned--use-bulkdel-for-full-removal-returns-per-email-detachedskippederrors-lists-and-triggers-a-single-xray-restart-if-any-target-inbound-was-running
  428. - content: Zero up/down counters for many clients in one call. Loops the
  429. single-reset path so each client is re-enabled across its attached
  430. inbounds and pushed to Xray/remote nodes. Returns the count of
  431. successfully reset clients.
  432. id: zero-updown-counters-for-many-clients-in-one-call-loops-the-single-reset-path-so-each-client-is-re-enabled-across-its-attached-inbounds-and-pushed-to-xrayremote-nodes-returns-the-count-of-successfully-reset-clients
  433. - content: List all client groups with their member counts. Merges persisted
  434. groups (rows in client_groups, including empty placeholders) with the
  435. distinct group_name values currently set on clients. Sorted
  436. alphabetically (case-insensitive).
  437. id: list-all-client-groups-with-their-member-counts-merges-persisted-groups-rows-in-client_groups-including-empty-placeholders-with-the-distinct-group_name-values-currently-set-on-clients-sorted-alphabetically-case-insensitive
  438. - content: Return just the email list of clients that currently belong to the
  439. given group. Useful for fanning a single bulk action over an entire
  440. group without round-tripping the full client list.
  441. id: return-just-the-email-list-of-clients-that-currently-belong-to-the-given-group-useful-for-fanning-a-single-bulk-action-over-an-entire-group-without-round-tripping-the-full-client-list
  442. - content: Create a new empty (placeholder) group. The group becomes selectable in
  443. client forms and the filter drawer even before any client is added to
  444. it. Errors if a group with the same name already exists.
  445. id: create-a-new-empty-placeholder-group-the-group-becomes-selectable-in-client-forms-and-the-filter-drawer-even-before-any-client-is-added-to-it-errors-if-a-group-with-the-same-name-already-exists
  446. - content: Rename a group. The new name is applied to the client_groups row AND
  447. propagated to every matching client (both clients.group_name and the
  448. client entry inside every owning inbound's settings JSON) in a single
  449. transaction. Returns the number of clients whose label was updated.
  450. id: rename-a-group-the-new-name-is-applied-to-the-client_groups-row-and-propagated-to-every-matching-client-both-clientsgroup_name-and-the-client-entry-inside-every-owning-inbounds-settings-json-in-a-single-transaction-returns-the-number-of-clients-whose-label-was-updated
  451. - content: Remove a group. Deletes the client_groups row and clears the group
  452. label from every matching client (both clients.group_name and the
  453. inbound settings JSON). The clients themselves are NOT deleted — use
  454. /bulkDel after filtering by group for that. Returns the count of
  455. clients whose label was cleared.
  456. 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
  457. - content: Reset only the group-level traffic counter shown on the groups page.
  458. Snapshots the current up/down sum of the group's members as a baseline
  459. so the group total reads zero, while leaving each client's own
  460. counters (and their quotas) untouched. No Xray restart is triggered.
  461. Creates the client_groups row if the group exists only as a derived
  462. label.
  463. 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
  464. - content: Zero out a single client’s up/down counters. Re-enables the client
  465. across every attached inbound and pushes the change to Xray (or the
  466. remote node) so depleted users can connect again immediately.
  467. id: zero-out-a-single-clients-updown-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
  468. - content: Manually adjust a client’s upload + download counters. Useful for
  469. migrations from external accounting systems.
  470. id: manually-adjust-a-clients-upload--download-counters-useful-for-migrations-from-external-accounting-systems
  471. - content: List source IPs that have connected with the given client’s
  472. credentials. Returns an array of "ip (timestamp)" strings.
  473. id: list-source-ips-that-have-connected-with-the-given-clients-credentials-returns-an-array-of-ip-timestamp-strings
  474. - content: Reset the recorded IP list for a client.
  475. id: reset-the-recorded-ip-list-for-a-client
  476. - content: List registered HWID devices for a client with a short fingerprint. Full hashes are not exposed.
  477. id: list-registered-hwid-devices-for-a-client-with-a-short-fingerprint-full-hashes-are-not-exposed
  478. - content: Clear all registered HWID devices for a client so new devices can
  479. register again.
  480. id: clear-all-registered-hwid-devices-for-a-client-so-new-devices-can-register-again
  481. - content: Remove a single registered HWID device by its id, freeing one slot
  482. under the HWID limit.
  483. id: remove-a-single-registered-hwid-device-by-its-id-freeing-one-slot-under-the-hwid-limit
  484. - content: List the emails of currently connected clients (last seen within the
  485. heartbeat window), deduped across every node.
  486. id: list-the-emails-of-currently-connected-clients-last-seen-within-the-heartbeat-window-deduped-across-every-node
  487. - content: Online client emails grouped by the panelGuid of the node that
  488. physically hosts each client. The local panel uses its own GUID; each
  489. node (at any depth in a chain) uses its GUID. Lets the inbounds page
  490. attribute online status to the real node instead of the intermediate
  491. one it syncs through.
  492. id: online-client-emails-grouped-by-the-panelguid-of-the-node-that-physically-hosts-each-client-the-local-panel-uses-its-own-guid-each-node-at-any-depth-in-a-chain-uses-its-guid-lets-the-inbounds-page-attribute-online-status-to-the-real-node-instead-of-the-intermediate-one-it-syncs-through
  493. - content: Per-client source IPs grouped by the panelGuid of the node that
  494. observed them. Lets the central panel attribute and enforce per-client
  495. IP limits using the real visitor IPs each node sees, instead of the
  496. address of the intermediate panel it syncs through.
  497. id: per-client-source-ips-grouped-by-the-panelguid-of-the-node-that-observed-them-lets-the-central-panel-attribute-and-enforce-per-client-ip-limits-using-the-real-visitor-ips-each-node-sees-instead-of-the-address-of-the-intermediate-panel-it-syncs-through
  498. - content: Inbound tags that carried traffic within the heartbeat window, grouped
  499. by the hosting node's panelGuid. Pairs with onlinesByGuid so the
  500. inbounds page only marks a multi-inbound client online on the inbounds
  501. it actually used. Nodes that do not report per-inbound activity are
  502. absent.
  503. id: inbound-tags-that-carried-traffic-within-the-heartbeat-window-grouped-by-the-hosting-nodes-panelguid-pairs-with-onlinesbyguid-so-the-inbounds-page-only-marks-a-multi-inbound-client-online-on-the-inbounds-it-actually-used-nodes-that-do-not-report-per-inbound-activity-are-absent
  504. - content: Map of client email → last-seen unix timestamp.
  505. id: map-of-client-email--last-seen-unix-timestamp
  506. - content: Traffic counters for a client identified by email.
  507. id: traffic-counters-for-a-client-identified-by-email
  508. - content: Return every protocol URL (vless://, vmess://, trojan://, ss://,
  509. hysteria://, hy2://) for clients matching the subscription ID. Same
  510. result set as the configured subPath endpoint, but as a JSON array —
  511. no base64. When an inbound has streamSettings.externalProxy set, one
  512. URL is emitted per external proxy. Empty array when the subId has no
  513. enabled clients.
  514. id: return-every-protocol-url-vless-vmess-trojan-ss-hysteria-hy2-for-clients-matching-the-subscription-id-same-result-set-as-the-configured-subpath-endpoint-but-as-a-json-array--no-base64-when-an-inbound-has-streamsettingsexternalproxy-set-one-url-is-emitted-per-external-proxy-empty-array-when-the-subid-has-no-enabled-clients
  515. - content: 'Return every URL for one client across all attached inbounds, one per
  516. advertised endpoint: the managed hosts of the inbound, else its
  517. streamSettings.externalProxy entries, else its own address. Supported
  518. protocols: vmess, vless, trojan, shadowsocks, hysteria, mtproto.
  519. Protocols without a URL form (socks, http, mixed, wireguard, dokodemo,
  520. tunnel) contribute nothing.'
  521. id: return-every-url-for-one-client-across-all-attached-inbounds-one-per-advertised-endpoint-the-managed-hosts-of-the-inbound-else-its-streamsettingsexternalproxy-entries-else-its-own-address-supported-protocols-vmess-vless-trojan-shadowsocks-hysteria-mtproto-protocols-without-a-url-form-socks-http-mixed-wireguard-dokodemo-tunnel-contribute-nothing
  522. contents:
  523. - content: >-
  524. Fields the server fills in when they are omitted — a valid value sent
  525. by the caller is never overwritten. Re-adding an email that already
  526. exists, with its stored `subId`, reuses the stored `id`, `password`,
  527. `auth` and `secret` instead of minting new ones, so the identity stays
  528. in sync across its inbounds.
  529. - **VLESS / VMess** — `id`, a fresh UUID
  530. - **Trojan** — `password`
  531. - **Shadowsocks** — `password`. On a `2022-blake3-*` inbound a
  532. supplied password that does not base64-decode to the key length of the
  533. cipher (16 or 32 bytes) is replaced by a generated key and the call
  534. still succeeds, so read the client back if you did not let the server
  535. pick. Legacy ciphers keep any non-empty password
  536. - **Hysteria** — `auth`
  537. - **mtproto** — `secret`, a FakeTLS secret derived from the fronting
  538. domain of the inbound, or from `www.cloudflare.com` when it has none
  539. - **WireGuard** — `privateKey` and `publicKey` when both are blank, or
  540. `publicKey` alone when only a `privateKey` was sent, plus
  541. `allowedIPs`: one free `/32` taken from the /24 the existing peers of
  542. that inbound already sit in, or from `10.0.0.0/24` when it has none
  543. Accepted on the same body but never generated: `preSharedKey` and
  544. `keepAlive` (WireGuard), `adTag` (mtproto).
  545. WireGuard is the only one of these that can fail. Allocation widens
  546. the search to the containing /16 before giving up with `inbound <id>:
  547. wireguard: no free address available in <scope>`, and an `allowedIPs`
  548. supplied by the caller is validated instead of allocated: `inbound
  549. <id>: wireguard: allowedIPs entry already used by another client:
  550. <address>` when a different client of that same inbound already holds
  551. it. The check is per inbound, so the same address on two different
  552. inbounds is accepted. The same validation runs on POST
  553. /panel/api/clients/{email}/attach, where a client that already carries
  554. an address brings it along.
  555. An `inboundIds` entry that names no existing inbound rejects the whole
  556. call before anything is written. Past that, the inbounds are applied
  557. concurrently and independently: one that fails no longer stops the
  558. others, so a `success:false` response can still have created the
  559. client on the rest. Every error names the inbound it came from
  560. (`inbound 7: <message>`), and several failures are reported together,
  561. one per line. `limitHwid` is applied only when every inbound
  562. succeeded, so re-run the call after fixing the failure.
  563. heading: 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
  564. - content: 'The inbounds are applied concurrently and independently: one that
  565. fails no longer stops the others. Every inbound error names the
  566. inbound it came from (`inbound 7: <message>`), and several failures
  567. are reported together, one per line. So a `success:false` response can
  568. still have applied the edit to the remaining inbounds. The client
  569. record is written after the inbounds, so a failure there is reported
  570. without an `inbound <id>:` prefix and leaves the inbound edits in
  571. place.'
  572. heading: update-an-existing-client-by-email-changes-propagate-to-every-attached-inbound-body-is-the-json-client-payload--supply-the-full-set-of-fields-you-want-to-keep-the-server-replaces-the-row-it-does-not-patch
  573. - content: 'The inbounds are applied concurrently and independently: one that
  574. fails no longer stops the others. Every inbound error names the
  575. inbound it came from (`inbound 7: <message>`), and several failures
  576. are reported together, one per line. So a `success:false` response can
  577. still have removed the client from the remaining inbounds; the client
  578. record is kept in that case, so re-running the call retries exactly
  579. the leftovers. The record and traffic rows are dropped after the
  580. inbounds, so a failure there is reported without an `inbound <id>:`
  581. prefix and leaves the client already removed from every inbound.'
  582. heading: delete-a-client-by-email-removes-it-from-every-attached-inbound-and-drops-its-traffic-record-unless-keeptraffic1-is-passed
  583. - content: 'A WireGuard client brings its stored `allowedIPs` into the new inbound
  584. instead of being given a fresh address, so the call fails with
  585. `inbound <id>: wireguard: allowedIPs entry already used by another
  586. client: <address>` when a different client of the target inbound
  587. already holds it. Free the address on that inbound first — see POST
  588. /panel/api/clients/add for the full rule. Inbounds are applied
  589. independently, so the remaining ones are still attached and a
  590. `success:false` response can be partial.'
  591. heading: attach-an-existing-client-to-one-or-more-additional-inbounds-body-is-json
  592. - content: 'The inbounds are applied concurrently and independently: one that
  593. fails no longer stops the others. Every inbound error names the
  594. inbound it came from (`inbound 7: <message>`), and several failures
  595. are reported together, one per line. So a `success:false` response can
  596. still have detached the remaining inbounds. Detach writes nothing
  597. beyond the inbounds, so every error carries the prefix.'
  598. heading: detach-a-client-from-one-or-more-inbounds-without-deleting-the-client
  599. ---
  600. {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
  601. export default function Layout(props) {
  602. const { APIPage, OpenAPIPage } = props.components ?? {};
  603. // "APIPage" is the old name from v10, this allows both for backward compatibility
  604. const Comp = OpenAPIPage ?? APIPage;
  605. return (
  606. <>
  607. {props.children}
  608. <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 />
  609. </>
  610. );
  611. }