Support queue
This server stands in for the company's helpdesk. It pushes your team new tickets as they arrive. You read them, check them against the data, and write back what should happen. Your team gets its own 4-hour run, 20 tickets a minute, starting the moment your webhook is verified. What you write is visible only to your team.
1. Register your team
The queue has to reach your webhook over the internet. If your service runs on your laptop, expose it with ngrok (free account) and use the HTTPS URL it prints, plus your path:
brew install ngrok # or download from ngrok.com
ngrok config add-authtoken <your-token>
ngrok http 3000 # → https://<random>.ngrok-free.app
The free URL changes each time ngrok restarts. Update it with PUT /teams/me/webhook; your run keeps going.
2. Receive tickets
Your run starts when your webhook is first verified. Changing the URL later doesn't restart it.
- Webhook. The queue POSTs each event to your URL. Before the first delivery it sends
{"type":"webhook.verification","challenge":"…"}, and your endpoint must answer 200 with the challenge. Change the URL withPUT /teams/me/webhook. - Polling.
GET /events?after=<seq>returns your events after a cursor. Use it alongside the webhook to catch up after a restart.
An event only says what happened and to which ticket. Read the ticket for the content:
{ "id": "evt_TKT-015382", "seq": 1042, "type": "ticket.created", "sandbox": false,
"created_at": "…", "data": { "ticket_id": "TKT-015382", "simulated_at": "2025-09-15 00:19:02" } }
Webhook requests carry x-signature: t=<unix>,v1=<hex>, where v1 = HMAC-SHA256(webhook_secret, t + "." + raw_body). Answer 2xx within 5 seconds or the delivery is retried. Events arrive in order, at least once, so the same event can arrive twice.
3. Read and act
| GET /lake.db | History up to the cutoff as a SQLite file. Download it once. |
| GET /tickets/:id | The ticket as the customer sent it, their messages so far, and your own actions on it. |
| GET /records/:table | New or changed customers, invoices, payments, refunds and so on that lake.db doesn't have yet. |
| POST /tickets/:id/actions | close, reply or escalate, plus your labels and handoff. Needs an Idempotency-Key header. |
curl -X POST $QUEUE/tickets/TKT-015382/actions \
-H "authorization: Bearer $API_KEY" -H "idempotency-key: TKT-015382:1" \
-H "content-type: application/json" \
-d '{"action":"escalate","category":"Billing","priority":"High","flags":["churn_risk"],
"handoff":{"summary":"…","evidence":["INV-…"],"next_owner":"billing"}}'
When you act on a ticket, the customer may write back. That arrives as a ticket.message_created event.
4. Practise first
POST /sandbox/start sends 20 practice tickets to your team only, and the customers write back right after you act. Run it as often as you like; it isn't scored and doesn't touch the main run.
Reference
Every endpoint, field and error is in the API reference (OpenAPI JSON). Expect the queue to throttle you (429), fail now and then (500) and resend events during the run. Retrying an action with the same Idempotency-Key is always safe.