Skip to main content

Catch an error

Every failed request throws a subclass of PolymorfaError:
Each error has these fields: Error codes never change meaning. The API can add new ones, so handle unknown codes. isKnownPolymorfaErrorCode(code) tells you whether the installed SDK knows a code.

Error classes

402: the team cannot pay

Paid actions, such as starting a paid Number, reserve credit first. A 402 means the team cannot pay for the request or lacks the entitlement. Retrying does not help. Check the balance and plan in the Console, then try again. The SDK never retries a 402.

409: the resource changed

Settings with a revision, such as call settings and Number configuration, fail with state_conflict when someone else changed them after you read them. Read the current value, apply your change again, and send the new revision. A 409 with an idempotency_* code concerns your idempotency key. See Retry a write safely.

429: rate limited

rateLimitReason says which limit applied, such as request_rate or whatsapp. Wait for the retry-after header before you send again. The SDK already does this for requests it retries. See Rate limits.

Automatic retries

The SDK retries a request when both are true:
  • The request is a GET, HEAD, or OPTIONS, or it has an idempotencyKey.
  • It failed with a network error, a timeout, or status 408, 409, 429, or 5xx.
It waits for Retry-After when the API sends it, up to 60 seconds. Otherwise it backs off exponentially, up to 5 seconds between attempts. It retries twice by default. Set maxNetworkRetries on the client or the request to change that, or to 0 to turn retries off. A write without an idempotency key is sent once. The SDK does not retry it, because it cannot tell whether the first attempt ran.

Retry a write safely

An idempotency key makes a write safe to repeat. The API runs it once and returns the stored result for every repeat with the same key:
Use an ID from your own system, such as an order event ID, so a restarted process sends the same key. The API keeps each key for 24 hours per credential. These methods create a random key when you do not pass one, so their automatic retries are always safe: messages.send, messages.react, chats.editMessage, chats.deleteMessage, channels.reactToMessage, campaigns.create, campaigns.launch, campaigns.pause, campaigns.resume, campaigns.stop, webhooks.test, and operations.cancel.

Read every page

Lists of events, webhooks, webhook deliveries, operations, call records, and call opt-outs return a CursorPage. Loop over it with for await and the SDK fetches the next pages for you:
To fetch one page at a time, use items, hasMore, and nextPage():
nextPage() returns null after the last page. page.response.metadata holds the response metadata. Some methods return the API’s page envelope directly as { data, page }. Pass page.nextCursor as cursor while page.hasMore is true:
See Pagination for page limits.