--- title: Create A Ticket (LLM) description: POST /tickets - create a ticket. Headoni API. --- # POST /tickets Create a ticket on the token's desk. Scope: `tickets:create`. Full URL: `https://.headoni.app/api/v1/tickets` Auth header: `Authorization: Bearer hd_` Content-Type: `application/json` The requester is the end user identified by `email` (created on first use), not the token owner. The token is recorded on the created event as the channel ("API Via "). ## Request Body | field | type | required | default | constraints | | --- | --- | --- | --- | --- | | email | string | yes | - | valid email, max 255, lowercased server-side | | name | string | no | local part of email | max 120; used only when the user is created | | subject | string | yes | - | 1 to 500 chars | | body | string | yes | - | 1 to 50000 chars; becomes the first public message | | priority | string | no | `normal` | one of `low`, `normal`, `high`, `urgent` | | departmentId | string | no | desk default department | numeric id; any non-deleted department on the desk (public or private) | | ticketTypeId | string | no | desk default type | numeric id; any non-archived type on the desk | ## Example Request ```bash curl -X POST https://acme.headoni.app/api/v1/tickets \ -H "Authorization: Bearer hd_your_secret_here" \ -H "Content-Type: application/json" \ -d '{ "email": "alice@example.com", "name": "Alice", "subject": "Login broken on staging", "body": "I loop back to /sign-in after typing my email.", "priority": "high", "departmentId": "1490375649123456789", "ticketTypeId": "1490375649987654321" }' ``` ## Success Response Status `201`. ```json { "ticket": { "id": "1490375649312800768", "number": 1247, "subject": "Login broken on staging", "priority": "high", "requester": { "email": "alice@example.com" } } } ``` - `id` is a string. `number` is the per-desk integer ticket number. - Read the full ticket back with `GET /tickets/{id or number}`. ## Blocklist Behavior If `email` is on the desk blocklist, the response is status `200` with body `{ "ok": true }` and no ticket is created. This is intentional to prevent enumeration of blocked addresses. Treat a `200 {ok:true}` as "accepted but not created". ## Errors | status | error | cause | | --- | --- | --- | | 400 | invalid_body | missing/malformed field; see `issues` | | 400 | department_not_found | `departmentId` not on this desk or soft-deleted | | 400 | ticket_type_not_found | `ticketTypeId` not on this desk or archived | | 401 | unauthenticated | missing or invalid token | | 403 | insufficient_scope | token lacks `tickets:create` | | 403 | token_desk_mismatch | token desk does not match the request host | ## Notes - No agent notification email is sent for API-created tickets (this is the bulk-import path). - To discover valid `departmentId` values: `GET /departments`. For `ticketTypeId`: `GET /ticket-types`.