# Core Routes This file lists the current HTTP routes exposed by Core, grouped by access level. ## Common conventions - Authenticated routes use JWT unless noted otherwise. - Admin routes require `role = admin`. - Node-private routes require the `x-node-auth-key` header and are documented separately in [`core-private-routes.md`](./core-private-routes.md). - The API returns raw JSON objects and arrays, not a wrapper object. ## Public routes | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/health` | none | `{ status: 'ok', timestamp }` | | `GET` | `/metrics` | none | Prometheus text format | | `POST` | `/auth/register` | `RegisterDto` | Creates a user account | | `POST` | `/auth/login` | `LoginDto` | Returns JWT tokens | | `POST` | `/auth/refresh` | `RefreshTokenDto` | Returns new JWT tokens | | `POST` | `/auth/telegram` | `TelegramAuthDto` | Telegram OAuth login | | `GET` | `/auth/telegram/bot-id` | none | `{ botId }` | | `GET` | `/public/settings/access` | none | Public panel and subscription host/path settings | | `GET` | `/sub/:uuid/info` | query string and request IP | Returns `SubscriptionInfo` JSON | | `GET` | `/sub/:uuid` | `format=v2ray|clash|singbox` | Returns encoded subscription content | ### `/sub/:uuid` output - `format=v2ray` - plain text, newline-separated URIs - `format=clash` - YAML with `proxies` - `format=singbox` - JSON with `outbounds` - unknown or missing `format` falls back to `v2ray` ## Authenticated user routes | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/auth/me` | none | Current user without `passwordHash` | | `POST` | `/auth/telegram/link` | `TelegramAuthDto` | Links Telegram to the current account | | `DELETE` | `/auth/telegram/unlink` | none | Unlinks Telegram from the current account | | `POST` | `/auth/referral-code/apply` | `{ code: string }` | Pending user self-approves via a referral code | | `GET` | `/me` | none | Current user without `passwordHash` | | `PATCH` | `/me/profile` | `UpdateProfileDto` | Updates name, email, or password | | `GET` | `/me/stats` | none | `UserStats` | | `GET` | `/me/traffic/daily` | none | Daily traffic series | | `GET` | `/me/traffic/hourly-dist` | none | Hour-of-day distribution | | `GET` | `/me/traffic` | `period=30d|7d|1d|1h` | Period traffic series | | `GET` | `/me/traffic/raw` | none | Raw per-minute traffic records | | `GET` | `/me/referral/referees` | none | Users invited by the current user | | `GET` | `/me/subscriptions/:id/usage` | `from?`, `to?` | Per-subscription usage for the current user | | `GET` | `/me/node-protocols` | none | Available node protocols for the current user | | `GET` | `/me/balance` | none | `{ balance }` | | `GET` | `/me/balance/transactions` | none | User balance transaction history | | `GET` | `/me/subscriptions` | none | User subscriptions | | `GET` | `/me/links` | none | All user subscription links | | `GET` | `/me/configs` | none | Available node/protocol configs for the current user | | `POST` | `/me/links` | `CreateUserLinkDto` | Creates a combined link or a per-subscription link | | `POST` | `/me/links/:id/reset` | none | Resets the link UUID | | `PATCH` | `/me/links/:id` | `UpdateUserLinkDto` | Renames, enables/disables, or reconfigures a link | | `DELETE` | `/me/links/:id` | none | Deletes a link | | `PATCH` | `/me/subscriptions/:id/auto-renew` | `UpdateAutoRenewDto` | Toggles auto-renew for own subscription | ## Admin routes - users | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/users` | `page`, `limit`, `search`, `status`, `isBlocked` | Paginated users | | `GET` | `/admin/users/all` | none | All users without pagination | | `GET` | `/admin/users/short` | none | Minimal user list (id, name, email) | | `POST` | `/admin/users` | `CreateAdminUserDto` | Creates a user account | | `GET` | `/admin/users/:id` | none | User detail | | `GET` | `/admin/users/:id/stats` | none | User stats | | `PATCH` | `/admin/users/:id` | `UpdateUserDto` | Updates email, password, role, block flag, name, comment | | `PATCH` | `/admin/users/:id/status` | `UpdateUserStatusDto` | Approves, rejects, or restores a user | | `GET` | `/admin/users/:id/referees` | none | Users invited by this user | | `DELETE` | `/admin/users/:id` | none | Deletes a user | ## Admin routes - balance | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `POST` | `/admin/users/:id/balance/transactions` | `CreateBalanceTransactionDto` | Creates a deposit, withdrawal, or refund | | `GET` | `/admin/users/:id/balance` | none | `{ balance }` | | `GET` | `/admin/users/:id/balance/transactions` | none | Full admin transaction history | | `PATCH` | `/admin/balance/transactions/:id` | `UpdateBalanceTransactionDto` | Edits a balance transaction | ## Admin routes - tariffs | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/tariffs` | none | Tariff list | | `GET` | `/admin/tariffs/:id` | none | Tariff detail | | `POST` | `/admin/tariffs` | `CreateTariffDto` | Creates a tariff | | `PATCH` | `/admin/tariffs/:id` | `UpdateTariffDto` | Updates a tariff | | `DELETE` | `/admin/tariffs/:id` | none | Deletes a tariff | ## Admin routes - subscriptions | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/subscriptions` | `page`, `limit`, `status`, `userId`, `tariffId` | Paginated subscriptions | | `GET` | `/admin/users/:id/subscriptions` | none | Subscriptions for a user | | `GET` | `/admin/users/:id/links` | none | All links for a user | | `GET` | `/admin/users/:id/node-protocols` | none | Available node protocols for a user | | `GET` | `/admin/subscriptions/:id/usage` | `from?`, `to?` | Per-subscription usage (admin) | | `POST` | `/admin/subscriptions` | `CreateSubscriptionDto` | Creates a subscription | | `DELETE` | `/admin/subscriptions/:id` | none | Cancels a subscription | | `PATCH` | `/admin/subscriptions/:id/auto-renew` | `UpdateAutoRenewDto` | Toggles auto-renew | | `POST` | `/admin/users/:id/links` | `CreateUserLinkDto` | Creates a link for any user | | `POST` | `/admin/links/:id/reset` | none | Resets a link UUID | | `PATCH` | `/admin/links/:id` | `UpdateUserLinkDto` | Updates a link | | `DELETE` | `/admin/links/:id` | none | Deletes a link | ## Admin routes - nodes | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/nodes` | `page`, `limit` | Paginated nodes ordered by region, name, then id; nodes without region are last | | `GET` | `/admin/nodes/all` | none | All nodes in the same display order without pagination | | `GET` | `/admin/nodes/short` | none | Minimal selector fields in the same display order | | `GET` | `/admin/nodes/status` | none | Computed node status list in the same display order | | `GET` | `/admin/nodes/outbound-options` | none | Node/protocol outbound options | | `GET` | `/admin/nodes/:id` | none | Node detail | | `POST` | `/admin/nodes` | `CreateNodeDto` | Creates a node | | `PATCH` | `/admin/nodes/:id` | `UpdateNodeDto` | Updates a node | | `DELETE` | `/admin/nodes/:id` | none | Deletes a node | | `POST` | `/admin/nodes/:id/sync` | none | Forces a config sync | | `POST` | `/admin/nodes/auth-code` | none | Generates a one-time node registration code | | `POST` | `/admin/nodes/:id/rotate-key` | none | Rotates the node auth key | | `GET` | `/admin/nodes/:id/protocols` | none | Node protocols | | `POST` | `/admin/nodes/:id/protocols` | `CreateProtocolDto` | Creates a node protocol | | `PUT` | `/admin/nodes/:id/protocols/:protocolId` | `UpdateProtocolDto` | Updates a node protocol | | `DELETE` | `/admin/nodes/:id/protocols/:protocolId` | none | Deletes a node protocol | | `GET` | `/admin/nodes/:id/accesses` | none | User access map for the node | | `POST` | `/admin/nodes/:nodeId/access/:userId/:protocol` | none | Grants protocol access | | `DELETE` | `/admin/nodes/:nodeId/access/:userId/:protocol` | none | Revokes protocol access | | `POST` | `/admin/nodes/:id/install-xray` | `InstallXrayDto` | Installs an xray version and stores the result | | `POST` | `/admin/nodes/:id/restart-xray` | none | Restarts xray | | `POST` | `/admin/nodes/:id/update-geoip` | `UpdateGeoipDto` | Updates stored geoip/geosite URLs and node files | | `POST` | `/admin/nodes/:id/crypto/x25519` | none | Generates x25519 keys | | `POST` | `/admin/nodes/:id/crypto/mldsa65` | none | Generates ML-DSA-65 keys | | `POST` | `/admin/nodes/:id/crypto/tls-ech` | `{ serverName? }` | Generates TLS-ECH keys | | `POST` | `/admin/nodes/:id/crypto/vlessenc` | `{ authentication? }` | Generates VLESS encryption material | | `GET` | `/admin/nodes/xray/versions` | none | Cached xray release tags | | `GET` | `/admin/nodes/mtproto/versions` | none | Cached telemt release tags | | `PATCH` | `/admin/nodes/:id/routing-config` | `UpdateNodeRoutingConfigDto` | Updates per-node routing config | | `DELETE` | `/admin/nodes/:id/routing-config` | none | Clears per-node routing config | | `PATCH` | `/admin/nodes/:id/observatory` | `UpdateNodeObservatoryDto` | Updates observatory (outbound health check) settings | | `GET` | `/admin/nodes/:id/routing-balancers` | none | Node routing balancers | | `POST` | `/admin/nodes/:id/routing-balancers` | `CreateNodeRoutingBalancerDto` | Creates a routing balancer | | `PATCH` | `/admin/nodes/:id/routing-balancers/:balancerId` | `UpdateNodeRoutingBalancerDto` | Updates a routing balancer | | `DELETE` | `/admin/nodes/:id/routing-balancers/:balancerId` | none | Deletes a routing balancer | | `PUT` | `/admin/nodes/:id/nginx/site` | multipart form-data | Uploads cert/key/html for a masking site | | `GET` | `/admin/nodes/:id/nginx/site` | none | Returns nginx masking site status | | `GET` | `/admin/nodes/:id/nginx/sites/:domain/certificate` | none | Returns certificate and domain validity info | | `DELETE` | `/admin/nodes/:id/nginx/sites/:domain` | none | Deletes a masking site | | `POST` | `/admin/nodes/:id/install-mtproto` | body `{ version?: string }` | Installs telemt and stores the version | | `POST` | `/admin/nodes/:id/restart-mtproto` | none | Restarts telemt | | `GET` | `/admin/nodes/:id/runtime-status` | `fromNode=true` forces a live fetch | Live runtime status from the node | | `GET` | `/admin/nodes/:id/stats-history` | `since` (timestamp) | Node stats history since a given time | | `GET` | `/admin/nodes/:id/outbounds` | none | Node outbounds | | `POST` | `/admin/nodes/:id/outbounds` | `CreateNodeOutboundDto` | Creates a node outbound | | `PATCH` | `/admin/nodes/:id/outbounds/:outboundId` | partial `CreateNodeOutboundDto` | Updates a node outbound | | `DELETE` | `/admin/nodes/:id/outbounds/:outboundId` | none | Deletes a node outbound | | `POST` | `/admin/nodes/:id/outbounds/:outboundId/probe` | `{ probeUrl? }` | Probes a node outbound and returns latency | | `POST` | `/admin/nodes/:id/outbounds/probe-builtin` | `{ tag, probeUrl? }` | Probes a builtin outbound (direct/block/etc.) | | `POST` | `/admin/nodes/:id/warp/generate` | none | Registers an anonymous WARP account on the node and returns a WireGuard outbound settings object | ## Admin routes - routing rule sets | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/routing-rule-sets` | none | All routing rule sets | | `POST` | `/admin/routing-rule-sets` | `CreateRoutingRuleSetDto` | Creates a routing rule set | | `PATCH` | `/admin/routing-rule-sets/:id` | `CreateRoutingRuleSetDto` | Updates a routing rule set | | `DELETE` | `/admin/routing-rule-sets/:id` | none | Deletes a routing rule set | ## Admin routes - external subscriptions | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/external-subscriptions` | none | External subscription sources | | `GET` | `/admin/external-subscriptions/:id` | none | External subscription source detail | | `POST` | `/admin/external-subscriptions` | `CreateExternalSubscriptionDto` | Creates a source | | `POST` | `/admin/external-subscriptions/test` | `TestExternalSubscriptionDto` | Tests a URL and returns source data | | `PATCH` | `/admin/external-subscriptions/:id` | `UpdateExternalSubscriptionDto` | Updates a source | | `DELETE` | `/admin/external-subscriptions/:id` | none | Deletes a source | ## Admin routes - logs and usage | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/logs` | `page`, `limit`, `action`, `userId` | Paginated audit logs | | `GET` | `/admin/usage` | `nodeId`, `userId`, `from`, `to` | Up to 1000 traffic usage rows | ## Admin routes - xray helpers | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `POST` | `/admin/xray/parse-link` | `{ link }` | Parses a proxy link into outbound config | ## Admin routes - settings | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `GET` | `/admin/settings/:category` | none | Returns settings for the given category (`panel`, `subscription`, `telegram`) | | `PATCH` | `/admin/settings/panel` | `PanelSettingsDto` | Updates panel settings | | `PATCH` | `/admin/settings/subscription` | `SubscriptionSettingsDto` | Updates subscription delivery settings | | `PATCH` | `/admin/settings/telegram` | `TelegramSettingsDto` | Updates Telegram bot settings | ## Admin routes - broadcasts | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `POST` | `/admin/broadcasts` | `CreateBroadcastDto` | Creates a Telegram broadcast | | `GET` | `/admin/broadcasts` | none | Broadcast list with delivery counts | | `GET` | `/admin/broadcasts/:id` | none | Broadcast detail | | `PATCH` | `/admin/broadcasts/:id` | `UpdateBroadcastDto` | Updates a broadcast | | `DELETE` | `/admin/broadcasts/:id` | none | Deletes a broadcast | | `GET` | `/admin/broadcasts/:id/deliveries` | `status?`, `page?`, `limit?` | Delivery log for a broadcast | ## DTO summary ### Auth - `LoginDto` - `email`, `password` - `RegisterDto` - `email`, `password` - `RefreshTokenDto` - `refreshToken` - `TelegramAuthDto` - `tgAuthResult` - `ApplyReferralCodeDto` - `code` ### Users - `CreateAdminUserDto` - `email`, `password`, `role?`, `name?` - `UpdateProfileDto` - `name?`, `email?`, `password?` - `UpdateUserDto` - `email?`, `password?`, `role?`, `isBlocked?`, `name?`, `comment?`, `allowedToInvite?` - `UpdateUserStatusDto` - `status: 'active' | 'pending' | 'rejected'` ### Balance - `CreateBalanceTransactionDto` - `amount`, `type`, `comment?`, `createdAt?` - `UpdateBalanceTransactionDto` - `amount?`, `type?`, `comment?` ### Tariffs - `CreateTariffDto` - `name` - `durationMonths: number | null` - `price` - `trafficLimitBytes?` - `isActive?` - `allowedProtocols: VpnProtocol[]` - `allowedNodeIds?` - `externalSubscriptionIds?` - `allowBittorrent?` - `allowAdult?` - `UpdateTariffDto` - partial `CreateTariffDto` ### Subscriptions - `CreateSubscriptionDto` - `userId`, `tariffId`, `startAt?` - `CreateUserLinkDto` - `subscriptionId?`, `name?`, `selectedNodeIds?` - `UpdateUserLinkDto` - `name?`, `isEnabled?`, `selectedNodeIds?` - `UpdateAutoRenewDto` - `autoRenew` ### Nodes - `CreateNodeDto` - `name` - `host` - `port?` - `useSsl?` - `ip?` - `region?` - `metadata?` - `comment?` - `emoji?` - `status?` - `useIpInSubscription?` - `UpdateNodeDto` - partial `CreateNodeDto` plus `geoipUrl?` and `geositeUrl?` - `CreateProtocolDto` - `protocol`, `config?`, `label?`, `isEnabled?` - `UpdateProtocolDto` - `config?`, `label?`, `isEnabled?` - `CreateNodeOutboundDto` - `name` - `tag` - `outboundType?` = `manual | node` - `config?` - `targetNodeId?` - `targetProtocolId?` - `UpdateNodeObservatoryDto` - observatory settings for outbound health probing - `CreateNodeRoutingBalancerDto` - `tag`, `selector`, `strategy?`, `fallbackTag?` - `UpdateNodeRoutingBalancerDto` - partial `CreateNodeRoutingBalancerDto` - `CreateRoutingRuleSetDto` - `name` - `description?` - `domainStrategy?` - `rules?` - `balancers?` - `blockTorrents?` - `blockAds?` - `blockMalware?` - `blockPhishing?` - `blockCryptominers?` - `blockAdult?` - `UpdateNodeRoutingConfigDto` - same routing fields as above, without `name` and `description` - `InstallXrayDto` - `version` - `UpdateGeoipDto` - `geoipUrl?`, `geositeUrl?` ### External subscriptions - `CreateExternalSubscriptionDto` - `name`, `url`, `description?` - `UpdateExternalSubscriptionDto` - partial `CreateExternalSubscriptionDto` - `TestExternalSubscriptionDto` - `url` ### Routing rules `XrayRule` fields: - `type` (`field`) - `domainMatcher?` - `domain?` - `ip?` - `port?` - `sourcePort?` - `localPort?` - `network?` - `source?` - `sourceIP?` - `localIP?` - `user?` - `inboundTag?` - `protocol?` - `attrs?` - `process?` - `vlessRoute?` - `webhook?` - `outboundTag?` - `balancerTag?` - `ruleTag?` `XrayBalancer` fields: - `tag` - `selector` - `strategy?` - `fallbackTag?` `XrayDomainStrategy` values: - `AsIs` - `IPIfNonMatch` - `IPOnDemand` `XrayBalancerStrategy` values: - `random` - `roundRobin` - `leastPing` - `leastLoad` ### Settings - `PanelSettingsDto` - `allowedHosts?`, `rootPath?` - `SubscriptionSettingsDto` - `allowedHosts?`, `rootPath?`, `updateInterval?`, `name?`, `supportUrl?`, `websiteUrl?` - `TelegramSettingsDto` - `botToken?` ### Broadcasts - `CreateBroadcastDto` - `text`, `filters?` (`{ nodeIds?: number[] }`), `scheduledAt?` - `UpdateBroadcastDto` - partial `CreateBroadcastDto`