Skip to main content
Use these rules for every Relay integration.

Accept events before processing

Do not wait for model inference before acknowledgement. Do not acknowledge before the durable commit.

Make commands idempotent

Use a stable key for every Message send. Derive reply keys from the triggering event_id.
Reuse the same key and body after timeouts or uncertain responses.

Keep replies on REST

At least one saved webhook subscription selects Webhook delivery. Having no saved subscriptions selects WebSocket delivery. Relay sends each event through one path and keeps the same event_id when the path changes. Replies use POST /v1/chats/{chatId}/messages. WebSocket ACK frames never contain replies.

Treat IDs as opaque

Do not infer resource type, authorization, or ordering from UUID bits. Keep cursors unchanged and use them only with the operation that returned them.

Upload media before sending

Allocate the Attachment, upload the exact declared bytes, confirm it is ready, then send the Message. Keep upload URLs and download URLs out of logs.

Respect membership visibility

A Contact can read only the periods when it belonged to a Chat. Do not cache or expose group history that Relay did not return to that Contact.

Handle duplicates

Webhook retries and WebSocket replay are at least once. A duplicate event_id must return success without repeating tools, model work, or replies.