Перейти к содержимому

Remnawave API compatibility

This catalog is generated from the same typed registry used by the runtime client. Do not edit it manually: update panel_api_contracts.py or remnawave_support.json, regenerate, and run the contract tests.

Core certifies 2 API generations at a time: the current generation and one maintenance generation. Exact versions are certified; a new patch/minor in a known generation is reported as unverified until live CI is green. Removal gets at least 90 days and 2 Core releases of notice, and requires a breaking Core release.

Unknown future Remnawave major versions run in best-effort mode: existing reads and writes remain available because a major bump does not necessarily change the API. They stay marked unverified until certified, and endpoint/capability fallbacks limit assumptions. If the metadata endpoint is temporarily unavailable, Core preserves best-effort compatibility and uses identifier/endpoint observations instead of caching a false version result.

Status API generation Exact versions Preset Capabilities Coverage Upstream
current rw3-numeric-user-id 3.2.3, 3.2.1, 3.2.0, 3.1.0, 3.0.0 3.2.3 numeric-user-ids, user-stream, user-stream-filters, targeted-squad-bulk, connections-drop, hwid-user-id-selector, empty-success-body, multi-node-usage, multi-node-top-users, bulk-squad-update fixture, live-read, live-write, upgrade release notes
maintenance rw2-uuid-user-id 2.8.1 2.8.1 multi-node-top-users, bulk-squad-update fixture, live-read, live-write, upgrade release notes

Historical presets remain useful for manual investigations but are not supported or run in the certification matrix:

  • 2.8.0 — Manual historical preset; not part of the certified CI matrix.
  • 2.7.4 — Manual historical preset; not part of the certified CI matrix.

{userRef} is a user UUID in 2.8.1 and the decimal form of a numeric user id in 3.0.0. Other UUIDs (nodes, squads, hosts, subscriptions) remain UUIDs.

Operation Method Path template Generations Success Response Compatibility Coverage
system.metadata GET /system/metadata rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable version probe; failures are not treated as a capability result. unit, live-read
users.stream GET /users/stream rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response 3.x is the canonical cursor stream and supports lookup filters; a 2.8 stream may expose UUID users or ignore the new filters, so Core validates results. unit, live-read, upgrade
users.list GET /users rw2-uuid-user-id 200 JSON envelope with response Legacy offset pagination used when the stream is absent or UUID-based. unit, live-read
users.get GET /users/{userRef} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response {userRef} is a UUID in 2.8.1 and a numeric id in 3.x. unit, live-read, upgrade
users.lookup.telegram GET /users/by-telegram-id/{telegramId} rw2-uuid-user-id 200 JSON envelope with response 3.x uses /users/stream?telegramId=… instead. unit, live-read
users.lookup.username GET /users/by-username/{username} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response The username lookup route remains stable through 3.2.3; 3.1+ reports an absent user as 404/A063. unit, live-read
users.lookup.email GET /users/by-email/{email} rw2-uuid-user-id 200 JSON envelope with response 3.x uses /users/stream?email=… instead. unit, live-read
users.create POST /users rw2-uuid-user-id, rw3-numeric-user-id 200, 201 JSON envelope with response Core never sends a caller-provided user UUID; 3.x returns numeric id. unit, live-write
users.update PATCH /users rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Selector field is uuid in 2.8.1 and integer id in 3.x. unit, live-write
users.bulk-update-squads POST /users/bulk/update-squads rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Exact-state squad update, chunked at 500 users. 2.8.1 selects UUIDs with uuids and returns affectedRows; 3.x selects numeric userIds and returns 204. An empty target state uses per-user PATCH because 3.0.0 returns A088/500. unit, live-write
users.status POST /users/{userRef}/actions/{enable|disable} rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Path identity follows the UUID/numeric-id generation. unit, live-write
users.connections.drop-v2 POST /ip-control/drop-connections rw2-uuid-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success 2.8 payload selects userUuids. unit, live-write
users.connections.drop-v3 POST /connections/drop rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success 3.x payload selects numeric userIds. unit, live-write
users.delete DELETE /users/{userRef} rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success 404 for a missing entity is idempotent success; route absence is distinct. unit, live-write
users.revoke POST /users/{userRef}/actions/revoke rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Path identity follows the UUID/numeric-id generation. unit, live-write
users.reset-traffic POST /users/{userRef}/actions/reset-traffic rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Path identity follows the UUID/numeric-id generation. unit, live-write
subscription.config.resolved GET /subscriptions/subpage-config/{shortUuid} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response GET intentionally carries requestHeaders in a JSON body as required upstream. unit, live-read
subscription-page-config.list GET /subscription-page-configs rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
subscription-page-config.get GET /subscription-page-configs/{uuid} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
external-squads.get GET /external-squads/{uuid} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
hwid.devices.get GET /hwid/devices/{userRef} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Path userRef is UUID in 2.8.1 and numeric id in 3.x. unit, live-read
hwid.devices.delete POST /hwid/devices/delete rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Payload selector is userUuid in 2.8.1 and userId in 3.x. unit, live-write
hwid.devices.stats GET /hwid/devices/stats rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
hwid.devices.top-users GET /hwid/devices/top-users rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
nodes.restart POST /nodes/{uuid}/actions/restart rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Node identifiers remain UUIDs in 3.x. unit
nodes.restart-all POST /nodes/actions/restart-all rw2-uuid-user-id, rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success Not run in live CI because it disrupts every registered node. unit
nodes.list GET /nodes rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
nodes.stats GET /system/stats/nodes rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
system.stats GET /system/stats rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
system.stats.bandwidth GET /system/stats/bandwidth rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
bandwidth.nodes GET /bandwidth-stats/nodes rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
bandwidth.users GET /bandwidth-stats/users/{userRef} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Path userRef is UUID in 2.8.1 and numeric id in 3.x. unit, live-read
bandwidth.node-users GET /bandwidth-stats/nodes/{nodeUuid}/users rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
bandwidth.nodes-users POST /bandwidth-stats/nodes/users rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response 2.8.1-compatible aggregate top-users request for a set of nodes; Core detects topUsersLimit saturation before treating missing users as zero. unit, live-read
bandwidth.nodes-usage POST /bandwidth-stats/nodes/usage rw3-numeric-user-id 200 JSON envelope with response 3.x returns numeric user ids and per-node totals for all requested nodes. Usage snapshots are refreshed no faster than the upstream aggregation cadence. unit, live-read
internal-squads.list GET /internal-squads rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
internal-squads.get GET /internal-squads/{uuid} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
internal-squads.nodes GET /internal-squads/{uuid}/{accessible-nodes|nodes} rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Core tries both upstream route spellings and validates response shape. unit, live-read
internal-squads.add-users POST /internal-squads/{uuid}/bulk-actions/add-many-users rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success 3.x targeted numeric-id bulk, chunked at 1000. In 2.8.1 the superficially similar add-users route targets every user, so Core PATCHes requested users. unit, live-write
internal-squads.remove-users DELETE /internal-squads/{uuid}/bulk-actions/remove-many-users rw3-numeric-user-id 200, 202, 204 JSON envelope with response; an empty 2xx body is success 3.x targeted numeric-id bulk, chunked at 1000; 2.8.1 uses per-user PATCH. unit, live-write
hosts.list GET /hosts rw2-uuid-user-id, rw3-numeric-user-id 200 JSON envelope with response Stable across the certified API generations. unit, live-read
Event Generations Identity handling Core behavior Coverage
user.expires_in_72_hours / 48_hours / 24_hours rw2-uuid-user-id, rw3-numeric-user-id user.uuid in 2.8.1; user.id normalized to the internal uuid alias in 3.x Subscription expiry notification and optional auto-renew processing. unit
user.expiration rw2-uuid-user-id, rw3-numeric-user-id user object plus meta.expirationHours Compatibility event mapped to before/after-expiration notification stages. unit
user.expired / user.expired_24_hours_ago rw2-uuid-user-id, rw3-numeric-user-id normalized user identity Expired subscription notification with stale-subscription suppression. unit
torrent_blocker.report rw2-uuid-user-id, rw3-numeric-user-id typed torrent-blocker payload; user identity is resolved independently Typed security notification; invalid or oversized payloads are rejected. unit
other events (for example user.modified) rw2-uuid-user-id, rw3-numeric-user-id normalized user identity when a user object is present Emitted to the Core/plugin event bus but ignored for lifecycle notifications. unit
From To Strategy Verification
2.8.1 3.2.3 same-panel-database tests/qa/test_remnawave_upgrade.py
  • Panel version detection has a five-minute positive cache. Failures are not cached, so startup races and temporary authorization failures self-heal.
  • 3.x users are normalized at the boundary: numeric id is also exposed internally as a decimal-string uuid alias. This intentionally preserves historical DB columns and service method names during an in-place panel upgrade.
  • Once the generation is known, user-scoped requests reject an identifier from the other generation locally. This prevents 3.x validation-error storms and prevents a stale UUID from being mistaken for a deleted user.
  • Background tariff synchronization lazily relinks stale 2.8 UUIDs through Telegram/email/deterministic username identity before it can deactivate a subscription. Failed or ambiguous identity lookups never create a duplicate user.
  • 2.8.1 uses offset /users pagination and UUID lookup routes. 3.x uses the cursor stream and stream filters. Responses are shape-checked before a capability is learned.
  • User-miss responses A025, A062, A063, and plain 404 are normalized as an empty lookup result. Removed-route 404 responses are handled first so a live 2.8-to-3.x upgrade switches to stream filters without restarting Mini Shop.
  • Empty 202/204 responses are accepted for mutation operations documented that way; malformed non-empty 2xx JSON is still a protocol error.
  • The 2.8.1 squad add-users route means all users. Core never calls it for a targeted request; it patches each requested UUID user. 3.x uses chunked numeric-id bulk calls.
  • Logs use registry labels instead of raw paths, preventing identifiers in route segments and query strings from becoming log/metric labels.
  1. Read the upstream release/API diff and classify the API generation. Future majors remain best-effort compatible, but are never presented as certified without live QA.
  2. Add or update an exact entry in remnawave_support.json and a dev-stand preset. Keep historical presets clearly separate from the certified matrix.
  3. Update every affected operation contract, compatibility adapter, webhook normalizer, version fixture, and all certified-version live jobs.
  4. Run read/write smoke tests for current and maintenance versions. For generation changes, also run the same-database upgrade job and verify persisted user identities after sync.
  5. Regenerate this catalog and public API artifacts, then run all backend/frontend gates.
  6. To retire a generation, announce deprecation for the policy window, remove it only in a breaking Core release, and move its presets to historical status.

Manifest review date: 2026-08-11.