Developers

REST errors

Every REST error has the same JSON shape, so a client can handle them all in one place.

The error shape

Error body
{
  "error": {
    "type": "permission",
    "code": "insufficient_scope",
    "message": "This route needs the deliverables:read scope, which this token does not hold.",
    "param": "deliverables:read"
  },
  "request_id": "req_4f9aXc2b7d3e8f0a"
}
  • type is the broad class to branch on: invalid_request, authentication, permission, not_found, conflict, rate_limit, plan, server.
  • code is the specific reason, listed below.
  • param appears when one query parameter, field or scope is at fault, and names it.
  • request_id is also sent as the x-request-id header on every response, errors or not. Quote it when you contact support.

Error codes

CodeHTTPTypeMeaning
invalid_parameter422invalid_requestA query parameter or body field is unknown or has a bad value. param names it.
invalid_body422invalid_requestThe request body is not a JSON object, or a PATCH changes nothing.
invalid_idempotency_key422invalid_requestThe Idempotency-Key header is empty, longer than 255 characters, or has spaces or non-ASCII characters.
missing_token401authenticationNo Authorization: Bearer header was sent.
invalid_token401authenticationThe token is unknown, revoked or expired, or the admin who made it is no longer an active owner or admin.
plan_inactive402planThe workspace's plan is not active. Reads and writes both stop until an owner chooses a plan.
insufficient_scope403permissionThe token does not hold a scope this route needs. param names the scope.
plan_limit403planThe workspace's plan does not allow another active project. An owner can change the plan in Settings.
not_link_owner403permissionOnly the token that created an external link can change or delete it. Links made in the app, or by another token, are read-only to you.
not_found404not_foundNo such record in this workspace. Another workspace's ids, deleted records and unknown ids all answer this way.
project_closed409conflictThe project was closed through Wrap. Nothing on it can change until someone reopens it in Production Engine.
link_exists409conflictThe project already has a link with this provider and external_id. The message names the existing link's id.
idempotency_mismatch409conflictThis Idempotency-Key was already used for a different request. Use a new key for a new request.
idempotency_in_progress409conflictA request with this Idempotency-Key is still running. Retry after it finishes.
rate_limited429rate_limitToo many requests for this token. Wait the number of seconds in Retry-After.
internal_error500serverSomething failed on our side. Quote the request_id when you contact support.

Retries and idempotency

A network error can leave you unsure whether a POST landed. Send an Idempotency-Key header, any string of up to 255 visible ASCII characters that you make up per request (a UUID works), and retry with the same key and the same body as often as you need:

Request
curl -X POST https://production-engine.com/api/v1/projects/cmexampleproject01/links \
  -H "Authorization: Bearer $PE_TOKEN" \
  -H "Idempotency-Key: 4d1c9a2e-link-drive_8f2k" \
  -H "Content-Type: application/json" \
  -d '{"provider":"shade","external_id":"drive_8f2k","url":"https://app.shade.inc/example/drive_8f2k"}'
  • The first request runs. A retry within 24 hours gets the first response back, with the same status and body and an Idempotent-Replayed: true header, and writes nothing.
  • The same key with a different path or body answers 409 idempotency_mismatch. Use a new key for a new request.
  • A retry that arrives while the first request is still running answers 409 idempotency_in_progress. Wait a moment and retry. A request that never finished frees its key after 60 seconds.
  • A request that fails (any 4xx or 5xx) does not keep its key, so you can fix the body and retry with the same key.
  • Keys belong to one token. Another token's key with the same value is a separate request. After 24 hours a key can be used again as new.
  • PATCH and DELETE take no key: repeating a PATCH sets the same values again, and repeating a DELETE answers 404.