Search the complete documentation

Try idempotency, proposal lifecycle, authentication, or ordering.

Navigate Open
繁體中文
Browse documentation

Relay · Contract reference

HTTP operation index and compatibility

This page inventories the current HTTP surface. It is an operation reference, not a generated schema. Request fields, response examples, retry behavior, and known gaps remain documented in the task guides linked from each area.

Base URL and authentication

All JSON operations use your Relay origin, for example https://relay.example.com. There is no /v1 prefix today.

SurfaceAuthentication
Conversation /api/*Authorization: Bearer <tenant-user-jwt>
Metadata updateTenant JWT or X-Admin-Token
Operator /api/admin/*X-Admin-Token
Host secret sync /api/host/*HTTP Basic with tenant-scoped host-sync credentials
MetricsAuthorization: Bearer <metrics-token> when METRICS_TOKEN is configured
HealthNone

Responses normally wrap resources in { "data": ... }. Most conversation errors use { "errors": [...] }; search, attachments, and rate-limit paths also use { "error": "..." }. This inconsistency is part of the current contract and remains product work.

Tenant isolation is not selected by a query parameter on normal conversation routes. Relay derives the tenant from the verified JWT and routes database access to that tenant’s schema.

Channels and membership

MethodPathPurpose
GET/api/channelsList channels visible to the tenant user
POST/api/channelsCreate a channel
GET/api/channels/{channel_id}Read one channel
POST/api/channels/{channel_id}/closeClose a channel
PATCH/api/channels/{channel_id}/metadataMerge metadata
PUT/api/channels/{channel_id}/metadataReplace metadata
GET/api/channels/{channel_id}/membersList channel members
POST/api/channels/{channel_id}/membersAdd a member
DELETE/api/channels/{channel_id}/members/{member_id}Remove the permitted membership
POST/api/channels/{channel_id}/notification_muteMute notifications for the current member
DELETE/api/channels/{channel_id}/notification_muteRemove the current member’s mute
GET/api/channels/unread?channel_ids={id}Read unread counts for selected channels

Channel discovery and membership authorization have current limitations. Read Channels and permissions before treating these operations as a private-channel or moderator model.

Messages, threads, pins, and reactions

MethodPathPurpose
GET/api/channels/{channel_id}/messagesList history with sequence pagination
POST/api/channels/{channel_id}/messagesCreate a message with nonce idempotency
PATCH/api/channels/{channel_id}/messages/{message_id}Edit the message body
POST/api/channels/{channel_id}/messages/{message_id}/retractRetract a message
POST/api/channels/{channel_id}/messages/{message_id}/pinPin a message
DELETE/api/channels/{channel_id}/messages/{message_id}/pinUnpin a message
GET/api/channels/{channel_id}/messages/pinnedList pinned messages
GET/api/channels/{channel_id}/messages/{message_id}/threadList thread replies
GET/api/channels/{channel_id}/messages/{message_id}/reactionsRead reactions and summary
PUT/api/channels/{channel_id}/messages/{message_id}/reactions/{emoji}Add the current user’s reaction
DELETE/api/channels/{channel_id}/messages/{message_id}/reactions/{emoji}Remove the current user’s reaction

Only message creation exposes a client idempotency key. Preserve the same nonce after an uncertain send. Channel-local seq, not timestamps or list position, defines message order. See Send a message and Realtime and reconnect.

Search and attachments

MethodPathPurpose
GET/api/channels/{channel_id}/messages/search?q={query}Search one channel
POST/api/uploads/presignCreate a direct-upload attachment record and PUT URL
GET/api/attachments/{attachment_id}/urlCreate a short-lived attachment download URL

Search indexing is asynchronous. Attachment upload is a multi-step contract: presign, object PUT, then bind the attachment ID in the same message transaction. See Search and Attachments for cursor, safety, and lifecycle boundaries.

Tenant host-sync API

MethodPathPurpose
POST/api/host/tenants/{tenant_id}/jwt_secret/fetchFetch the active tenant signing secret with host-sync Basic credentials

This response carries credential material and sets no-store cache headers. It is a server-to-server bootstrap path, not a browser API. See Authentication.

Operator API

Every operation in this section requires X-Admin-Token. It is a deployment-wide control plane, not tenant self-service.

Tenants, credentials, and limits

MethodPathPurpose
GET/api/admin/tenantsList tenants
POST/api/admin/tenantsCreate a tenant and initial host-sync credential
GET/api/admin/tenants/{tenant_id}Read tenant status
POST/api/admin/tenants/{tenant_id}/disableDisable tenant authentication and host sync
POST/api/admin/tenants/{tenant_id}/jwt_secret/rotateRotate the JWT primary secret
POST/api/admin/tenants/{tenant_id}/jwt_secret/expire_previousRemove the previous JWT secret
POST/api/admin/tenants/{tenant_id}/jwt_secret/revoke_allRevoke existing JWT secrets and replace the primary
POST/api/admin/tenants/{tenant_id}/host_sync_secret/rotateRotate host-sync credentials
POST/api/admin/tenants/{tenant_id}/host_sync_secret/expire_previousRemove the previous host-sync secret
POST/api/admin/tenants/{tenant_id}/host_sync_secret/revoke_allRevoke host-sync credentials and issue a replacement
GET/api/admin/tenants/{tenant_id}/rate_limitsRead tenant rate-limit overrides
PUT/api/admin/tenants/{tenant_id}/rate_limitsReplace tenant rate-limit overrides

Data governance and audit

MethodPathPurpose
GET/api/admin/tenants/{tenant_id}/data_retentionRead retention policy
PUT/api/admin/tenants/{tenant_id}/data_retentionReplace retention policy
DELETE/api/admin/messages/{message_id}?tenant_id={tenant_id}Soft-delete a message and schedule related cleanup
DELETE/api/admin/users/{user_id}?tenant_id={tenant_id}Delete or tombstone tenant-scoped user data
POST/api/admin/users/{user_id}/exports?tenant_id={tenant_id}Queue a user export
GET/api/admin/user_exports/{job_id}?tenant_id={tenant_id}Read export status
GET/api/admin/user_exports/{job_id}/download?tenant_id={tenant_id}&token={token}Download a completed export
GET/api/admin/tenant_audit_events?tenant_id={tenant_id}Query control-plane audit rows
GET/api/admin/message_audit_events?tenant_id={tenant_id}Query message lifecycle audit rows

Read Data lifecycle and audit before mapping these operations to erasure or compliance controls.

Agents, search, handoffs, and dead letters

MethodPathPurpose
GET/api/admin/botsList registered agent users
POST/api/admin/botsRegister an agent user
DELETE/api/admin/bots/{user_id}Revoke an agent user
POST/api/admin/tenants/{tenant_id}/search/reindexQueue a tenant search backfill
GET/api/admin/tenants/{tenant_id}/search/reindexRead reindex status
GET/api/admin/post_commit_handoffsInspect durable handoffs
GET/api/admin/post_commit_handoffs/channel_backlogsInspect channel-level fan-out backlog
GET/api/admin/post_commit_handoffs/{handoff_id}Inspect one handoff
GET/api/admin/host_webhook/dead_lettersList exhausted webhook deliveries
POST/api/admin/host_webhook/dead_letters/{dead_letter_id}/replayRequeue a dead letter

Dead-letter replay has fidelity limits for some event types. See Webhooks and Deployment and operations.

Health, metrics, and adapter ingress

MethodPathPurpose
GET/healthLegacy liveness
GET/livezProcess liveness
GET/readyDatabase-backed readiness
GET/readyzDatabase-backed readiness alias
GET/metricsPrometheus metrics, optionally protected by METRICS_TOKEN
POST/adapters/{source}/webhookIn-tree adapter ingress with source-specific verification

Adapter ingress is an extension point, not a uniform customer webhook contract. Supported sources, signatures, and payloads depend on the installed in-tree adapter.

Current compatibility policy

The HTTP paths are unversioned and no canonical OpenAPI or AsyncAPI artifact is published. Therefore the REST surface is a contract beta, even where the underlying database invariants and SDK package are stronger.

During contract beta:

  • message nonce idempotency, tenant isolation, the shared REST and WebSocket write path, and server-assigned channel sequence are the core invariants;
  • clients must ignore unknown response fields and unknown WebSocket event fields;
  • cursors are opaque and must not be parsed, altered, or constructed by clients;
  • additive fields and endpoints may ship without a major path change;
  • a changed or removed field, route, auth rule, status meaning, or idempotency behavior is breaking and must ship with updated docs and a migration note;
  • the published @tonetify/relay package version does not establish server compatibility until a tested compatibility matrix exists.

Before Relay can claim a stable public API, it still needs a versioned base path or media type, a canonical machine-readable schema, contract tests against that schema, a deprecation and overlap window, changelog and migration surfaces, and a server-to-SDK compatibility matrix.

Do not infer server API stability from the name v1 in internal documents or the SDK’s published 0.1.0-beta.1 version. Neither is a published server API version.

Related: Authentication · Limits and errors · Relay overview