Appearance
API reference
Base URL: your serverUrl. All /api/* endpoints require Authorization: Bearer <session-jwt>. Responses are JSON; errors are { error, message } with an appropriate status.
The SDK calls these for you — this reference is for debugging and for teams extending the backend.
Health
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health | — | Liveness. Always 200 if the process is up. |
| GET | /ready | — | Readiness. Checks DB + Intercom breaker. 200 / 503. |
Conversations
| Method | Path | Description |
|---|---|---|
| GET | /api/conversations | List the user's conversations (summaries). |
| POST | /api/conversations | Start a request. Body { body?, reason?, meta? } — see below. |
| GET | /api/conversations/:id | Full conversation: messages + state + rating. |
| GET | /api/conversations/:id/poll?since=<ms> | New messages and live state (below). |
| POST | /api/conversations/:id/read | Mark the conversation read (clears the unread badge). |
| POST | /api/conversations/:id/close | Close the request (user-initiated). Triggers the CSAT prompt. |
| POST | /api/conversations/:id/reply | Send a message. Body { body, attachmentIds? }. |
Starting a request — body is optional. If you pass a reason ({ main, sub? }) with no body, the backend opens the conversation from the topic alone (the picked topic is recorded as an internal note/tag, not shown as a user message). meta carries browser/IP-style context used to enrich the Intercom contact. At least one of body / reason is required.
Poll response — besides messages, the poll returns live conversation state so operator-side changes reflect within one interval without a reload:
json
{
"messages": [ /* … newer than `since` */ ],
"latestTimestamp": 1719750000,
"state": "open", // "open" | "closed" | "snoozed"
"snoozedUntil": null,
"rated": false // true once a CSAT tag is on the conversation
}Tickets
| Method | Path | Description |
|---|---|---|
| GET | /api/tickets | List the user's tickets (newest first; includes rated). |
| GET | /api/tickets/search?q=AW-123 | Filter by reference. |
| GET | /api/tickets/:id | Ticket detail: messages + status timeline. |
| POST | /api/tickets/:id/reply | Reply. Reopens the ticket if it was resolved. |
| POST | /api/tickets/:id/clarify | Route a "clarify status" message to the chat. |
Files
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/files/upload | Bearer | multipart/form-data (file). Validates, then S3/local. |
| GET | /api/files/:id | Bearer | Download/redirect for the in-app viewer. |
| GET | /files/:id?t=<hmac> | public | Signed URL so Intercom can fetch a user's attachment (it sends no auth header). |
Upload validation: size cap MAX_FILE_MB (default 20 MB), count cap MAX_FILES_PER_MSG (default 10), a fixed allow-list (JPEG, PNG, GIF, WEBP, BMP, PDF, MP4, TXT) verified by magic bytes (name/MIME are never trusted), stored under a randomized owner-tagged key and served with X-Content-Type-Options: nosniff.
CSAT & complaints (bypass Intercom → our DB)
| Method | Path | Body | Description |
|---|---|---|---|
| POST | /api/csat | { stars 1–5, comment?, ticketId?, conversationId? } | Idempotent per (user, ticket); duplicate → { id: null, duplicate: true }. |
| POST | /api/complaints | { category, description (≥10), chatId?, dialogId? } | Stores a complaint. |
Complaint categories: funds · security · operator · technical · other.
Devices & settings
| Method | Path | Description |
|---|---|---|
| POST | /api/devices/register | { platform: "mobile"|"tma", token }. Upserts. |
| DELETE | /api/devices/:id | Unregister (on logout). |
| GET | /api/settings/notifications | Preferences (defaults all-on). |
| PUT | /api/settings/notifications | { chatMessages?, ticketUpdates?, systemNotices? }. |
Diagnostics
| Method | Path | Description |
|---|---|---|
| POST | /api/diagnostics | Log device telemetry (no PII). 204. |
Webhooks
| Method | Path | Description |
|---|---|---|
| POST | /webhooks/intercom | Intercom events. Public; HMAC-verified. See Webhooks. |
Error codes
| Status | error | When |
|---|---|---|
| 400 | validation_error / bad_request | Bad input. |
| 401 | unauthorized | Missing/invalid/expired token. |
| 429 | rate_limited | Per-user rate limit (see Retry-After). |
| 502 | service_unavailable | Intercom down / circuit open. |
| 500 | internal_error | Unexpected. |