API reference

API errors, limits, and retries

Check the HTTP status before using a response's data. Errors use this shape:

{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "The API key does not have the required scope.",
    "request_id": "example-request-id"
  }
}

Save the status, error code, and X-Request-Id response header for troubleshooting. Do not log credentials, signing secrets, private download URLs, or customer message bodies. When contacting support, share the request ID and operation rather than the secret.

Common responses

StatusMeaningWhat to do
400Invalid fields, cursor, or missing idempotency keyCheck the endpoint schema. Unknown JSON fields are rejected.
401Missing, invalid, revoked, or expired credentialsCheck the active connection. Refresh an expired OAuth access token or replace invalid credentials.
402Message sending requires billingConfirm the workspace's billed subscription before sending again.
403Missing permissions, read-only resource, blocked or opted-out recipientCheck the error code and access. Do not repeatedly retry denied actions.
404Missing or inaccessible resourceVerify the ID and connection scope; access restrictions can also produce this response.
409Idempotency, resource version, capacity, or sender-state conflictResolve the specific conflict before retrying. Fetch a changed resource again before editing.
410Expired or consumed uploadCreate a new reservation for a new intended send.
413Request, attachments, or response too largeReduce body or attachment size, or lower the list page size.
415Unsupported content typeUse the endpoint's required JSON or binary MIME type.
429Rate budget exhaustedWait for Retry-After, then retry with backoff.
503Service temporarily unavailableRetry with backoff; preserve the original idempotency key and body for writes.

Contact capacity and creation limits

  • CONTACT_LIMIT_REACHED (409): the workspace has reached its stored contact limit. Existing contacts can still be updated. Contact Waveline Support if you need more capacity; do not keep retrying the same create request.
  • CONTACT_CREATE_RATE_LIMITED (429): too many contacts were created by workspace integrations in a short period. Wait for Retry-After before retrying, and preserve the original idempotency key and request body.

Rate limits and request sizes

Requests share connection and workspace limits. Successful responses can expose RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset, plus a rate_limit object containing limit, remaining, and reset_at. Use the returned values rather than hard-coding a limit. 429 responses include Retry-After in seconds. A connection with remaining capacity can still be limited by workspace-wide request limits.

Keep concurrent requests bounded. After transient errors, use increasing delays with jitter so many jobs do not retry at once. Respect Retry-After when present.

LimitValue
JSON request body64 KiB
JSON response4 MiB
Binary upload5 MiB
Contact, call, and message page size1–100; default 50
Phone-number page size1–100; default 20
Cursor lifetime24 hours
Message text1,600 characters
Message attachmentsUp to 10; 5 MiB total

Pagination and filters

Paginated endpoints return data and next_cursor. Keep the same credentials, endpoint, filters, ordering, and limit when following a cursor, and stop when next_cursor is null. IDs are decimal strings and can exceed JavaScript's safe integer range; keep them as strings.

Contacts, calls, and messages default to order=oldest, which pages by ascending stable record ID. Use order=newest to start with the newest records and continue toward older records. Do not change the order while following a cursor.

For these lists, created_after is inclusive and created_before is exclusive. Include an explicit time zone. The filters apply to calls' start_time and to contacts' and messages' created_at; they do not find later edits to older contacts.

Conversations use most-recent-activity order, and their date filters apply to the last activity. A conversation that receives a new message while you page can appear again, so deduplicate by conversation ID. Pages are live results, not a frozen snapshot.

Phone numbers, contact notes, contact-property lists, call recordings, and message attachments also support cursor pagination. Their supported filters and ordering differ; use the relevant endpoint parameters rather than applying the contact-list options to every list. Teammate pagination is available only through the personal assistant connection described in API access and permissions.

Inbox and subscription lists return their complete authorized collections and do not accept pagination filters. Webhook delivery history accepts limit and returns recent records without a cursor or date range.

Idempotency for writes

Operations requiring Idempotency-Key accept 8–128 visible ASCII characters. Persist a unique key with each intended operation. Preserve the exact JSON body, path, and key when retrying an uncertain outcome.

Contact writes replay saved responses for seven days, subject to current resource access. Subscription creation retains its identity for seven days and returns current metadata and its signing secret; a disabled or deleted subscription rejects replay. Message-send deduplication is permanent. Subscription state changes are repeatable, and binary upload retries use the reserved upload ID instead of a separate idempotency header.

After the contact-write retention window, reconcile the existing resource before issuing another create. A new idempotency key represents a new operation and can create duplicates. Never resolve a send timeout by blindly creating a new key.

Previous
Webhooks