Endpoints
The full, always-current list of endpoints lives in the interactive explorer and the OpenAPI spec. This page covers the conventions every endpoint shares.
Response envelope
Successful responses wrap their result in data:
{ "data": { "id": "...", "ticketNumber": 42 } }
List endpoints add cursor pagination:
{
"data": [
/* ... */
],
"pagination": { "nextCursor": "eyJ...", "hasMore": true, "limit": 50 }
}
Pagination
List endpoints are cursor-based. Pass ?limit= (1-100, default 50) and, to fetch
the next page, ?cursor= with the previous response's nextCursor. When
hasMore is false, nextCursor is null.
Errors
Errors share a consistent shape and use standard HTTP status codes:
{
"error": {
"code": "forbidden",
"message": "Missing required scope(s): tickets:write"
}
}
| Status | Code | Meaning |
|---|---|---|
| 400 | validation_error |
Bad request body or query parameter |
| 401 | unauthorized |
Missing or invalid token |
| 403 | forbidden |
Missing scope or wrong token type |
| 404 | not_found |
Resource not found |
| 409 | conflict |
Duplicate, or related records still exist |
| 429 | rate_limited |
Rate limit exceeded |
| 503 | bot_unavailable |
A Discord-affecting action could not reach the bot |
Scopes
Each token carries scopes. Read endpoints need a :read scope; writes need
:write. Examples: tickets:read, tickets:write, categories:write,
transcripts:read, analytics:read, webhooks:write. Organization tokens also
use org:servers:read, org:members:read, org:analytics:read, and
org:transcripts:read for the aggregate endpoints.
A few resources share a scope with the thing they belong to rather than having
their own: automation rules and custom commands use flows:read / flows:write,
and canned replies use knowledgebase:read / knowledgebase:write. There is no
automations:*, commands:* or canned-replies:* scope. Every endpoint states
the scope it wants in the OpenAPI spec,
and a 403 for a missing one names the scope.
See Authentication for how to create tokens and assign scopes.
Rate limits
Requests are rate limited per token. Every response includes:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 299
X-RateLimit-Reset: 1780000000
When you exceed the limit you get a 429 with a Retry-After header. Limits
scale with plan tier.
Idempotency
POST /v1/tickets accepts an Idempotency-Key header. Retrying with the same key
within 24 hours returns the original result instead of creating a duplicate.
Secrets in flow nodes
Flow nodes that call third-party services (API Request, Send Webhook) store
credentials in their data object. Reads never return them in the clear.
GET /v1/flows/{id} replaces a stored authToken, authUsername, authPassword
and any credential-bearing header (authorization, x-api-key and similar) with
the literal string __redacted__. A field that holds no credential is returned
absent or empty, so you can still tell "a secret is set" from "there is no secret".
Writes accept the mask back:
| You send | Result |
|---|---|
__redacted__ |
the stored credential is kept |
| a real value | the credential is rotated |
"" |
the credential is cleared |
| the field omitted entirely | the credential is cleared |
That last row is the one to watch. A read-modify-write that strips unfamiliar
fields before PATCHing will delete the credential, and the flow will start failing
its API calls with no other symptom. Echo data back as you received it and change
only what you mean to change.