ticketNumber path parameter is that per-agent number, not a global id. A ticket’s channel records where it originated, such as email, the chat widget, or WhatsApp. Tickets created through this API always have channel: "api".
Statuses
Each ticket has a status, and each status belongs to one of six fixed categories:new, on_you, on_customer, on_hold, closed, cancelled. The statuses themselves are configured per agent in the dashboard; every category has exactly one default status.
Write endpoints accept a status in one of two forms, at most one per request:
List ticket statuses returns the AI agent’s active statuses with their ids, categories, and labels. Each status has two labels:
externalLabel is what the customer sees, internalLabel is what the dashboard shows.
Assignment and routing
When you create a ticket, the assignee fields decide whether auto-assignment runs.assigneeId and assigneeEmail are a mutually exclusive pair; sending both is a 400.
Update a ticket never auto-assigns. Omitted fields keep their current value,
assigneeId: null unassigns the ticket, and teamId: null clears the team.
List teams returns the AI agent’s teams; exactly one is the default.
Messages
A ticket’s thread contains three message types:metadata.eventType names the kind of change. Changes made by a trigger carry triggerId, triggerName, and runId, and every event from the same trigger run shares its runId. Webhook events report deliveryStatus (pending, delivered, or failed) and the statusCode your endpoint returned. New event kinds may be added, so treat an unknown eventType as a generic change rather than an error.
Add a message to a ticket currently accepts only type: "reply", attributed to a team member via authorId or authorEmail. The body is GitHub-flavored Markdown; raw HTML is stripped. Delivery to the customer is asynchronous, so a 201 means the reply was recorded, not that it reached the customer.
Endpoints
List tickets
Filterable, sortable, paginated list
Search tickets
Free-text search over ticket messages
Create a ticket
Open a ticket on behalf of a customer
Get a ticket
Retrieve a single ticket by number
Update a ticket
Change status, assignee, or team
List ticket messages
Read a ticket’s thread
Add a message to a ticket
Post an agent reply
List teams
The AI agent’s teams and the default
List ticket statuses
Configured statuses with ids and labels
Error codes
Helpdesk-specific error codes beyond the standard authentication and rate-limiting errors:| Code | HTTP | Description |
|---|---|---|
TICKET_NOT_FOUND | 404 | No ticket matches this number for the AI agent. |
CONVERSATION_NOT_TAKEN_OVER | 409 | The ticket is linked to a live conversation that has not been taken over from the AI agent, so a human reply cannot be posted. Take over the conversation from the dashboard first. |
MESSAGE_CONTENT_NOT_RENDERABLE | 422 | The message body rendered to empty HTML. This happens when it consists only of raw HTML, which is stripped. Send Markdown or plain text. |
TICKET_INVALID_STATUS | 422 | statusId does not belong to a status for this AI agent. |
TICKET_ARCHIVED_STATUS | 422 | statusId refers to an archived status, which cannot be applied. |
TICKET_TEAM_MEMBER_NOT_FOUND | 422 | Neither assigneeId nor assigneeEmail resolved to a team member on this account. |
TICKET_TEAM_NOT_FOUND | 422 | teamId does not belong to a team for this AI agent. |
TEAM_MEMBER_NOT_FOUND | 422 | On message creation, neither authorId nor authorEmail resolved to a team member on this account. |