mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-24 20:07:13 +00:00
da01b7637d
* 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>
3162 lines
68 KiB
TypeScript
3162 lines
68 KiB
TypeScript
// Code generated by tools/openapigen. DO NOT EDIT.
|
|
export const SCHEMAS: Record<string, unknown> = {
|
|
"AllSetting": {
|
|
"properties": {
|
|
"datepicker": {
|
|
"type": "string"
|
|
},
|
|
"expireDiff": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"externalTrafficInformEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"externalTrafficInformURI": {
|
|
"type": "string"
|
|
},
|
|
"ipLimitAllowlist": {
|
|
"type": "string"
|
|
},
|
|
"ldapAutoCreate": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapAutoDelete": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapBaseDN": {
|
|
"type": "string"
|
|
},
|
|
"ldapBindDN": {
|
|
"type": "string"
|
|
},
|
|
"ldapDefaultExpiryDays": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapDefaultLimitIP": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapDefaultTotalGB": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapFlagField": {
|
|
"type": "string"
|
|
},
|
|
"ldapHost": {
|
|
"type": "string"
|
|
},
|
|
"ldapInboundTags": {
|
|
"type": "string"
|
|
},
|
|
"ldapInsecureSkipVerify": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapInvertFlag": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapPassword": {
|
|
"type": "string"
|
|
},
|
|
"ldapPort": {
|
|
"maximum": 65535,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapSyncCron": {
|
|
"type": "string"
|
|
},
|
|
"ldapTruthyValues": {
|
|
"type": "string"
|
|
},
|
|
"ldapUseTLS": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapUserAttr": {
|
|
"type": "string"
|
|
},
|
|
"ldapUserFilter": {
|
|
"type": "string"
|
|
},
|
|
"ldapVlessField": {
|
|
"type": "string"
|
|
},
|
|
"outboundDownThreshold": {
|
|
"maximum": 100,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"pageSize": {
|
|
"maximum": 1000,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"panelOutbound": {
|
|
"type": "string"
|
|
},
|
|
"remarkTemplate": {
|
|
"type": "string"
|
|
},
|
|
"restartXrayOnClientDisable": {
|
|
"type": "boolean"
|
|
},
|
|
"sessionMaxAge": {
|
|
"maximum": 525600,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"smtpCpu": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"smtpEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"smtpEnabledEvents": {
|
|
"type": "string"
|
|
},
|
|
"smtpEncryptionType": {
|
|
"type": "string"
|
|
},
|
|
"smtpFrom": {
|
|
"type": "string"
|
|
},
|
|
"smtpFromName": {
|
|
"type": "string"
|
|
},
|
|
"smtpHost": {
|
|
"type": "string"
|
|
},
|
|
"smtpMemory": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"smtpPassword": {
|
|
"type": "string"
|
|
},
|
|
"smtpPort": {
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"smtpTo": {
|
|
"type": "string"
|
|
},
|
|
"smtpUsername": {
|
|
"type": "string"
|
|
},
|
|
"subAnnounce": {
|
|
"type": "string"
|
|
},
|
|
"subCertFile": {
|
|
"type": "string"
|
|
},
|
|
"subClashAutoDetect": {
|
|
"type": "boolean"
|
|
},
|
|
"subClashEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"subClashEnableRouting": {
|
|
"type": "boolean"
|
|
},
|
|
"subClashPath": {
|
|
"type": "string"
|
|
},
|
|
"subClashRules": {
|
|
"type": "string"
|
|
},
|
|
"subClashURI": {
|
|
"type": "string"
|
|
},
|
|
"subClashUserAgentRegex": {
|
|
"type": "string"
|
|
},
|
|
"subDomain": {
|
|
"type": "string"
|
|
},
|
|
"subEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"subEnableRouting": {
|
|
"type": "boolean"
|
|
},
|
|
"subEncrypt": {
|
|
"type": "boolean"
|
|
},
|
|
"subHideSettings": {
|
|
"type": "boolean"
|
|
},
|
|
"subIncyEnableRouting": {
|
|
"type": "boolean"
|
|
},
|
|
"subIncyRoutingRules": {
|
|
"type": "string"
|
|
},
|
|
"subJsonAlwaysArray": {
|
|
"type": "boolean"
|
|
},
|
|
"subJsonAutoDetect": {
|
|
"type": "boolean"
|
|
},
|
|
"subJsonEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"subJsonFinalMask": {
|
|
"type": "string"
|
|
},
|
|
"subJsonMux": {
|
|
"type": "string"
|
|
},
|
|
"subJsonObservatory": {
|
|
"type": "string"
|
|
},
|
|
"subJsonPath": {
|
|
"type": "string"
|
|
},
|
|
"subJsonRules": {
|
|
"type": "string"
|
|
},
|
|
"subJsonURI": {
|
|
"type": "string"
|
|
},
|
|
"subJsonUserAgentRegex": {
|
|
"type": "string"
|
|
},
|
|
"subKeyFile": {
|
|
"type": "string"
|
|
},
|
|
"subListen": {
|
|
"type": "string"
|
|
},
|
|
"subPath": {
|
|
"type": "string"
|
|
},
|
|
"subPort": {
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"subProfileUrl": {
|
|
"type": "string"
|
|
},
|
|
"subRoutingRules": {
|
|
"type": "string"
|
|
},
|
|
"subShowIdentityOnAllLinks": {
|
|
"type": "boolean"
|
|
},
|
|
"subSupportUrl": {
|
|
"type": "string"
|
|
},
|
|
"subThemeDir": {
|
|
"type": "string"
|
|
},
|
|
"subTitle": {
|
|
"type": "string"
|
|
},
|
|
"subURI": {
|
|
"type": "string"
|
|
},
|
|
"subUpdates": {
|
|
"maximum": 525600,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"tgBotAPIServer": {
|
|
"type": "string"
|
|
},
|
|
"tgBotBackup": {
|
|
"type": "boolean"
|
|
},
|
|
"tgBotChatId": {
|
|
"type": "string"
|
|
},
|
|
"tgBotEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"tgBotProxy": {
|
|
"type": "string"
|
|
},
|
|
"tgBotToken": {
|
|
"type": "string"
|
|
},
|
|
"tgCpu": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"tgEnabledEvents": {
|
|
"type": "string"
|
|
},
|
|
"tgLang": {
|
|
"type": "string"
|
|
},
|
|
"tgMemory": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"tgRunTime": {
|
|
"type": "string"
|
|
},
|
|
"timeLocation": {
|
|
"type": "string"
|
|
},
|
|
"trafficDiff": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"trustedProxyCIDRs": {
|
|
"type": "string"
|
|
},
|
|
"twoFactorEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"twoFactorToken": {
|
|
"type": "string"
|
|
},
|
|
"warpUpdateInterval": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"webBasePath": {
|
|
"type": "string"
|
|
},
|
|
"webCertFile": {
|
|
"type": "string"
|
|
},
|
|
"webDomain": {
|
|
"type": "string"
|
|
},
|
|
"webKeyFile": {
|
|
"type": "string"
|
|
},
|
|
"webListen": {
|
|
"type": "string"
|
|
},
|
|
"webPort": {
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"datepicker",
|
|
"expireDiff",
|
|
"externalTrafficInformEnable",
|
|
"externalTrafficInformURI",
|
|
"ipLimitAllowlist",
|
|
"ldapAutoCreate",
|
|
"ldapAutoDelete",
|
|
"ldapBaseDN",
|
|
"ldapBindDN",
|
|
"ldapDefaultExpiryDays",
|
|
"ldapDefaultLimitIP",
|
|
"ldapDefaultTotalGB",
|
|
"ldapEnable",
|
|
"ldapFlagField",
|
|
"ldapHost",
|
|
"ldapInboundTags",
|
|
"ldapInsecureSkipVerify",
|
|
"ldapInvertFlag",
|
|
"ldapPassword",
|
|
"ldapPort",
|
|
"ldapSyncCron",
|
|
"ldapTruthyValues",
|
|
"ldapUseTLS",
|
|
"ldapUserAttr",
|
|
"ldapUserFilter",
|
|
"ldapVlessField",
|
|
"outboundDownThreshold",
|
|
"pageSize",
|
|
"panelOutbound",
|
|
"remarkTemplate",
|
|
"restartXrayOnClientDisable",
|
|
"sessionMaxAge",
|
|
"smtpCpu",
|
|
"smtpEnable",
|
|
"smtpEnabledEvents",
|
|
"smtpEncryptionType",
|
|
"smtpFrom",
|
|
"smtpFromName",
|
|
"smtpHost",
|
|
"smtpMemory",
|
|
"smtpPassword",
|
|
"smtpPort",
|
|
"smtpTo",
|
|
"smtpUsername",
|
|
"subAnnounce",
|
|
"subCertFile",
|
|
"subClashAutoDetect",
|
|
"subClashEnable",
|
|
"subClashEnableRouting",
|
|
"subClashPath",
|
|
"subClashRules",
|
|
"subClashURI",
|
|
"subClashUserAgentRegex",
|
|
"subDomain",
|
|
"subEnable",
|
|
"subEnableRouting",
|
|
"subEncrypt",
|
|
"subHideSettings",
|
|
"subIncyEnableRouting",
|
|
"subIncyRoutingRules",
|
|
"subJsonAlwaysArray",
|
|
"subJsonAutoDetect",
|
|
"subJsonEnable",
|
|
"subJsonFinalMask",
|
|
"subJsonMux",
|
|
"subJsonObservatory",
|
|
"subJsonPath",
|
|
"subJsonRules",
|
|
"subJsonURI",
|
|
"subJsonUserAgentRegex",
|
|
"subKeyFile",
|
|
"subListen",
|
|
"subPath",
|
|
"subPort",
|
|
"subProfileUrl",
|
|
"subRoutingRules",
|
|
"subShowIdentityOnAllLinks",
|
|
"subSupportUrl",
|
|
"subThemeDir",
|
|
"subTitle",
|
|
"subURI",
|
|
"subUpdates",
|
|
"tgBotAPIServer",
|
|
"tgBotBackup",
|
|
"tgBotChatId",
|
|
"tgBotEnable",
|
|
"tgBotProxy",
|
|
"tgBotToken",
|
|
"tgCpu",
|
|
"tgEnabledEvents",
|
|
"tgLang",
|
|
"tgMemory",
|
|
"tgRunTime",
|
|
"timeLocation",
|
|
"trafficDiff",
|
|
"trustedProxyCIDRs",
|
|
"twoFactorEnable",
|
|
"twoFactorToken",
|
|
"warpUpdateInterval",
|
|
"webBasePath",
|
|
"webCertFile",
|
|
"webDomain",
|
|
"webKeyFile",
|
|
"webListen",
|
|
"webPort"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"AllSettingView": {
|
|
"properties": {
|
|
"datepicker": {
|
|
"type": "string"
|
|
},
|
|
"expireDiff": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"externalTrafficInformEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"externalTrafficInformURI": {
|
|
"type": "string"
|
|
},
|
|
"hasApiToken": {
|
|
"type": "boolean"
|
|
},
|
|
"hasLdapPassword": {
|
|
"type": "boolean"
|
|
},
|
|
"hasNordSecret": {
|
|
"type": "boolean"
|
|
},
|
|
"hasSmtpPassword": {
|
|
"type": "boolean"
|
|
},
|
|
"hasTgBotToken": {
|
|
"type": "boolean"
|
|
},
|
|
"hasTwoFactorToken": {
|
|
"type": "boolean"
|
|
},
|
|
"hasWarpSecret": {
|
|
"type": "boolean"
|
|
},
|
|
"ipLimitAllowlist": {
|
|
"type": "string"
|
|
},
|
|
"ldapAutoCreate": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapAutoDelete": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapBaseDN": {
|
|
"type": "string"
|
|
},
|
|
"ldapBindDN": {
|
|
"type": "string"
|
|
},
|
|
"ldapDefaultExpiryDays": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapDefaultLimitIP": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapDefaultTotalGB": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapFlagField": {
|
|
"type": "string"
|
|
},
|
|
"ldapHost": {
|
|
"type": "string"
|
|
},
|
|
"ldapInboundTags": {
|
|
"type": "string"
|
|
},
|
|
"ldapInsecureSkipVerify": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapInvertFlag": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapPassword": {
|
|
"type": "string"
|
|
},
|
|
"ldapPort": {
|
|
"maximum": 65535,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"ldapSyncCron": {
|
|
"type": "string"
|
|
},
|
|
"ldapTruthyValues": {
|
|
"type": "string"
|
|
},
|
|
"ldapUseTLS": {
|
|
"type": "boolean"
|
|
},
|
|
"ldapUserAttr": {
|
|
"type": "string"
|
|
},
|
|
"ldapUserFilter": {
|
|
"type": "string"
|
|
},
|
|
"ldapVlessField": {
|
|
"type": "string"
|
|
},
|
|
"outboundDownThreshold": {
|
|
"maximum": 100,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"pageSize": {
|
|
"maximum": 1000,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"panelOutbound": {
|
|
"type": "string"
|
|
},
|
|
"remarkTemplate": {
|
|
"type": "string"
|
|
},
|
|
"restartXrayOnClientDisable": {
|
|
"type": "boolean"
|
|
},
|
|
"sessionMaxAge": {
|
|
"maximum": 525600,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"smtpCpu": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"smtpEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"smtpEnabledEvents": {
|
|
"type": "string"
|
|
},
|
|
"smtpEncryptionType": {
|
|
"type": "string"
|
|
},
|
|
"smtpFrom": {
|
|
"type": "string"
|
|
},
|
|
"smtpFromName": {
|
|
"type": "string"
|
|
},
|
|
"smtpHost": {
|
|
"type": "string"
|
|
},
|
|
"smtpMemory": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"smtpPassword": {
|
|
"type": "string"
|
|
},
|
|
"smtpPort": {
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"smtpTo": {
|
|
"type": "string"
|
|
},
|
|
"smtpUsername": {
|
|
"type": "string"
|
|
},
|
|
"subAnnounce": {
|
|
"type": "string"
|
|
},
|
|
"subCertFile": {
|
|
"type": "string"
|
|
},
|
|
"subClashAutoDetect": {
|
|
"type": "boolean"
|
|
},
|
|
"subClashEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"subClashEnableRouting": {
|
|
"type": "boolean"
|
|
},
|
|
"subClashPath": {
|
|
"type": "string"
|
|
},
|
|
"subClashRules": {
|
|
"type": "string"
|
|
},
|
|
"subClashURI": {
|
|
"type": "string"
|
|
},
|
|
"subClashUserAgentRegex": {
|
|
"type": "string"
|
|
},
|
|
"subDomain": {
|
|
"type": "string"
|
|
},
|
|
"subEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"subEnableRouting": {
|
|
"type": "boolean"
|
|
},
|
|
"subEncrypt": {
|
|
"type": "boolean"
|
|
},
|
|
"subHideSettings": {
|
|
"type": "boolean"
|
|
},
|
|
"subIncyEnableRouting": {
|
|
"type": "boolean"
|
|
},
|
|
"subIncyRoutingRules": {
|
|
"type": "string"
|
|
},
|
|
"subJsonAlwaysArray": {
|
|
"type": "boolean"
|
|
},
|
|
"subJsonAutoDetect": {
|
|
"type": "boolean"
|
|
},
|
|
"subJsonEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"subJsonFinalMask": {
|
|
"type": "string"
|
|
},
|
|
"subJsonMux": {
|
|
"type": "string"
|
|
},
|
|
"subJsonObservatory": {
|
|
"type": "string"
|
|
},
|
|
"subJsonPath": {
|
|
"type": "string"
|
|
},
|
|
"subJsonRules": {
|
|
"type": "string"
|
|
},
|
|
"subJsonURI": {
|
|
"type": "string"
|
|
},
|
|
"subJsonUserAgentRegex": {
|
|
"type": "string"
|
|
},
|
|
"subKeyFile": {
|
|
"type": "string"
|
|
},
|
|
"subListen": {
|
|
"type": "string"
|
|
},
|
|
"subPath": {
|
|
"type": "string"
|
|
},
|
|
"subPort": {
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"subProfileUrl": {
|
|
"type": "string"
|
|
},
|
|
"subRoutingRules": {
|
|
"type": "string"
|
|
},
|
|
"subShowIdentityOnAllLinks": {
|
|
"type": "boolean"
|
|
},
|
|
"subSupportUrl": {
|
|
"type": "string"
|
|
},
|
|
"subThemeDir": {
|
|
"type": "string"
|
|
},
|
|
"subTitle": {
|
|
"type": "string"
|
|
},
|
|
"subURI": {
|
|
"type": "string"
|
|
},
|
|
"subUpdates": {
|
|
"maximum": 525600,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"tgBotAPIServer": {
|
|
"type": "string"
|
|
},
|
|
"tgBotBackup": {
|
|
"type": "boolean"
|
|
},
|
|
"tgBotChatId": {
|
|
"type": "string"
|
|
},
|
|
"tgBotEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"tgBotProxy": {
|
|
"type": "string"
|
|
},
|
|
"tgBotToken": {
|
|
"type": "string"
|
|
},
|
|
"tgCpu": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"tgEnabledEvents": {
|
|
"type": "string"
|
|
},
|
|
"tgLang": {
|
|
"type": "string"
|
|
},
|
|
"tgMemory": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"tgRunTime": {
|
|
"type": "string"
|
|
},
|
|
"timeLocation": {
|
|
"type": "string"
|
|
},
|
|
"trafficDiff": {
|
|
"maximum": 100,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"trustedProxyCIDRs": {
|
|
"type": "string"
|
|
},
|
|
"twoFactorEnable": {
|
|
"type": "boolean"
|
|
},
|
|
"twoFactorToken": {
|
|
"type": "string"
|
|
},
|
|
"warpUpdateInterval": {
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"webBasePath": {
|
|
"type": "string"
|
|
},
|
|
"webCertFile": {
|
|
"type": "string"
|
|
},
|
|
"webDomain": {
|
|
"type": "string"
|
|
},
|
|
"webKeyFile": {
|
|
"type": "string"
|
|
},
|
|
"webListen": {
|
|
"type": "string"
|
|
},
|
|
"webPort": {
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"datepicker",
|
|
"expireDiff",
|
|
"externalTrafficInformEnable",
|
|
"externalTrafficInformURI",
|
|
"hasApiToken",
|
|
"hasLdapPassword",
|
|
"hasNordSecret",
|
|
"hasSmtpPassword",
|
|
"hasTgBotToken",
|
|
"hasTwoFactorToken",
|
|
"hasWarpSecret",
|
|
"ipLimitAllowlist",
|
|
"ldapAutoCreate",
|
|
"ldapAutoDelete",
|
|
"ldapBaseDN",
|
|
"ldapBindDN",
|
|
"ldapDefaultExpiryDays",
|
|
"ldapDefaultLimitIP",
|
|
"ldapDefaultTotalGB",
|
|
"ldapEnable",
|
|
"ldapFlagField",
|
|
"ldapHost",
|
|
"ldapInboundTags",
|
|
"ldapInsecureSkipVerify",
|
|
"ldapInvertFlag",
|
|
"ldapPassword",
|
|
"ldapPort",
|
|
"ldapSyncCron",
|
|
"ldapTruthyValues",
|
|
"ldapUseTLS",
|
|
"ldapUserAttr",
|
|
"ldapUserFilter",
|
|
"ldapVlessField",
|
|
"outboundDownThreshold",
|
|
"pageSize",
|
|
"panelOutbound",
|
|
"remarkTemplate",
|
|
"restartXrayOnClientDisable",
|
|
"sessionMaxAge",
|
|
"smtpCpu",
|
|
"smtpEnable",
|
|
"smtpEnabledEvents",
|
|
"smtpEncryptionType",
|
|
"smtpFrom",
|
|
"smtpFromName",
|
|
"smtpHost",
|
|
"smtpMemory",
|
|
"smtpPassword",
|
|
"smtpPort",
|
|
"smtpTo",
|
|
"smtpUsername",
|
|
"subAnnounce",
|
|
"subCertFile",
|
|
"subClashAutoDetect",
|
|
"subClashEnable",
|
|
"subClashEnableRouting",
|
|
"subClashPath",
|
|
"subClashRules",
|
|
"subClashURI",
|
|
"subClashUserAgentRegex",
|
|
"subDomain",
|
|
"subEnable",
|
|
"subEnableRouting",
|
|
"subEncrypt",
|
|
"subHideSettings",
|
|
"subIncyEnableRouting",
|
|
"subIncyRoutingRules",
|
|
"subJsonAlwaysArray",
|
|
"subJsonAutoDetect",
|
|
"subJsonEnable",
|
|
"subJsonFinalMask",
|
|
"subJsonMux",
|
|
"subJsonObservatory",
|
|
"subJsonPath",
|
|
"subJsonRules",
|
|
"subJsonURI",
|
|
"subJsonUserAgentRegex",
|
|
"subKeyFile",
|
|
"subListen",
|
|
"subPath",
|
|
"subPort",
|
|
"subProfileUrl",
|
|
"subRoutingRules",
|
|
"subShowIdentityOnAllLinks",
|
|
"subSupportUrl",
|
|
"subThemeDir",
|
|
"subTitle",
|
|
"subURI",
|
|
"subUpdates",
|
|
"tgBotAPIServer",
|
|
"tgBotBackup",
|
|
"tgBotChatId",
|
|
"tgBotEnable",
|
|
"tgBotProxy",
|
|
"tgBotToken",
|
|
"tgCpu",
|
|
"tgEnabledEvents",
|
|
"tgLang",
|
|
"tgMemory",
|
|
"tgRunTime",
|
|
"timeLocation",
|
|
"trafficDiff",
|
|
"trustedProxyCIDRs",
|
|
"twoFactorEnable",
|
|
"twoFactorToken",
|
|
"warpUpdateInterval",
|
|
"webBasePath",
|
|
"webCertFile",
|
|
"webDomain",
|
|
"webKeyFile",
|
|
"webListen",
|
|
"webPort"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ApiToken": {
|
|
"properties": {
|
|
"createdAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"enabled": {
|
|
"type": "boolean"
|
|
},
|
|
"expiresAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"type": "string"
|
|
},
|
|
"token": {
|
|
"description": "SHA-256 hash; the plaintext is shown only once at creation",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"createdAt",
|
|
"enabled",
|
|
"expiresAt",
|
|
"id",
|
|
"name",
|
|
"scope",
|
|
"token"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ApiTokenView": {
|
|
"properties": {
|
|
"createdAt": {
|
|
"example": 1736000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"enabled": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"expiresAt": {
|
|
"example": 0,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"id": {
|
|
"example": 2,
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"example": "central-panel-a",
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"example": "admin",
|
|
"type": "string"
|
|
},
|
|
"token": {
|
|
"example": "new-token-string",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"createdAt",
|
|
"enabled",
|
|
"expiresAt",
|
|
"id",
|
|
"name",
|
|
"scope"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Client": {
|
|
"description": "Client represents a client configuration for Xray inbounds with traffic limits and settings.",
|
|
"properties": {
|
|
"adTag": {
|
|
"example": "0123456789abcdef0123456789abcdef",
|
|
"type": "string"
|
|
},
|
|
"allowedIPs": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"auth": {
|
|
"description": "Auth password (Hysteria)",
|
|
"type": "string"
|
|
},
|
|
"comment": {
|
|
"description": "Client comment",
|
|
"type": "string"
|
|
},
|
|
"created_at": {
|
|
"description": "Creation timestamp",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"email": {
|
|
"description": "Client email identifier",
|
|
"type": "string"
|
|
},
|
|
"enable": {
|
|
"description": "Whether the client is enabled",
|
|
"type": "boolean"
|
|
},
|
|
"expiryTime": {
|
|
"description": "Expiration timestamp",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"flow": {
|
|
"description": "Flow control (XTLS)",
|
|
"type": "string"
|
|
},
|
|
"group": {
|
|
"description": "Logical grouping label",
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"description": "Unique client identifier",
|
|
"type": "string"
|
|
},
|
|
"keepAlive": {
|
|
"type": "integer"
|
|
},
|
|
"limitIp": {
|
|
"description": "IP limit for this client",
|
|
"type": "integer"
|
|
},
|
|
"password": {
|
|
"description": "Client password",
|
|
"type": "string"
|
|
},
|
|
"preSharedKey": {
|
|
"type": "string"
|
|
},
|
|
"privateKey": {
|
|
"type": "string"
|
|
},
|
|
"publicKey": {
|
|
"type": "string"
|
|
},
|
|
"reset": {
|
|
"description": "Reset period in days",
|
|
"type": "integer"
|
|
},
|
|
"resetDay": {
|
|
"description": "Calendar renewal day 1-31, 0 = interval mode",
|
|
"type": "integer"
|
|
},
|
|
"resetMax": {
|
|
"description": "Max auto-renew count, 0 = unlimited",
|
|
"type": "integer"
|
|
},
|
|
"reverse": {
|
|
"allOf": [
|
|
{
|
|
"$ref": "#/components/schemas/ClientReverse"
|
|
}
|
|
],
|
|
"description": "VLESS simple reverse proxy settings",
|
|
"nullable": true
|
|
},
|
|
"secret": {
|
|
"example": "ee1234567890abcdef1234567890abcd7777772e636c6f7564666c6172652e636f6d",
|
|
"type": "string"
|
|
},
|
|
"security": {
|
|
"description": "Security method (e.g., \"auto\", \"aes-128-gcm\")",
|
|
"type": "string"
|
|
},
|
|
"subId": {
|
|
"description": "Subscription identifier",
|
|
"type": "string"
|
|
},
|
|
"tgId": {
|
|
"description": "Telegram user ID for notifications",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"totalGB": {
|
|
"description": "Total traffic limit in GB",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"trafficReset": {
|
|
"description": "Per-client traffic reset cycle, independent of the inbound's own (#5497).",
|
|
"enum": [
|
|
"never",
|
|
"hourly",
|
|
"daily",
|
|
"weekly",
|
|
"monthly"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"trafficResetDay": {
|
|
"maximum": 31,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"updated_at": {
|
|
"description": "Last update timestamp",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"comment",
|
|
"email",
|
|
"enable",
|
|
"expiryTime",
|
|
"limitIp",
|
|
"reset",
|
|
"resetDay",
|
|
"resetMax",
|
|
"security",
|
|
"subId",
|
|
"tgId",
|
|
"totalGB"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ClientInbound": {
|
|
"properties": {
|
|
"clientId": {
|
|
"type": "integer"
|
|
},
|
|
"createdAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"flowOverride": {
|
|
"type": "string"
|
|
},
|
|
"inboundId": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"clientId",
|
|
"createdAt",
|
|
"flowOverride",
|
|
"inboundId"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ClientRecord": {
|
|
"properties": {
|
|
"adTag": {
|
|
"type": "string"
|
|
},
|
|
"allowedIPs": {
|
|
"type": "string"
|
|
},
|
|
"auth": {
|
|
"type": "string"
|
|
},
|
|
"comment": {
|
|
"type": "string"
|
|
},
|
|
"createdAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"email": {
|
|
"type": "string"
|
|
},
|
|
"enable": {
|
|
"type": "boolean"
|
|
},
|
|
"expiryTime": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"flow": {
|
|
"type": "string"
|
|
},
|
|
"group": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"keepAlive": {
|
|
"type": "integer"
|
|
},
|
|
"limitHwid": {
|
|
"type": "integer"
|
|
},
|
|
"limitIp": {
|
|
"type": "integer"
|
|
},
|
|
"password": {
|
|
"type": "string"
|
|
},
|
|
"preSharedKey": {
|
|
"type": "string"
|
|
},
|
|
"privateKey": {
|
|
"type": "string"
|
|
},
|
|
"publicKey": {
|
|
"type": "string"
|
|
},
|
|
"reset": {
|
|
"type": "integer"
|
|
},
|
|
"resetDay": {
|
|
"type": "integer"
|
|
},
|
|
"resetMax": {
|
|
"type": "integer"
|
|
},
|
|
"reverse": {},
|
|
"secret": {
|
|
"type": "string"
|
|
},
|
|
"security": {
|
|
"type": "string"
|
|
},
|
|
"subId": {
|
|
"type": "string"
|
|
},
|
|
"tgId": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"totalGB": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"trafficReset": {
|
|
"type": "string"
|
|
},
|
|
"trafficResetDay": {
|
|
"type": "integer"
|
|
},
|
|
"updatedAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"adTag",
|
|
"allowedIPs",
|
|
"auth",
|
|
"comment",
|
|
"createdAt",
|
|
"email",
|
|
"enable",
|
|
"expiryTime",
|
|
"flow",
|
|
"group",
|
|
"id",
|
|
"keepAlive",
|
|
"limitHwid",
|
|
"limitIp",
|
|
"password",
|
|
"preSharedKey",
|
|
"privateKey",
|
|
"publicKey",
|
|
"reset",
|
|
"resetDay",
|
|
"resetMax",
|
|
"reverse",
|
|
"secret",
|
|
"security",
|
|
"subId",
|
|
"tgId",
|
|
"totalGB",
|
|
"trafficReset",
|
|
"trafficResetDay",
|
|
"updatedAt",
|
|
"uuid"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ClientReverse": {
|
|
"properties": {
|
|
"tag": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"tag"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ClientTraffic": {
|
|
"description": "ClientTraffic represents traffic statistics and limits for a specific client.\nIt tracks upload/download usage, expiry times, and online status for inbound clients.",
|
|
"properties": {
|
|
"down": {
|
|
"example": 2097152,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"email": {
|
|
"example": "user1",
|
|
"type": "string"
|
|
},
|
|
"enable": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"expiryTime": {
|
|
"example": 1735689600000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"id": {
|
|
"example": 14825,
|
|
"type": "integer"
|
|
},
|
|
"inboundId": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"lastOnline": {
|
|
"example": 1735680000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"lastSubFetch": {
|
|
"example": 1735680000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"reset": {
|
|
"example": 0,
|
|
"type": "integer"
|
|
},
|
|
"resetCount": {
|
|
"description": "ResetCount is how many have fired, so a prepaid plan stops on its own.",
|
|
"example": 0,
|
|
"type": "integer"
|
|
},
|
|
"resetDay": {
|
|
"description": "ResetDay renews on that day of each calendar month instead of every\nReset days; 0 keeps the interval behaviour.",
|
|
"example": 0,
|
|
"type": "integer"
|
|
},
|
|
"resetMax": {
|
|
"description": "ResetMax caps how many times auto-renew may fire; 0 means no cap.",
|
|
"example": 0,
|
|
"type": "integer"
|
|
},
|
|
"subId": {
|
|
"example": "i7tvdpeffi0hvvf1",
|
|
"type": "string"
|
|
},
|
|
"total": {
|
|
"example": 10737418240,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"up": {
|
|
"example": 1048576,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"example": "e18c9a96-71bf-48d4-933f-8b9a46d4290c",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"down",
|
|
"email",
|
|
"enable",
|
|
"expiryTime",
|
|
"id",
|
|
"inboundId",
|
|
"lastOnline",
|
|
"lastSubFetch",
|
|
"reset",
|
|
"resetCount",
|
|
"resetDay",
|
|
"resetMax",
|
|
"subId",
|
|
"total",
|
|
"up",
|
|
"uuid"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"FallbackParentInfo": {
|
|
"description": "FallbackParentInfo carries everything the frontend needs to rewrite a\nchild inbound's client link: where to connect (the master's address\nand port) and which path matched on the master's fallbacks array.\nThe frontend already has the master inbound in its dbInbounds list,\nso we only ship identifiers + the match path here.",
|
|
"properties": {
|
|
"masterId": {
|
|
"type": "integer"
|
|
},
|
|
"path": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"masterId"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"GeoCategory": {
|
|
"description": "GeoCategory is one code inside a database, such as geosite's \"google\".",
|
|
"properties": {
|
|
"attributes": {
|
|
"example": [
|
|
"ads",
|
|
"cn"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"code": {
|
|
"example": "google",
|
|
"type": "string"
|
|
},
|
|
"entries": {
|
|
"example": 1284,
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"attributes",
|
|
"code",
|
|
"entries"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"GeoCategoryPage": {
|
|
"description": "GeoCategoryPage is one page of categories plus the unpaged total.",
|
|
"properties": {
|
|
"items": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/GeoCategory"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"total": {
|
|
"example": 1043,
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"items",
|
|
"total"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"GeoEntry": {
|
|
"description": "GeoEntry is a single rule inside a category: a domain rule for geosite\ndatabases, a CIDR for geoip ones.",
|
|
"properties": {
|
|
"kind": {
|
|
"example": "domain",
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"example": "google.com",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"kind",
|
|
"value"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"GeoEntryPage": {
|
|
"description": "GeoEntryPage is one page of category entries plus the unpaged total.",
|
|
"properties": {
|
|
"items": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/GeoEntry"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"total": {
|
|
"example": 1284,
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"items",
|
|
"total"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"GeoFile": {
|
|
"description": "GeoFile describes one .dat database found in the asset directory.",
|
|
"properties": {
|
|
"categories": {
|
|
"example": 1043,
|
|
"type": "integer"
|
|
},
|
|
"error": {
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"example": "site",
|
|
"type": "string"
|
|
},
|
|
"modifiedAt": {
|
|
"example": 1769558400000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"example": "geosite.dat",
|
|
"type": "string"
|
|
},
|
|
"size": {
|
|
"example": 1467392,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"categories",
|
|
"kind",
|
|
"modifiedAt",
|
|
"name",
|
|
"size"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"GeodataTokenIssue": {
|
|
"description": "GeodataTokenIssue reports a routing token the running core would reject,\nor would silently match nothing against.",
|
|
"properties": {
|
|
"code": {
|
|
"example": "blabla",
|
|
"type": "string"
|
|
},
|
|
"file": {
|
|
"example": "geosite.dat",
|
|
"type": "string"
|
|
},
|
|
"reason": {
|
|
"example": "categoryMissing",
|
|
"type": "string"
|
|
},
|
|
"token": {
|
|
"example": "geosite:blabla",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"reason",
|
|
"token"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"HistoryOfSeeders": {
|
|
"description": "HistoryOfSeeders tracks which database seeders have been executed to prevent re-running.",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"seederName": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"seederName"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Host": {
|
|
"properties": {
|
|
"address": {
|
|
"example": "cdn.example.com",
|
|
"type": "string"
|
|
},
|
|
"allowInsecure": {
|
|
"type": "boolean"
|
|
},
|
|
"alpn": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"createdAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"echConfigList": {
|
|
"type": "string"
|
|
},
|
|
"excludeFromSubTypes": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"finalMask": {
|
|
"description": "FinalMask is a JSON object of xray finalmask masks (tcp/udp/quicParams),\nmerged into this host's JSON-subscription stream. Empty = no override.",
|
|
"type": "string"
|
|
},
|
|
"fingerprint": {
|
|
"type": "string"
|
|
},
|
|
"groupId": {
|
|
"type": "string"
|
|
},
|
|
"hostHeader": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"inboundId": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"isDisabled": {
|
|
"type": "boolean"
|
|
},
|
|
"isHidden": {
|
|
"type": "boolean"
|
|
},
|
|
"keepSniBlank": {
|
|
"type": "boolean"
|
|
},
|
|
"mihomoIpVersion": {
|
|
"enum": [
|
|
"dual",
|
|
"ipv4",
|
|
"ipv6",
|
|
"ipv4-prefer",
|
|
"ipv6-prefer"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"mihomoX25519": {
|
|
"type": "boolean"
|
|
},
|
|
"muxParams": {},
|
|
"nodeGuids": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"overrideSniFromAddress": {
|
|
"type": "boolean"
|
|
},
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"pinnedPeerCertSha256": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"port": {
|
|
"example": 8443,
|
|
"maximum": 65535,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"remark": {
|
|
"example": "cdn-front",
|
|
"maxLength": 256,
|
|
"type": "string"
|
|
},
|
|
"security": {
|
|
"enum": [
|
|
"same",
|
|
"tls",
|
|
"none",
|
|
"reality"
|
|
],
|
|
"example": "same",
|
|
"type": "string"
|
|
},
|
|
"serverDescription": {
|
|
"maxLength": 64,
|
|
"type": "string"
|
|
},
|
|
"shuffleHost": {
|
|
"type": "boolean"
|
|
},
|
|
"sni": {
|
|
"type": "string"
|
|
},
|
|
"sockoptParams": {},
|
|
"sortOrder": {
|
|
"type": "integer"
|
|
},
|
|
"tags": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"updatedAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"verifyPeerCertByName": {
|
|
"type": "string"
|
|
},
|
|
"vlessRoute": {
|
|
"description": "Single VLESS route value (0-65535) baked into the subscription UUID's 3rd\ngroup (bytes 6-7), which xray reads via net.PortFromBytes(id[6:8]). Empty = none.",
|
|
"example": "443",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"address",
|
|
"allowInsecure",
|
|
"alpn",
|
|
"createdAt",
|
|
"echConfigList",
|
|
"excludeFromSubTypes",
|
|
"finalMask",
|
|
"fingerprint",
|
|
"groupId",
|
|
"hostHeader",
|
|
"id",
|
|
"inboundId",
|
|
"isDisabled",
|
|
"isHidden",
|
|
"keepSniBlank",
|
|
"mihomoIpVersion",
|
|
"mihomoX25519",
|
|
"muxParams",
|
|
"overrideSniFromAddress",
|
|
"path",
|
|
"pinnedPeerCertSha256",
|
|
"port",
|
|
"remark",
|
|
"security",
|
|
"serverDescription",
|
|
"shuffleHost",
|
|
"sni",
|
|
"sockoptParams",
|
|
"sortOrder",
|
|
"tags",
|
|
"updatedAt",
|
|
"verifyPeerCertByName",
|
|
"vlessRoute"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"HostGroup": {
|
|
"properties": {
|
|
"allowInsecure": {
|
|
"type": "boolean"
|
|
},
|
|
"alpn": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"echConfigList": {
|
|
"type": "string"
|
|
},
|
|
"excludeFromSubTypes": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"finalMask": {
|
|
"type": "string"
|
|
},
|
|
"fingerprint": {
|
|
"type": "string"
|
|
},
|
|
"groupId": {
|
|
"type": "string"
|
|
},
|
|
"hostHeader": {
|
|
"type": "string"
|
|
},
|
|
"hosts": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"inboundIds": {
|
|
"items": {
|
|
"type": "integer"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"isDisabled": {
|
|
"type": "boolean"
|
|
},
|
|
"isHidden": {
|
|
"type": "boolean"
|
|
},
|
|
"keepSniBlank": {
|
|
"type": "boolean"
|
|
},
|
|
"mihomoIpVersion": {
|
|
"enum": [
|
|
"dual",
|
|
"ipv4",
|
|
"ipv6",
|
|
"ipv4-prefer",
|
|
"ipv6-prefer"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"mihomoX25519": {
|
|
"type": "boolean"
|
|
},
|
|
"muxParams": {
|
|
"type": "string"
|
|
},
|
|
"nodeGuids": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"overrideSniFromAddress": {
|
|
"type": "boolean"
|
|
},
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"pinnedPeerCertSha256": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"port": {
|
|
"maximum": 65535,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"remark": {
|
|
"maxLength": 256,
|
|
"type": "string"
|
|
},
|
|
"security": {
|
|
"enum": [
|
|
"same",
|
|
"tls",
|
|
"none",
|
|
"reality"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"serverDescription": {
|
|
"maxLength": 64,
|
|
"type": "string"
|
|
},
|
|
"shuffleHost": {
|
|
"type": "boolean"
|
|
},
|
|
"sni": {
|
|
"type": "string"
|
|
},
|
|
"sockoptParams": {
|
|
"type": "string"
|
|
},
|
|
"sortOrder": {
|
|
"type": "integer"
|
|
},
|
|
"tags": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"verifyPeerCertByName": {
|
|
"type": "string"
|
|
},
|
|
"vlessRoute": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"allowInsecure",
|
|
"alpn",
|
|
"echConfigList",
|
|
"excludeFromSubTypes",
|
|
"finalMask",
|
|
"fingerprint",
|
|
"groupId",
|
|
"hostHeader",
|
|
"hosts",
|
|
"inboundIds",
|
|
"isDisabled",
|
|
"isHidden",
|
|
"keepSniBlank",
|
|
"mihomoIpVersion",
|
|
"mihomoX25519",
|
|
"muxParams",
|
|
"nodeGuids",
|
|
"overrideSniFromAddress",
|
|
"path",
|
|
"pinnedPeerCertSha256",
|
|
"port",
|
|
"remark",
|
|
"security",
|
|
"serverDescription",
|
|
"shuffleHost",
|
|
"sni",
|
|
"sockoptParams",
|
|
"sortOrder",
|
|
"tags",
|
|
"verifyPeerCertByName",
|
|
"vlessRoute"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Inbound": {
|
|
"description": "Inbound represents an Xray inbound configuration with traffic statistics and settings.",
|
|
"properties": {
|
|
"clientStats": {
|
|
"description": "Client traffic statistics",
|
|
"items": {
|
|
"$ref": "#/components/schemas/ClientTraffic"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"disableFlow": {
|
|
"example": false,
|
|
"type": "boolean"
|
|
},
|
|
"down": {
|
|
"description": "Download traffic in bytes",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"enable": {
|
|
"description": "Whether the inbound is enabled",
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"expiryTime": {
|
|
"description": "Expiration timestamp",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"fallbackParent": {
|
|
"allOf": [
|
|
{
|
|
"$ref": "#/components/schemas/FallbackParentInfo"
|
|
}
|
|
],
|
|
"description": "FallbackParent is populated by the API layer when this inbound is\nattached as a fallback child of a VLESS/Trojan TCP-TLS master.\nThe frontend uses it to rewrite client-share links so they advertise\nthe master's externally reachable endpoint instead of the child's\nloopback listen. Not persisted.",
|
|
"nullable": true
|
|
},
|
|
"id": {
|
|
"description": "Unique identifier",
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"lastTrafficResetTime": {
|
|
"description": "Last traffic reset timestamp",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"listen": {
|
|
"description": "Xray configuration fields",
|
|
"type": "string"
|
|
},
|
|
"nodeId": {
|
|
"nullable": true,
|
|
"type": "integer"
|
|
},
|
|
"originNodeGuid": {
|
|
"description": "OriginNodeGuid is the panelGuid of the node that physically hosts this\ninbound, propagated up across hops (#4983). Empty for an inbound that\nlives on this panel's own xray; set to the originating node's GUID when\nthe inbound was synced from a node (kept as-is across further hops). Lets\nthe master attribute a deeply nested inbound to the real node instead of\nthe intermediate one it was fetched through.",
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"example": 443,
|
|
"maximum": 65535,
|
|
"minimum": 0,
|
|
"type": "integer"
|
|
},
|
|
"protocol": {
|
|
"enum": [
|
|
"vmess",
|
|
"vless",
|
|
"trojan",
|
|
"shadowsocks",
|
|
"wireguard",
|
|
"hysteria",
|
|
"http",
|
|
"mixed",
|
|
"tunnel",
|
|
"tun",
|
|
"mtproto"
|
|
],
|
|
"example": "vless",
|
|
"type": "string"
|
|
},
|
|
"remark": {
|
|
"description": "Human-readable remark",
|
|
"example": "VLESS-443",
|
|
"type": "string"
|
|
},
|
|
"settings": {},
|
|
"shareAddr": {
|
|
"type": "string"
|
|
},
|
|
"shareAddrStrategy": {
|
|
"enum": [
|
|
"node",
|
|
"listen",
|
|
"custom"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"sniffing": {},
|
|
"streamSettings": {},
|
|
"subSortIndex": {
|
|
"description": "1-based sort order of this inbound's links in subscription output only (lower first; ties by id)",
|
|
"example": 1,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"tag": {
|
|
"example": "in-443-tcp",
|
|
"type": "string"
|
|
},
|
|
"total": {
|
|
"description": "Total traffic limit in bytes",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"trafficReset": {
|
|
"description": "Traffic reset schedule",
|
|
"enum": [
|
|
"never",
|
|
"hourly",
|
|
"daily",
|
|
"weekly",
|
|
"monthly"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"trafficResetDay": {
|
|
"description": "Day of month for monthly traffic resets",
|
|
"example": 1,
|
|
"maximum": 31,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"up": {
|
|
"description": "Upload traffic in bytes",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"clientStats",
|
|
"disableFlow",
|
|
"down",
|
|
"enable",
|
|
"expiryTime",
|
|
"id",
|
|
"lastTrafficResetTime",
|
|
"listen",
|
|
"port",
|
|
"protocol",
|
|
"remark",
|
|
"settings",
|
|
"shareAddr",
|
|
"shareAddrStrategy",
|
|
"sniffing",
|
|
"streamSettings",
|
|
"subSortIndex",
|
|
"tag",
|
|
"total",
|
|
"trafficReset",
|
|
"trafficResetDay",
|
|
"up"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"InboundClientIps": {
|
|
"description": "InboundClientIps stores IP addresses associated with inbound clients for access control.",
|
|
"properties": {
|
|
"clientEmail": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"ips": {}
|
|
},
|
|
"required": [
|
|
"clientEmail",
|
|
"id",
|
|
"ips"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"InboundFallback": {
|
|
"properties": {
|
|
"alpn": {
|
|
"type": "string"
|
|
},
|
|
"childId": {
|
|
"type": "integer"
|
|
},
|
|
"dest": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"masterId": {
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"sortOrder": {
|
|
"type": "integer"
|
|
},
|
|
"xver": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"alpn",
|
|
"childId",
|
|
"dest",
|
|
"id",
|
|
"masterId",
|
|
"name",
|
|
"path",
|
|
"sortOrder",
|
|
"xver"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"InboundOption": {
|
|
"properties": {
|
|
"enable": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"listen": {
|
|
"type": "string"
|
|
},
|
|
"mtprotoDomain": {
|
|
"type": "string"
|
|
},
|
|
"nodeAddress": {
|
|
"description": "Share-host resolution inputs, mirroring the subscription's\nresolveInboundAddress so the clients page renders a node-managed WireGuard\nEndpoint that points at the node, not the master panel. NodeAddress is the\nhosting node's externally reachable address (empty for this panel's own\ninbounds); Listen and ShareAddrStrategy/ShareAddr feed the same\nnode→listen→custom fallback the share/QR links already use.",
|
|
"type": "string"
|
|
},
|
|
"nodeId": {
|
|
"description": "Hosting node; nil for this panel's own inbounds. Lets the clients\npage map a node filter onto inbound IDs (#4997).",
|
|
"nullable": true,
|
|
"type": "integer"
|
|
},
|
|
"port": {
|
|
"example": 443,
|
|
"type": "integer"
|
|
},
|
|
"protocol": {
|
|
"example": "vless",
|
|
"type": "string"
|
|
},
|
|
"remark": {
|
|
"example": "VLESS-443",
|
|
"type": "string"
|
|
},
|
|
"shareAddr": {
|
|
"type": "string"
|
|
},
|
|
"shareAddrStrategy": {
|
|
"type": "string"
|
|
},
|
|
"ssMethod": {
|
|
"type": "string"
|
|
},
|
|
"tag": {
|
|
"example": "in-443-tcp",
|
|
"type": "string"
|
|
},
|
|
"tlsFlowCapable": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"wgDns": {
|
|
"type": "string"
|
|
},
|
|
"wgMtu": {
|
|
"type": "integer"
|
|
},
|
|
"wgPublicKey": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"enable",
|
|
"id",
|
|
"port",
|
|
"protocol",
|
|
"remark",
|
|
"ssMethod",
|
|
"tag",
|
|
"tlsFlowCapable"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Msg": {
|
|
"properties": {
|
|
"msg": {
|
|
"type": "string"
|
|
},
|
|
"obj": {},
|
|
"success": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"msg",
|
|
"obj",
|
|
"success"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Node": {
|
|
"description": "Node represents a remote 3x-ui panel registered with the central panel.\nThe central panel polls each node's existing /panel/api/server/status\nendpoint over HTTP using the per-node ApiToken to populate the runtime\nstatus fields below.",
|
|
"properties": {
|
|
"activeCount": {
|
|
"example": 23,
|
|
"type": "integer"
|
|
},
|
|
"address": {
|
|
"example": "node1.example.com",
|
|
"type": "string"
|
|
},
|
|
"allowPrivateAddress": {
|
|
"type": "boolean"
|
|
},
|
|
"basePath": {
|
|
"example": "/",
|
|
"type": "string"
|
|
},
|
|
"clientCount": {
|
|
"example": 27,
|
|
"type": "integer"
|
|
},
|
|
"configDirty": {
|
|
"type": "boolean"
|
|
},
|
|
"configDirtyAt": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"cpuPct": {
|
|
"example": 23.5,
|
|
"type": "number"
|
|
},
|
|
"createdAt": {
|
|
"example": 1700000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"depletedCount": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"disabledCount": {
|
|
"example": 3,
|
|
"type": "integer"
|
|
},
|
|
"enable": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"guid": {
|
|
"description": "Guid is the remote panel's stable self-identifier (its panelGuid),\nlearned from each heartbeat. It is the globally stable node identity used\nto attribute online clients/inbounds to the physical node across a chain\nof nodes (#4983); panel-local autoincrement ids don't survive a hop.\nObserved-state only — never user-edited.",
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"inboundCount": {
|
|
"example": 5,
|
|
"type": "integer"
|
|
},
|
|
"inboundSyncMode": {
|
|
"enum": [
|
|
"all",
|
|
"selected"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"inboundTags": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"lastError": {
|
|
"type": "string"
|
|
},
|
|
"lastHeartbeat": {
|
|
"description": "unix seconds, 0 = never",
|
|
"example": 1700000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"latencyMs": {
|
|
"example": 42,
|
|
"type": "integer"
|
|
},
|
|
"memPct": {
|
|
"example": 45.1,
|
|
"type": "number"
|
|
},
|
|
"name": {
|
|
"example": "de-fra-1",
|
|
"type": "string"
|
|
},
|
|
"netDown": {
|
|
"example": 2097152,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"netUp": {
|
|
"example": 1048576,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"onlineCount": {
|
|
"example": 3,
|
|
"type": "integer"
|
|
},
|
|
"outboundTag": {
|
|
"type": "string"
|
|
},
|
|
"panelVersion": {
|
|
"example": "v3.x.x",
|
|
"type": "string"
|
|
},
|
|
"parentGuid": {
|
|
"description": "ParentGuid + Transitive are set only when a node is surfaced as part of a\nnode tree (#4983): direct nodes carry the master panel's own GUID, a\ntransitive sub-node carries its parent node's GUID. Transitive nodes are\nread-only projections (Id == 0, not persisted) — never edited or deployed.",
|
|
"type": "string"
|
|
},
|
|
"pinnedCertSha256": {
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"example": 2053,
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"remark": {
|
|
"type": "string"
|
|
},
|
|
"scheme": {
|
|
"enum": [
|
|
"http",
|
|
"https"
|
|
],
|
|
"example": "https",
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"description": "Heartbeat-updated fields. UpdatedAt advances on every probe even when\nthe row is otherwise unchanged so the UI's \"last seen\" tooltip is\ntruthful without us having to read LastHeartbeat separately.\nonline|offline|unknown",
|
|
"example": "online",
|
|
"type": "string"
|
|
},
|
|
"tlsVerifyMode": {
|
|
"enum": [
|
|
"verify",
|
|
"skip",
|
|
"pin",
|
|
"mtls"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"transitive": {
|
|
"type": "boolean"
|
|
},
|
|
"updatedAt": {
|
|
"example": 1700000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"uptimeSecs": {
|
|
"example": 86400,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"xrayError": {
|
|
"type": "string"
|
|
},
|
|
"xrayState": {
|
|
"description": "XrayState and XrayError are captured from the remote node's /panel/api/server/status\nduring heartbeats. They let the central panel distinguish \"panel API reachable\"\n(status=online) from \"Xray core itself has failed on the node\" for monitoring.",
|
|
"type": "string"
|
|
},
|
|
"xrayVersion": {
|
|
"example": "25.10.31",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"activeCount",
|
|
"address",
|
|
"allowPrivateAddress",
|
|
"basePath",
|
|
"clientCount",
|
|
"configDirty",
|
|
"configDirtyAt",
|
|
"cpuPct",
|
|
"createdAt",
|
|
"depletedCount",
|
|
"disabledCount",
|
|
"enable",
|
|
"guid",
|
|
"id",
|
|
"inboundCount",
|
|
"inboundSyncMode",
|
|
"inboundTags",
|
|
"lastError",
|
|
"lastHeartbeat",
|
|
"latencyMs",
|
|
"memPct",
|
|
"name",
|
|
"netDown",
|
|
"netUp",
|
|
"onlineCount",
|
|
"outboundTag",
|
|
"panelVersion",
|
|
"pinnedCertSha256",
|
|
"port",
|
|
"remark",
|
|
"scheme",
|
|
"status",
|
|
"tlsVerifyMode",
|
|
"updatedAt",
|
|
"uptimeSecs",
|
|
"xrayError",
|
|
"xrayState",
|
|
"xrayVersion"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"NodeMutationRequest": {
|
|
"description": "NodeMutationRequest is the node write/probe contract. ApiToken is accepted\nonly as input. On update, nil means keep the stored token; replacement and\nclearing are explicit and mutually exclusive.",
|
|
"properties": {
|
|
"address": {
|
|
"type": "string"
|
|
},
|
|
"allowPrivateAddress": {
|
|
"type": "boolean"
|
|
},
|
|
"apiToken": {
|
|
"nullable": true,
|
|
"type": "string"
|
|
},
|
|
"basePath": {
|
|
"type": "string"
|
|
},
|
|
"clearApiToken": {
|
|
"type": "boolean"
|
|
},
|
|
"enable": {
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"inboundSyncMode": {
|
|
"enum": [
|
|
"all",
|
|
"selected"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"inboundTags": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"outboundTag": {
|
|
"type": "string"
|
|
},
|
|
"pinnedCertSha256": {
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"maximum": 65535,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"remark": {
|
|
"type": "string"
|
|
},
|
|
"scheme": {
|
|
"enum": [
|
|
"http",
|
|
"https"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"tlsVerifyMode": {
|
|
"enum": [
|
|
"verify",
|
|
"skip",
|
|
"pin",
|
|
"mtls"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"address",
|
|
"allowPrivateAddress",
|
|
"basePath",
|
|
"enable",
|
|
"id",
|
|
"inboundSyncMode",
|
|
"inboundTags",
|
|
"name",
|
|
"outboundTag",
|
|
"pinnedCertSha256",
|
|
"port",
|
|
"remark",
|
|
"scheme",
|
|
"tlsVerifyMode"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"NodeView": {
|
|
"description": "NodeView is the browser/API read contract for nodes. Credentials are\nwrite-only: responses expose only whether a node has a token configured.",
|
|
"properties": {
|
|
"activeCount": {
|
|
"example": 20,
|
|
"type": "integer"
|
|
},
|
|
"address": {
|
|
"example": "node.example.com",
|
|
"type": "string"
|
|
},
|
|
"allowPrivateAddress": {
|
|
"example": false,
|
|
"type": "boolean"
|
|
},
|
|
"basePath": {
|
|
"example": "/",
|
|
"type": "string"
|
|
},
|
|
"clientCount": {
|
|
"example": 25,
|
|
"type": "integer"
|
|
},
|
|
"configDirty": {
|
|
"example": false,
|
|
"type": "boolean"
|
|
},
|
|
"configDirtyAt": {
|
|
"example": 0,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"cpuPct": {
|
|
"example": 12.5,
|
|
"type": "number"
|
|
},
|
|
"createdAt": {
|
|
"example": 1700000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"depletedCount": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"disabledCount": {
|
|
"example": 2,
|
|
"type": "integer"
|
|
},
|
|
"enable": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"guid": {
|
|
"example": "node-guid",
|
|
"type": "string"
|
|
},
|
|
"hasApiToken": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"inboundCount": {
|
|
"example": 3,
|
|
"type": "integer"
|
|
},
|
|
"inboundSyncMode": {
|
|
"example": "all",
|
|
"type": "string"
|
|
},
|
|
"inboundTags": {
|
|
"example": [
|
|
"in-443-tcp"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"lastError": {
|
|
"type": "string"
|
|
},
|
|
"lastHeartbeat": {
|
|
"example": 1700000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"latencyMs": {
|
|
"example": 42,
|
|
"type": "integer"
|
|
},
|
|
"memPct": {
|
|
"example": 45.2,
|
|
"type": "number"
|
|
},
|
|
"name": {
|
|
"example": "edge-1",
|
|
"type": "string"
|
|
},
|
|
"netDown": {
|
|
"example": 1048576,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"netUp": {
|
|
"example": 2097152,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"onlineCount": {
|
|
"example": 5,
|
|
"type": "integer"
|
|
},
|
|
"outboundTag": {
|
|
"example": "direct",
|
|
"type": "string"
|
|
},
|
|
"panelVersion": {
|
|
"example": "v3.x.x",
|
|
"type": "string"
|
|
},
|
|
"parentGuid": {
|
|
"type": "string"
|
|
},
|
|
"pinnedCertSha256": {
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"example": 2053,
|
|
"type": "integer"
|
|
},
|
|
"remark": {
|
|
"example": "Primary edge",
|
|
"type": "string"
|
|
},
|
|
"scheme": {
|
|
"example": "https",
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"example": "online",
|
|
"type": "string"
|
|
},
|
|
"tlsVerifyMode": {
|
|
"example": "verify",
|
|
"type": "string"
|
|
},
|
|
"transitive": {
|
|
"example": false,
|
|
"type": "boolean"
|
|
},
|
|
"updatedAt": {
|
|
"example": 1700003600,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"uptimeSecs": {
|
|
"example": 86400,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"xrayError": {
|
|
"type": "string"
|
|
},
|
|
"xrayState": {
|
|
"example": "running",
|
|
"type": "string"
|
|
},
|
|
"xrayVersion": {
|
|
"example": "25.10.31",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"activeCount",
|
|
"address",
|
|
"allowPrivateAddress",
|
|
"basePath",
|
|
"clientCount",
|
|
"configDirty",
|
|
"configDirtyAt",
|
|
"cpuPct",
|
|
"createdAt",
|
|
"depletedCount",
|
|
"disabledCount",
|
|
"enable",
|
|
"guid",
|
|
"hasApiToken",
|
|
"id",
|
|
"inboundCount",
|
|
"inboundSyncMode",
|
|
"inboundTags",
|
|
"lastError",
|
|
"lastHeartbeat",
|
|
"latencyMs",
|
|
"memPct",
|
|
"name",
|
|
"netDown",
|
|
"netUp",
|
|
"onlineCount",
|
|
"outboundTag",
|
|
"panelVersion",
|
|
"pinnedCertSha256",
|
|
"port",
|
|
"remark",
|
|
"scheme",
|
|
"status",
|
|
"tlsVerifyMode",
|
|
"updatedAt",
|
|
"uptimeSecs",
|
|
"xrayError",
|
|
"xrayState",
|
|
"xrayVersion"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"OutboundTraffics": {
|
|
"description": "OutboundTraffics tracks traffic statistics for Xray outbound connections.",
|
|
"properties": {
|
|
"down": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"tag": {
|
|
"type": "string"
|
|
},
|
|
"total": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"up": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"down",
|
|
"id",
|
|
"tag",
|
|
"total",
|
|
"up"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"PanelUpdateStatus": {
|
|
"description": "PanelUpdateStatus reports the outcome of the most recently launched panel\nself-update. RunID lets the caller confirm this status belongs to the\nupdate it started rather than a stale result left over from an earlier\nrun; State is one of \"pending\", \"success\", or \"failed\". RunID is a decimal\nstring, not a JSON number: it's a formatted UnixNano timestamp, and\nJavaScript's number type can't represent that precisely (it exceeds\nNumber.MAX_SAFE_INTEGER), which would let two different runs round to the\nsame value on the wire and defeat the whole point of this field.",
|
|
"properties": {
|
|
"exitCode": {
|
|
"example": 0,
|
|
"type": "integer"
|
|
},
|
|
"finishedAt": {
|
|
"example": 1735689612,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"runId": {
|
|
"example": "1735689600123456789",
|
|
"type": "string"
|
|
},
|
|
"state": {
|
|
"example": "success",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"exitCode",
|
|
"finishedAt",
|
|
"runId",
|
|
"state"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ProbeResultUI": {
|
|
"properties": {
|
|
"cpuPct": {
|
|
"example": 12.5,
|
|
"type": "number"
|
|
},
|
|
"error": {
|
|
"type": "string"
|
|
},
|
|
"latencyMs": {
|
|
"example": 42,
|
|
"type": "integer"
|
|
},
|
|
"memPct": {
|
|
"example": 45.2,
|
|
"type": "number"
|
|
},
|
|
"panelVersion": {
|
|
"example": "v3.x.x",
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"example": "online",
|
|
"type": "string"
|
|
},
|
|
"uptimeSecs": {
|
|
"example": 86400,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"xrayError": {
|
|
"type": "string"
|
|
},
|
|
"xrayState": {
|
|
"description": "XrayState/XrayError are populated on successful probes even when the node's\nXray core is not healthy. The UI uses them for a distinct \"panel ok, xray failed\" indicator.",
|
|
"type": "string"
|
|
},
|
|
"xrayVersion": {
|
|
"example": "25.10.31",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"cpuPct",
|
|
"error",
|
|
"latencyMs",
|
|
"memPct",
|
|
"panelVersion",
|
|
"status",
|
|
"uptimeSecs",
|
|
"xrayError",
|
|
"xrayState",
|
|
"xrayVersion"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"RealityScanResult": {
|
|
"properties": {
|
|
"alpn": {
|
|
"example": "h2",
|
|
"type": "string"
|
|
},
|
|
"certChainValid": {
|
|
"description": "CertChainValid ignores the name: a trusted chain presented for other names\nstill has serverNames the panel can offer instead of the failing SNI.",
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"certIssuer": {
|
|
"example": "Google Trust Services",
|
|
"type": "string"
|
|
},
|
|
"certSubject": {
|
|
"example": "cloudflare.com",
|
|
"type": "string"
|
|
},
|
|
"certValid": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"curveID": {
|
|
"example": "X25519",
|
|
"type": "string"
|
|
},
|
|
"feasible": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"h2": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"host": {
|
|
"example": "www.cloudflare.com",
|
|
"type": "string"
|
|
},
|
|
"ip": {
|
|
"example": "104.16.124.96",
|
|
"type": "string"
|
|
},
|
|
"latencyMs": {
|
|
"example": 180,
|
|
"type": "integer"
|
|
},
|
|
"notAfter": {
|
|
"example": "2026-08-01T00:00:00Z",
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"example": 443,
|
|
"type": "integer"
|
|
},
|
|
"privateTarget": {
|
|
"description": "PrivateTarget marks a target that resolves to a loopback/private/link-local\naddress: blocked before the probe unless the caller opted in, then flagged.",
|
|
"example": false,
|
|
"type": "boolean"
|
|
},
|
|
"reason": {
|
|
"type": "string"
|
|
},
|
|
"serverNames": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"target": {
|
|
"example": "www.cloudflare.com:443",
|
|
"type": "string"
|
|
},
|
|
"tls13": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"tlsVersion": {
|
|
"example": "1.3",
|
|
"type": "string"
|
|
},
|
|
"x25519": {
|
|
"example": true,
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"alpn",
|
|
"certChainValid",
|
|
"certIssuer",
|
|
"certSubject",
|
|
"certValid",
|
|
"curveID",
|
|
"feasible",
|
|
"h2",
|
|
"host",
|
|
"ip",
|
|
"latencyMs",
|
|
"notAfter",
|
|
"port",
|
|
"privateTarget",
|
|
"reason",
|
|
"serverNames",
|
|
"target",
|
|
"tls13",
|
|
"tlsVersion",
|
|
"x25519"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Setting": {
|
|
"description": "Setting stores key-value configuration settings for the 3x-ui panel.",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"key": {
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"key",
|
|
"value"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"SubBalancer": {
|
|
"description": "SubBalancer is one extra JSON-subscription config document whose members are\nthe selected inbounds' proxy outbounds. SortOrder shares SubSortIndex semantics.",
|
|
"properties": {
|
|
"createdAt": {
|
|
"example": 1710000000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"enabled": {
|
|
"description": "No gorm default:true — a bool default makes an explicit false at insert\ncollapse back to the column default (zero value is skipped).",
|
|
"example": true,
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"example": 1,
|
|
"type": "integer"
|
|
},
|
|
"inboundIds": {
|
|
"example": [
|
|
1,
|
|
3
|
|
],
|
|
"items": {
|
|
"type": "integer"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"remark": {
|
|
"example": "auto-fastest",
|
|
"maxLength": 256,
|
|
"type": "string"
|
|
},
|
|
"sortOrder": {
|
|
"example": 1,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
},
|
|
"strategy": {
|
|
"enum": [
|
|
"leastLoad",
|
|
"leastPing",
|
|
"random",
|
|
"roundRobin"
|
|
],
|
|
"example": "random",
|
|
"type": "string"
|
|
},
|
|
"updatedAt": {
|
|
"example": 1710000000000,
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"createdAt",
|
|
"enabled",
|
|
"id",
|
|
"inboundIds",
|
|
"remark",
|
|
"sortOrder",
|
|
"strategy",
|
|
"updatedAt"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"User": {
|
|
"description": "User represents a user account in the 3x-ui panel.",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"password": {
|
|
"type": "string"
|
|
},
|
|
"username": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"password",
|
|
"username"
|
|
],
|
|
"type": "object"
|
|
}
|
|
};
|