Skip to main content

Base URL

All endpoints are relative to:

Request and response format

  • All requests that send a body use Content-Type: application/json.
  • All responses are JSON. Timestamps are ISO-8601 strings in UTC (2026-01-01T00:00:00.000Z).

Pagination

List endpoints return cursor-based pagination by default:
Pass nextCursor as the cursor parameter in the next request. Use limit to control page size (default 20, max 100). Some endpoints that are offset-indexed by design (activity logs, analytics feeds) use page-based pagination instead:
For example, advance through GET /messages with ?page=2&limit=25, not with a cursor. The endpoint’s OpenAPI parameters are the source of truth when choosing a pagination mode.

Nested query filters

Object-shaped query parameters use OpenAPI deepObject encoding. For example, this live audience filter returns people enrolled in one campaign:
Do not send the rule tree as a JSON string in a single filter= parameter.

Expansions

Some detail endpoints (GET /{resource}/{id}) support inline expansion of related objects via expand[]:
Expansion fields are always optional in the response — the base response never changes, only the expanded fields are added.

Errors

All errors follow the same envelope:
param and issues appear for schema-validation errors. They identify invalid fields without echoing submitted values. Domain errors can instead include an actionable hint and doc_url.

Soft deletes

Any resource that has been used (sent from, enrolled into, etc.) is never hard-deleted. DELETE on such a resource returns the row with archivedAt set. Archived resources are excluded from list results by default; pass ?includeArchived=true to include them.

IDs

All IDs are prefixed cuid2 strings (e.g. cnt_, sndr_, prg_, msg_). They are not time-sortable — always sort lists by createdAt or occurredAt.

Rate limits

Rate limits are per-organization per-endpoint. On 429 the Retry-After header tells you how many seconds to wait.