# Core Private Node Routes These routes are consumed only by the node agent and require the `x-node-auth-key` header. ## Authentication - `POST /node/register` is the only public route in this group. - All other routes require a valid node auth key. - The auth key is issued by Core during registration and persisted on the node side. ## Route table | Method | Route | Input | Output / Notes | | --- | --- | --- | --- | | `POST` | `/node/register` | `RegisterNodeDto` | Returns `{ authKey, nodeId }` | | `POST` | `/node/heartbeat` | `NodeHeartbeatDto` | Returns `{ ok: true, needSync }` | | `POST` | `/node/usage` | `NodeUsageDto` | Returns `{ ok: true }` | | `POST` | `/node/outbound-usage` | `NodeOutboundUsageDto` | Returns `{ ok: true }` | | `POST` | `/node/session-events` | `SessionEventsDto` | Returns `{ ok: true }` | | `GET` | `/node/config/latest` | none | Returns `NodeConfig` | | `POST` | `/node/config/applied` | `NodeConfigAppliedDto` | Returns `{ ok: true }` | | `POST` | `/node/error` | `NodeErrorDto` | Returns `{ ok: true }` | ## Request payloads ### `RegisterNodeDto` - `code: string` - `name: string` - `host: string` - `ip: string` - `region: string` ### `NodeHeartbeatDto` - `ip?: string` - `revision?: number` The node sends its current revision in heartbeats. Core uses it to decide whether a sync is needed. ### `NodeUsageDto` - `entries: UsageEntryDto[]` `UsageEntryDto` fields: - `userId: number` - `subscriptionId?: number | null` - `nodeProtocolId: number` - `bytesUp: number` - `bytesDown: number` - `recordedAt: string` ### `NodeOutboundUsageDto` - `items: OutboundUsageItem[]` `OutboundUsageItem` fields: - `tag: string` - `bytesUp: number` - `bytesDown: number` ### `SessionEventsDto` - `events: SessionEventEntryDto[]` `SessionEventEntryDto` fields: - `userId: number` - `protocol: VpnProtocol` - `eventType: SessionEventType` - `occurredAt: string` - `ipAddress?: string` ### `NodeConfigAppliedDto` - `revision: number` ### `NodeErrorDto` - `message: string` - `code?: string` - `details?: Record` ## `NodeConfig` The config returned by `GET /node/config/latest` has this structure: ```ts { revision: number clientMap: Record services: { xray?: XrayServiceConfig mtproto?: MtProtoServiceConfig } } ``` Important notes: - `clientMap` maps subscription link UUIDs to the user and subscription used for traffic attribution. - `services.xray` contains the Xray inbounds, routing, and outbounds for the node. - `services.mtproto` contains MTProto inbounds for `telemt`. - the node stores the current revision and client map locally after a successful apply ## Route semantics - `POST /node/heartbeat` updates `lastSeenAt` and can request a sync when the node revision is behind. - `POST /node/usage` stores per-minute usage rows and increments subscription traffic counters. - `POST /node/outbound-usage` increments `node_outbounds.traffic_bytes_up/down`. - `POST /node/session-events` stores online/offline events in `session_events`. - `POST /node/config/applied` marks the node sync status as `synced`. - `POST /node/error` marks the node as `error` and the sync status as `failed`.