Skip to content

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.

GET /v1/inboxes

Returned unpaginated.

Terminal window
curl "https://publicapi.shout.com/v1/inboxes" \
-H "Authorization: Bearer $SHOUT_API_KEY"
{
"items": [
{
"id": "0c1f6873-35f9-d9ed-df62-3a206f1f1af1",
"name": "Support",
"description": "Customer support inbox",
"ticketPrefix": "SUPPORT",
"workspaceId": "34c78488-d53e-09bb-27b9-3a206f1f1ad7",
"channels": ["email_forward", "form_submissions"],
"createdAt": "2026-04-05T09:21:13.9938578Z"
}
]
}
GET /v1/tickets
Query paramDescription
cursorPagination cursor.
limitPage size, default 25, max 100.
inbox_idOnly tickets in this inbox.
statusopen, snoozed, done, or spam.
sinceOnly tickets with activity at/after this ISO-8601 UTC timestamp.
contact_idOnly tickets for this contact.
Terminal window
curl "https://publicapi.shout.com/v1/tickets?status=open&limit=1" \
-H "Authorization: Bearer $SHOUT_API_KEY"
{
"items": [
{
"id": "66746f32-a74f-0900-b4fa-3a22628b2e12",
"reference": "SUPPORT-123",
"sequentialNumber": 123,
"inboxId": "0c1f6873-35f9-d9ed-df62-3a206f1f1af1",
"status": "open",
"priority": "medium",
"contactId": "8768931a-6136-79ef-cc73-3a22628a1e06",
"assignedToUserId": null,
"lastActivityAt": "2026-07-11T08:49:47.5387188Z",
"snoozedUntil": null,
"waitingSince": "2026-07-11T08:49:47.5387192Z",
"createdAt": "2026-07-11T08:49:47.5392349Z"
}
],
"nextCursor": "djE6NjM5MTkzNTY1..."
}

status is open / snoozed / done / spam; priority is low / medium / high. reference and sequentialNumber are null until 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.

{
"ticket": {
"id": "66746f32-a74f-0900-b4fa-3a22628b2e12",
"reference": "SUPPORT-123",
"status": "open",
"priority": "medium",
"contactId": "8768931a-6136-79ef-cc73-3a22628a1e06",
"createdAt": "2026-07-11T08:49:47.5392349Z"
},
"contact": {
"id": "8768931a-6136-79ef-cc73-3a22628a1e06",
"email": "customer@example.com",
"name": "Sam",
"lastName": "Taylor"
},
"messages": [
{
"id": "769119d7-e4ea-8f82-3115-3a22628b2e17",
"type": "reply",
"direction": "inbound",
"source": "email",
"subject": "Help with my export",
"bodyHtml": "<p>Hi, I can't download my results…</p>",
"bodyText": "Hi, I can't download my results…",
"sentByUserId": null,
"sentByName": null,
"customerEmail": "customer@example.com",
"createdAt": "2026-07-11T08:49:47.5435538Z"
}
]
}

Message type is reply, form_response or form_response_update. direction is inbound (from the customer) or outbound (from your team / the API). contact may be null for anonymous tickets.

POST /v1/tickets/{id}/replies
Terminal window
curl -X POST "https://publicapi.shout.com/v1/tickets/66746f32-a74f-0900-b4fa-3a22628b2e12/replies" \
-H "Authorization: Bearer $SHOUT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "html": "<p>Thanks for reaching out — try the export again now.</p>" }'

html is required; text is an optional plain-text fallback. On success you get 201 Created:

{ "delivered": true, "messageId": "a1b2c3d4-...", "channel": "email" }

Replies are email-only in v1. Expect these failures:

StatuserrorWhen
422unprocessableThe ticket is on a live-messaging channel (chat/WhatsApp/etc.), or its contact has no email address.
502delivery_failedThe email couldn’t be delivered, or the account hit its outbound daily limit. Not caused by your request.
404not_foundNo such ticket.
PUT /v1/tickets/{id}/status

status must be open, done, snoozed, or spam. When snoozing, snoozedUntil (an ISO-8601 timestamp) is required.

Terminal window
curl -X PUT "https://publicapi.shout.com/v1/tickets/66746f32-a74f-0900-b4fa-3a22628b2e12/status" \
-H "Authorization: Bearer $SHOUT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "snoozed", "snoozedUntil": "2026-07-20T09:00:00Z" }'

Returns 200 OK with the updated ticket. A status change fires any subscribed ticket.status_changed webhook. Invalid input:

  • 400 invalid_request — status isn’t one of the four values, or snoozedUntil is missing for snoozed.
  • 404 not_found — no such ticket.