Docs

cxthread Customer API

Create tickets and append replies with one endpoint. Messages land in cxthread tickets and their linked Slack threads.

Quick start

Use this flow for a production-safe first integration.

  • 1) Create or rotate an inbox API key in Admin → Inboxes.
  • 2) Send server-side POST requests to one endpoint.
  • 3) Store returned ticketToken in your app.
  • 4) Reuse the same ticketToken to append future replies.
The API is currently non-idempotent. Retry logic should include your own dedupe key strategy.

Authentication

All requests require a bearer token for a specific inbox.

Authorization: Bearer cxk_REDACTED

Keep API keys on your backend only. Never embed them in browser or mobile client bundles.

Endpoint

One endpoint handles both create and reply.

POST /api/v1/inbox/messages

Create ticket

Omit ticketToken. cxthread creates a new ticket + Slack thread.

Reply to ticket

Include a previously returned ticketToken.

Request body

Send JSON with Content-Type application/json.

Required fields

  • email: customer email.
  • message: inbound message text.

Optional fields

  • name: customer display name.
  • subject: used on first ticket create.
  • ticketToken: append to existing ticket.
  • externalId: your correlation key.
{
  "email": "customer@company.com",
  "message": "My app is broken.",
  "name": "Jane Doe",
  "subject": "Help!",
  "ticketToken": "optional",
  "externalId": "optional"
}

Create a new ticket (curl)

Use this when your app starts a new support conversation.

curl -sS -X POST "https://YOUR_DOMAIN/api/v1/inbox/messages" \
  -H "Authorization: Bearer cxk_REDACTED" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "customer@company.com",
    "name": "Jane Doe",
    "subject": "Help!",
    "message": "My app is broken.",
    "externalId": "user_123:request_456"
  }'

Append to an existing ticket (curl)

Reuse ticketToken from the first response to keep messages in the same ticket/thread.

curl -sS -X POST "https://YOUR_DOMAIN/api/v1/inbox/messages" \
  -H "Authorization: Bearer cxk_REDACTED" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "customer@company.com",
    "ticketToken": "TICKET_TOKEN_FROM_FIRST_CALL",
    "message": "Additional context: I tried restarting and it still fails."
  }'

Response payload

{
  "ok": true,
  "ticketId": "uuid",
  "ticketToken": "uuid",
  "messageId": "uuid"
}
  • ticketId: cxthread ticket UUID.
  • ticketToken: stable conversation token for future appends.
  • messageId: created inbound message UUID.

OpenAPI schema

For Postman/Insomnia import or SDK generation:

GET https://YOUR_DOMAIN/api/openapi

Errors and limits

Error responses are plain text with an HTTP status code.

  • 400 invalid input
  • 401 missing/invalid API key
  • 402 subscription inactive
  • 403 ticketToken does not belong to this inbox
  • 404 inbox not found/disabled
  • 413 message too large (over 20,000 chars)
  • 500 server error

Requests are not idempotent yet. Retries can create duplicate messages.

Full message bodies are stored in cxthread. Slack thread excerpts are truncated for readability.

Security notes

Treat inbox API keys as secrets. Rotate immediately if exposed in client logs, browser code, or public repos.

Need browser-safe intake? Use the website widget flow instead of direct API keys.