Relay · Contract reference
HTTP 操作索引與相容性
本頁列出目前完整 HTTP surface。它是 operation reference,不是 generated schema。Request field、response example、retry behavior 與 known gap 仍以各主題文件為準。
Base URL 與 authentication
所有 JSON operation 都使用 Relay origin,例如 https://relay.example.com。目前沒有 /v1 prefix。
| Surface | Authentication |
|---|---|
Conversation /api/* | Authorization: Bearer <tenant-user-jwt> |
| Metadata update | Tenant JWT 或 X-Admin-Token |
Operator /api/admin/* | X-Admin-Token |
Host secret sync /api/host/* | 使用 tenant-scoped host-sync credential 的 HTTP Basic |
| Metrics | 設定 METRICS_TOKEN 時使用 Authorization: Bearer <metrics-token> |
| Health | 無 |
Response 通常以 { "data": ... } 包住 resource。多數 conversation error 使用 { "errors": [...] };search、attachment 與 rate-limit path 也會使用 { "error": "..." }。這個 inconsistency 是目前 contract 的一部分,仍屬於 product work。
一般 conversation route 不會透過 query parameter 選擇 tenant。Relay 從 verified JWT 取得 tenant,再將 database access 導向該 tenant schema。
Channel 與 membership
| Method | Path | 用途 |
|---|---|---|
GET | /api/channels | 列出 tenant user 可見的 channel |
POST | /api/channels | 建立 channel |
GET | /api/channels/{channel_id} | 讀取單一 channel |
POST | /api/channels/{channel_id}/close | 關閉 channel |
PATCH | /api/channels/{channel_id}/metadata | Merge metadata |
PUT | /api/channels/{channel_id}/metadata | Replace metadata |
GET | /api/channels/{channel_id}/members | 列出 channel member |
POST | /api/channels/{channel_id}/members | 新增 member |
DELETE | /api/channels/{channel_id}/members/{member_id} | 移除允許刪除的 membership |
POST | /api/channels/{channel_id}/notification_mute | 為目前 member 關閉 notification |
DELETE | /api/channels/{channel_id}/notification_mute | 移除目前 member 的 mute |
GET | /api/channels/unread?channel_ids={id} | 讀取指定 channel 的 unread count |
Channel discovery 與 membership authorization 仍有現有限制。將這些 operation 當成 private-channel 或 moderator model 前,先閱讀 Channel 與權限。
Message、thread、pin 與 reaction
| Method | Path | 用途 |
|---|---|---|
GET | /api/channels/{channel_id}/messages | 以 sequence pagination 列出 history |
POST | /api/channels/{channel_id}/messages | 使用 nonce idempotency 建立 message |
PATCH | /api/channels/{channel_id}/messages/{message_id} | 編輯 message body |
POST | /api/channels/{channel_id}/messages/{message_id}/retract | Retract message |
POST | /api/channels/{channel_id}/messages/{message_id}/pin | Pin message |
DELETE | /api/channels/{channel_id}/messages/{message_id}/pin | Unpin message |
GET | /api/channels/{channel_id}/messages/pinned | 列出 pinned message |
GET | /api/channels/{channel_id}/messages/{message_id}/thread | 列出 thread reply |
GET | /api/channels/{channel_id}/messages/{message_id}/reactions | 讀取 reaction 與 summary |
PUT | /api/channels/{channel_id}/messages/{message_id}/reactions/{emoji} | 新增目前 user 的 reaction |
DELETE | /api/channels/{channel_id}/messages/{message_id}/reactions/{emoji} | 移除目前 user 的 reaction |
只有 message creation 提供 client idempotency key。Send result 不確定時必須保留相同 nonce。Message order 由 channel-local seq 定義,不能使用 timestamp 或 list position。詳見傳送訊息與即時事件與重新連線。
Search 與 attachment
| Method | Path | 用途 |
|---|---|---|
GET | /api/channels/{channel_id}/messages/search?q={query} | 搜尋單一 channel |
POST | /api/uploads/presign | 建立 direct-upload attachment row 與 PUT URL |
GET | /api/attachments/{attachment_id}/url | 建立短效 attachment download URL |
Search indexing 是非同步流程。Attachment upload 是 multi-step contract:presign、object PUT,最後在同一個 message transaction 內 bind attachment ID。Cursor、safety 與 lifecycle boundary 詳見搜尋與附件。
Tenant host-sync API
| Method | Path | 用途 |
|---|---|---|
POST | /api/host/tenants/{tenant_id}/jwt_secret/fetch | 使用 host-sync Basic credential 取得目前 tenant signing secret |
這個 response 帶有 credential material,並設定 no-store cache header。它是 server-to-server bootstrap path,不是 browser API。詳見身分驗證。
Operator API
本節每個 operation 都需要 X-Admin-Token。它是 deployment-wide control plane,不是 tenant self-service。
Tenant、credential 與 limit
| Method | Path | 用途 |
|---|---|---|
GET | /api/admin/tenants | 列出 tenant |
POST | /api/admin/tenants | 建立 tenant 與 initial host-sync credential |
GET | /api/admin/tenants/{tenant_id} | 讀取 tenant status |
POST | /api/admin/tenants/{tenant_id}/disable | 停用 tenant authentication 與 host sync |
POST | /api/admin/tenants/{tenant_id}/jwt_secret/rotate | Rotate JWT primary secret |
POST | /api/admin/tenants/{tenant_id}/jwt_secret/expire_previous | 移除 previous JWT secret |
POST | /api/admin/tenants/{tenant_id}/jwt_secret/revoke_all | Revoke 既有 JWT secret 並取代 primary |
POST | /api/admin/tenants/{tenant_id}/host_sync_secret/rotate | Rotate host-sync credential |
POST | /api/admin/tenants/{tenant_id}/host_sync_secret/expire_previous | 移除 previous host-sync secret |
POST | /api/admin/tenants/{tenant_id}/host_sync_secret/revoke_all | Revoke host-sync credential 並簽發 replacement |
GET | /api/admin/tenants/{tenant_id}/rate_limits | 讀取 tenant rate-limit override |
PUT | /api/admin/tenants/{tenant_id}/rate_limits | 取代 tenant rate-limit override |
Data governance 與 audit
| Method | Path | 用途 |
|---|---|---|
GET | /api/admin/tenants/{tenant_id}/data_retention | 讀取 retention policy |
PUT | /api/admin/tenants/{tenant_id}/data_retention | 取代 retention policy |
DELETE | /api/admin/messages/{message_id}?tenant_id={tenant_id} | Soft-delete message 並排程相關 cleanup |
DELETE | /api/admin/users/{user_id}?tenant_id={tenant_id} | 刪除或 tombstone tenant-scoped user data |
POST | /api/admin/users/{user_id}/exports?tenant_id={tenant_id} | Queue user export |
GET | /api/admin/user_exports/{job_id}?tenant_id={tenant_id} | 讀取 export status |
GET | /api/admin/user_exports/{job_id}/download?tenant_id={tenant_id}&token={token} | 下載 completed export |
GET | /api/admin/tenant_audit_events?tenant_id={tenant_id} | Query control-plane audit row |
GET | /api/admin/message_audit_events?tenant_id={tenant_id} | Query message lifecycle audit row |
將這些 operation 對應到 erasure 或 compliance control 前,先閱讀資料生命週期與稽核。
Agent、search、handoff 與 dead letter
| Method | Path | 用途 |
|---|---|---|
GET | /api/admin/bots | 列出 registered agent user |
POST | /api/admin/bots | Register agent user |
DELETE | /api/admin/bots/{user_id} | Revoke agent user |
POST | /api/admin/tenants/{tenant_id}/search/reindex | Queue tenant search backfill |
GET | /api/admin/tenants/{tenant_id}/search/reindex | 讀取 reindex status |
GET | /api/admin/post_commit_handoffs | Inspect durable handoff |
GET | /api/admin/post_commit_handoffs/channel_backlogs | Inspect channel-level fan-out backlog |
GET | /api/admin/post_commit_handoffs/{handoff_id} | Inspect 單一 handoff |
GET | /api/admin/host_webhook/dead_letters | 列出 exhausted webhook delivery |
POST | /api/admin/host_webhook/dead_letters/{dead_letter_id}/replay | Requeue dead letter |
部分 event type 的 dead-letter replay 仍有 fidelity limit。詳見 Webhook與部署與操作。
Health、metrics 與 adapter ingress
| Method | Path | 用途 |
|---|---|---|
GET | /health | Legacy liveness |
GET | /livez | Process liveness |
GET | /ready | Database-backed readiness |
GET | /readyz | Database-backed readiness alias |
GET | /metrics | Prometheus metrics,可使用 METRICS_TOKEN 保護 |
POST | /adapters/{source}/webhook | 使用 source-specific verification 的 in-tree adapter ingress |
Adapter ingress 是 extension point,不是統一的 customer webhook contract。支援的 source、signature 與 payload 取決於 installed in-tree adapter。
目前的 compatibility policy
HTTP path 尚未 versioned,也沒有 canonical OpenAPI 或 AsyncAPI artifact。因此即使 underlying database invariant 與 SDK package 較成熟,REST surface 仍屬於 contract beta。
Contract beta 期間:
- message nonce idempotency、tenant isolation、共用 REST 與 WebSocket write path,以及 server-assigned channel sequence 是 core invariant;
- client 必須忽略 unknown response field 與 unknown WebSocket event field;
- cursor 是 opaque value,client 不能 parse、修改或自行建構;
- additive field 與 endpoint 可以在不改 major path 的情況下發布;
- field、route、auth rule、status meaning 或 idempotency behavior 的修改與移除都是 breaking change,必須在同一個 release 提供更新文件與 migration note;
- 在 tested compatibility matrix 建立前,已發布的
@tonetify/relaypackage version 不代表 server compatibility。
Relay 要宣稱 stable public API,仍需要 versioned base path 或 media type、canonical machine-readable schema、對 schema 執行的 contract test、deprecation 與 overlap window、changelog 與 migration surface,以及 server-to-SDK compatibility matrix。
不能從 internal document 的 v1 名稱或 SDK 已發布的 0.1.0-beta.1 version 推定 server API stability。兩者都不是已發布的 server API version。