Inbox API
Sits on top of Conversations and powers the human-agent surface — who is currently viewing what, internal notes, saved filtered views, conversation routing, and quick-reply macros. Base path:/api/v1/inbox
Authentication: API key (X-API-Key) or session JWT. The dashboard uses a Clerk session, and server-to-server callers can use an API key against the same endpoints.
Using the SDKs
client.request() escape hatch above. See the Python SDK.
Returns the typed ApiResponse envelope. See the SDK index at SDK quickstart.
Live presence
Used by the inbox UI to show “X is viewing” + typing indicators. Heartbeat the viewing endpoint roughly every 20 seconds while the conversation is open. The server holds presence for a 30-second TTL, so a 20-second cadence keeps it alive with margin — heartbeating at the full 30 seconds races the TTL and intermittently drops your own presence.Example — heartbeat a conversation every 20 seconds
1. Register as viewing (send on open, then repeat every ~20 s):ttl_seconds: 30 is the caveat from above, verbatim: refresh well inside 30 seconds — the dashboard heartbeats at 20 seconds so a slow call still lands before the TTL expires. session_id is optional; pass it when a user can have several tabs open so each tab registers its own presence row.
2. Read the current viewers:
DELETE /{conversationId}/viewing unregisters immediately rather than waiting out the 30-second TTL.
Internal notes
Team-only notes attached to a conversation. Never visible to the contact; surfaced inline with messages in the inbox UI.Example — post a note with a mention
mentions carries the user ids your typeahead resolved while composing; each mentioned user gets a Notification Center entry. Response (201):
Saved views
Personal or team-wide filtered views over the conversation list — “My open WhatsApp conversations”, “VIP escalations”, “Stale > 4h”, etc.Example — create a team view with filters
filters object is the shared inbox filter AST — channels, statuses, assignee, tags, unread, search, date ranges, and more; every field is optional and combines conjunctively. scope: "team" requires owner/admin; "personal" (default) is visible only to you. Response (201):
Routing rules
Auto-assign incoming conversations to agents or teams based on channel, contact, content, or time. Rules are evaluated in priority order; first match wins.Example — create a rule, then dry-run it
Create (owner/admin only — routing writes are team-wide):conditions + action shape is strict (unknown fields are rejected with VALIDATION_ERROR). keyword entries are plain substrings, or /regex/ patterns — regexes that risk ReDoS are rejected at save time. time_of_day narrows the match to a weekly window (here: weekdays 09:00–18:00); omit it to match around the clock. Action types: assign_user, assign_team, assign_round_robin, assign_skill_based, set_tag, set_priority, trigger_agent.
Response (201):
rule (an inline create-style body) instead of rule_id to preview a rule before saving it. When matched is false, action comes back null — so a false verdict reads as { "matched": false, "action": null }.
Macros
Saved quick replies with optional variables, attachments, and post-actions (close, tag, assign).Example — create a macro, then run it
Create with a mustache variable and a follow-up step:{{extra.*}} variables:
{{contact.first_name}} resolve from the conversation’s contact; anything you pass in variables is exposed to the template as {{extra.<key>}}. On a partial failure the run returns HTTP 207 and failed_step reports the 1-based index of the step that threw.
See also
- Conversations API — the lifecycle this surface decorates