Inbox & Tickets
Read your team inboxes and their tickets, reply to customers, and move tickets through their
workflow. Reading requires tickets:read; replying and changing status require tickets:write.
A tenant-scoped API key sees all of your team inboxes and tickets — there’s no per-user inbox membership behind a key.
Ticket shape and enums
Section titled “Ticket shape and enums”statusisopen/snoozed/done/spam;priorityislow/medium/high.referenceandsequentialNumberarenulluntil a ticket is assigned an inbox with a prefix.GET /v1/tickets/{id}returns the ticket, a summary of its contact, and the full message thread (oldest first). Internal notes are never included.contactmay benullfor anonymous tickets.- On each message,
typeisreply,form_responseorform_response_update;directionisinbound(from the customer) oroutbound(from your team / the API).
Replying to a ticket
Section titled “Replying to a ticket”POST /v1/tickets/{id}/replies — html is required; text is an optional plain-text fallback. On
success you get 201 Created with { "delivered": true, "messageId": "...", "channel": "email" }.
Replies are email-only in v1. Expect these failures:
| Status | error | When |
|---|---|---|
422 | unprocessable | The ticket is on a live-messaging channel (chat/WhatsApp/etc.), or its contact has no email address. |
502 | delivery_failed | The email couldn’t be delivered, or the account hit its outbound daily limit. Not caused by your request. |
404 | not_found | No such ticket. |
Changing ticket status
Section titled “Changing ticket status”PUT /v1/tickets/{id}/status — status must be open, done, snoozed, or spam. When snoozing,
snoozedUntil (an ISO-8601 timestamp) is required. A status change fires any subscribed
ticket.status_changed webhook.
400 invalid_request— status isn’t one of the four values, orsnoozedUntilis missing forsnoozed.404 not_found— no such ticket.