For AI agents: a documentation index is available at /llms.txt. A markdown version of this page is available at /guide/api/errors.md.

APIIntroduction

Errors

Status codes the Developer API returns, what causes each one, and which are worth retrying.

Errors use standard HTTP status codes and the same envelope as successful responses, so you can parse both with one code path.

json
{
  "success": false,
  "message": "Invalid API key"
}

#Status codes

200Success. Check the success field for soft failures.
201Created. Returned by the create endpoints, with the new record's UUID in data.
401Authentication failed: missing or invalid API key, or a payload that does not decrypt.
403Authenticated, but the key's user cannot act on this record.
400Validation error: the decrypted payload is missing a field or has a bad value.
422Returned only by validate, when encrypted_data is missing.
429Rate limit exceeded.
500Server error.

#401 Unauthorized

By far the most common error while building an integration. It has three causes, and the message field tells you which:

MessageCauseFix
API key is requiredThe X-API-KEY header is absentSend X-API-KEY on every request
Invalid API keyKey unknown, inactive or expiredCheck the key in the admin portal
Failed to decrypt request dataencrypted_data does not decrypt with this key's secretSee below

#Debugging a payload that will not decrypt

Work through these in order:

  1. Check the key pair

    The secret must belong to the same key pair as the X-API-KEY you send. After a rotation, update both together.

  2. Check the AES key

    The AES key is the raw 32-byte SHA-256 digest of the secret, not its 64-character hex string.

  3. Check the IV

    Use 16 fresh random bytes per request, and prepend them to the ciphertext before Base64-encoding.

  4. Check the padding and encoding

    AES-256-CBC with PKCS#7 padding, standard Base64 (not URL-safe), and the plaintext must be valid JSON.

Tip

Call /api/v1/partner/validate while debugging. It decrypts your payload and echoes it back without touching any data, so if validate succeeds but a real call fails, the problem is in that call's payload, not your encryption.

#403 Forbidden

The key authenticated, but the user it is bound to cannot act on that record, for example a checklist in a project that user does not belong to. Use a key issued for a user with the right access.

#400 Validation error

The key was accepted and the payload decrypted, but its contents failed validation — a missing required field, an unknown status value, or a UUID where an integer id was expected. The message names each failing field:

json
{
  "success": false,
  "message": "Validation failed: {\"project_id\":[\"The project id field is required.\"]}"
}

Common causes:

  • Passing a user UUID to assigned_to, which expects a numeric id
  • A priority outside low, medium, high, urgent
  • A date that is not YYYY-MM-DD
  • Referencing a record in a project the key's workspace cannot see

#429 Too Many Requests

You have exceeded 120 requests in a minute or 5,000 in a day. The response carries headers telling you how long to wait:

less
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
Retry-After: 60

See Rate limits for how to stay under them.

#500 Server error

Something failed on our side. These are logged with a correlation id.

#What to retry

Retry rules

Retry 429 after Retry-After, and 500 with exponential backoff and jitter. Encrypt the payload again for each attempt so every request carries a fresh IV.

Never retry 400, 401 or 403 — they are deterministic and will fail identically until you change the request.

Retries are not idempotent

The create endpoints have no idempotency key. A retried tasks/create that actually succeeded the first time will create a second task. Confirm with a search before retrying a write that timed out.

#Audit trail

Every request, successful or not, is recorded with its status code, response time, calling IP and endpoint — the same trail the MCP server writes to. If a call behaves unexpectedly in production, that log is the place to start.