Skip to main content
All relay endpoints are POST, take and return JSON, and live under one base URL: Ringg calls your webhook with events.

Authentication

Every request carries three headers: The signature covers the exact bytes you send. Serialize the body once, sign those bytes, and send those same bytes. Re-serializing after signing changes spacing or key order and breaks the signature. Requests more than 300 seconds old or ahead are rejected.
The API key proves which workspace is calling; the signature proves the body came from you, unchanged. Both must be valid, and the API key must belong to the workspace that owns the number.

Forward a customer message: POST /inbound

Send Meta’s value object (from entry[].changes[].value in Meta’s webhook) unchanged, one message per request.
Request
202 Accepted
202 means the message is stored and will be processed; the reply follows on your webhook. Sending the same messages[0].id again is harmless: it is processed once. If you get a 5xx or no response, retry the same request.

Events Ringg sends to your webhook

Ringg POSTs each event to your webhook URL with these headers: Answer 2xx once you have stored or queued the event, within 10 seconds. How Ringg reacts to anything else:

message.outbound

A reply to send to the customer. delivery.message is the exact body for Meta’s POST /{phone_number_id}/messages.
Then:
  • Order: send replies to Meta in sequence order per chat. Sequences start at 1 and increase by 1.
  • Expiry: don’t send a reply after its expires_at; ack it as skipped instead.
  • Ack: always ack every message.outbound.

message.typing

Sent as soon as Ringg starts working on a customer’s message. delivery.message marks the message as read and shows a typing indicator. Send it to Meta if you want the customer to see it. It has no sequence and no ack.

conversation.closed

The chat has ended, either because the AI agent closed it (reason: "completed") or because you called /close (your reason). There is nothing to send to Meta. The customer’s next message starts a new chat.

Report the result: POST /ack

Call once per message.outbound, after you tried to send it.
Request
200 OK
  • unknown_event: Ringg doesn’t recognise the event_id, or it doesn’t belong to that chat_id. Don’t retry the ack.
  • chat_closed: true: Meta refused the reply in a way that ends the conversation (131047, 131026 or 131051). Ringg has closed the chat.

Forward delivery statuses: POST /status

Pass on the statuses array from Meta’s status webhooks, as received. The body has exactly two fields: don’t wrap it in Meta’s entry or value.
Request
200 OK

Start a conversation: POST /outbound

Opens a chat with a customer and returns an approved template for you to send. When the customer replies, forward it to /inbound as usual and the AI agent continues. Send an X-Idempotency-Key header to make retries safe: the same key within 24 hours returns the first response instead of opening a second chat.
Request
200 OK
Send delivery.message to Meta, then ack it with this event_id, exactly as for a message.outbound event.

Close a conversation: POST /close

Ends a chat, for example when your human agent resolves it. Optionally sends one last message first.
Request
200 OK
closing means a final message is on its way to your webhook; without closing_message the status is closed. Either way, you then receive conversation.closed.

Errors

Authentication and validation errors share one shape. Quote the trace_id when you contact Ringg.