Handle API errors, pagination, retries, and realtime events
Interpret errors, follow cursors, retry supported writes carefully, respect rate limits, and reconnect to workspace event streams.
Updated
Use this guide when integrating with the workspace Platform API at https://api.protodesk.io/v1. Consult the public OpenAPI contract for each endpoint's scope, parameters, and response.
Help Center authoring, public Help Center reads, and customer Chat have their own contracts. Do not assume their authentication, pagination, or retry rules are identical. Internal /app endpoints are not a substitute for a supported public API.
Verify authentication and workspace first
Send the API key in the Authorization: Bearer <your-api-key> header from your server. Use GET /v1/me to confirm the workspace and granted scopes before processing data or making changes.
Use only the permissions the integration needs. A Help Center authoring key cannot automatically read customers, manage webhooks, or open a workspace event stream. Test and Live labels are not isolated environments; the workspace behind the key is the actual target.
Never place a workspace API key in browser JavaScript, a query parameter, a support message, or a public example. Keep authorization headers out of logs. See Create and manage API keys.
Read errors as structured responses
The standard API error body includes an error object with code, message, and requestId, sometimes with additional details. Read the HTTP status and stable code rather than matching only the human-readable message.
| Response | What to do |
|---|---|
| 400 | Correct the request: check JSON, required fields, event names, limit, and cursor. Repeating the unchanged invalid request will not help. |
| 401 | Check the Bearer header, key value, expiry where applicable, and revocation. Do not repeatedly retry invalid credentials. |
| 403 | Check the required scope and authorization. Ask an authorized administrator for the specific access needed, not a blanket full-access key. |
| 404 | Check the resource ID, route, and key's workspace. A resource in another workspace is not accessible by changing a query parameter. |
| 409 | Inspect the code and current state. An idempotency conflict and a request still in progress require different handling. |
| 413 | Reduce the payload to the endpoint's documented size. Ordinary Platform API JSON writes have a 64 KiB default cap; specialized routes can differ. |
| 429 | Slow down, respect Retry-After when supplied, and reduce concurrent requests. |
| 5xx or network timeout | Treat the outcome as uncertain, especially for writes. Use bounded retries only when safe, and reconcile before issuing a new operation. |
Record the request ID, method, endpoint, approximate time, and non-secret error code for support. A timeout after a write does not prove that the server made no change.
Follow pagination without guessing cursors
Common resource lists, including customers, conversations, webhook subscriptions, and delivery history, use:
data: the current page.hasMore: whether another page is available.nextCursor: the opaque position for the next request.
Start without a cursor. On these lists, limit defaults to 25 and accepts 1–100. When hasMore is true, pass the returned nextCursor unchanged as the next request's cursor, keeping the same endpoint and filters. Stop when there are no more results.
Do not decode, edit, invent, or substitute cursors between lists. If the response claims more data but has no usable cursor, stop and investigate instead of repeating the same page indefinitely. These are live lists, not a frozen export; concurrent changes can require reconciliation and deduplication by resource ID.
Endpoint-specific exceptions matter. For example, Help Center authoring's article list accepts its returned cursor as after, not cursor. Follow that endpoint's contract rather than a universal pagination helper that assumes one parameter name.
Retry writes deliberately
An Idempotency-Key identifies one logical operation on endpoints that explicitly support it. It is not a universal retry switch for every POST, PATCH, or DELETE. Creating a webhook subscription supports it; sending a webhook test does not use the same replay middleware.
For a supported write:
- Generate a unique key before the first attempt and store it with the intended operation.
- Reuse that key only for the same method, resource URL, query, and exact request body. Do not change JSON formatting or field values between retries.
- Keep keys unique across operations in the workspace, including operations aimed at different resource IDs.
- On a replayed response,
Idempotency-Replayed: trueindicates a stored response was returned. - On
idempotency.in_progress, wait before retrying the identical request with the same key. Onidempotency.conflict, stop and check what the key was previously used for; do not blindly choose another key.
The common Platform API replay store has a 24-hour default lifetime. Do not depend on an old key to prevent duplicates indefinitely. Other surfaces, including Help Center authoring, have separate idempotency rules and limits.
Even with an idempotency key, an uncertain write deserves care: not every internal failure is an atomic rollback of both the resource change and saved replay response. Check supported resource reads or ask support before starting a replacement operation. Keep retries bounded with increasing delays and jitter.
Respond to rate limits
When available, inspect RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. In this API, the reset value is a duration in seconds, not a Unix timestamp. A throttled request can also return Retry-After in seconds.
Read and write requests use separate budgets; heavier routes can have a separate budget too. Do not hard-code one requests-per-minute number for all operations or create extra keys to evade throttling. Queue work, cap concurrency, and back off when told to retry later. Missing limit headers do not establish unlimited capacity.
Reconnect to workspace realtime events
GET /v1/realtime/events uses Server-Sent Events and requires realtime:read. It carries workspace events, not the customer-scoped Chat connection. Keep the API key and the stream on a trusted server; do not expose this workspace feed directly to customers.
Each event has SSE id, event, and JSON data fields. Optional filters are conversationId and a comma-separated eventTypes list. A filter narrows the feed; it does not turn the key into a customer-scoped credential.
Save the last event ID only after your consumer has durably handled it. Reconnect with that ID in Last-Event-ID, or the cursor query parameter. If both are supplied, the query cursor takes precedence. This event ID is different from a resource-list pagination cursor.
Without a cursor, the stream starts after the latest existing event and sends new events only. It does not return the workspace's full history. Normal idle heartbeat comments contain no business event, and long-lived connections are periodically closed so clients can reconnect.
Handle disconnects and comment-only errors, reconnect with backoff, and deduplicate event IDs. If the API returns realtime.invalid_cursor, do not silently discard the cursor and assume no events were missed. Reconcile the affected resources and deliberately establish a new checkpoint. The stream is not a permanent audit archive or an exactly-once delivery guarantee.
Related articles
- Integrate Live Chat identity and messagingEmbed the website widget, distinguish anonymous and verified visitor identity, and handle scoped Chat messaging safely.
- Read published Help Center content through the APIUse the read-only public API to find a live Help Center, list and search published articles, and retrieve a full article safely.
- Make your first supported API requestCreate a limited workspace key, verify its scopes and workspace with /v1/me, and safely make your first public API read.
- Manage conversations and messages through the APICreate and manage conversations, read messages safely, and distinguish recorded API messages from channel delivery.
- Manage customers and identities through the APICreate and upsert customers, read and patch profiles, and link channel identities without confusing records or verification.