Open a ticket by hand, stamped with its SLA and create macros
Open a ticket by hand, or record one migrated from another system.
/v1/ticketsEditor- Operation id
- create_ticket
- Access
- A viewer is refused.
/v1/ticketsOpen a ticket by hand, or record one migrated from another system.
Use this for an operator-authored ticket. Inbound customer traffic should go through the channel ingress routes instead, which thread replies onto existing tickets and record provenance. Every id in the body is checked to exist in the calling workspace before the row is written.
On create the ticket is stamped with the SLA policy matching its priority,
and every enabled macro whose trigger includes create and whose conditions
match is applied before the response is returned.
Tenancy: the request is scoped to one workspace, and the credential presented is what selects it. A caller with no membership in that workspace is refused with 404, which is indistinguishable from a workspace that does not exist.
Authorisation: editor, admin or owner. A viewer receives 403 insufficient_role.
Access: Authorization: Bearer carrying either a realm access token or an API key. A key must hold the tickets:write scope, and the workspace role of the person who owns it must meet the floor above.
A realm-issued access token, presented as Authorization: Bearer <token>. It acts as the person who signed in, and every operation resolves their workspace role live from the membership record.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/tickets" \ -H "Content-Type: application/json" \ -d '{ "subject": "Card declined at checkout", "description": "Customer\'s Visa is declined on every attempt since Tuesday.", "priority": "high", "source": "manual", "customer_id": "9f1d6c4e-6b6e-4b31-9a5b-2f1c9a4d5e60", "assignee_id": "3fe98b76-2409-5003-b75a-93e56b450433", "team_id": "d907a188-148a-5522-82a6-55798ccdecb6", "tags": [ "billing", "vip" ], "metadata": { "order_id": "A-1042" } }'{ "id": "5e8b0c31-7a4d-4f92-b6c8-1d3e2a5f7b90", "subject": "Card declined at checkout", "description": "Customer's Visa is declined on every attempt since Tuesday.", "status": "open", "priority": "high", "source": "manual", "assignee_id": "3fe98b76-2409-5003-b75a-93e56b450433", "assignee_name": "Dana Osei", "customer_id": "9f1d6c4e-6b6e-4b31-9a5b-2f1c9a4d5e60", "customer_name": "Sam Okafor", "customer_email": "sam.okafor@northwind.example", "team_id": "d907a188-148a-5522-82a6-55798ccdecb6", "team_name": "Billing", "tags": [ "billing", "vip" ], "metadata": { "order_id": "A-1042" }, "first_response_due": "2026-08-14T12:20:00+00:00", "resolution_due": "2026-08-15T10:20:00+00:00", "sla_breached": false, "sla_policy_id": "b6a0f2d7-4c19-4e63-8f52-7a1b9c0d3e46", "created_at": "2026-08-14T10:20:00+00:00", "updated_at": "2026-08-14T10:20:00+00:00", "legal_next_states": [ "closed", "on_hold", "pending", "solved", "spam" ], "assignee_email": "dana.osei@northwind.example", "time_total_minutes": 0, "time_billable_minutes": 0, "todo_counts": { "open": 0, "done": 0, "overdue": 0 }, "events": []}Update many tickets at once
Multi-ticket update. Skips tickets whose current status doesn't legally permit the requested mutation (so a bulk "Mark solved" on a list that includes already-merged tickets safely...
Get one ticket with its full timeline
Everything the ticket detail view needs in one call: the ticket, its resolved assignee/customer/agent/team names, its SLA state, its own logged time and todo counts, and its comple...