Errors
Errors are JSON. Treat the status code as the contract and the message as a hint for humans - message wording is not stable and should not be parsed.
Status codes
Section titled “Status codes”| Status | Meaning | What to do |
|---|---|---|
400 |
Malformed request - bad JSON, unparseable CSR, invalid parameter | Fix the request. Retrying is pointless |
401 |
Missing, malformed, unknown or revoked token | Check the token; reissue if revoked |
403 |
Valid token, but its scopes do not cover this endpoint | Add the required scope - a new token, scopes are fixed at creation |
404 |
Not found, or not visible to your tenant | See below |
409 |
Conflict with current state, e.g. renewal already open | Read current state before retrying |
422 |
Well-formed but semantically rejected, e.g. CSR key too weak | Fix the input |
429 |
Rate limit exceeded | Back off - see rate limits |
5xx |
Server-side fault | Retry with backoff. If it persists, report it |
Why 404 and not 403 for another tenant’s data
Section titled “Why 404 and not 403 for another tenant’s data”Requesting a certificate that belongs to a different tenant returns 404, not
403. This is intentional: a 403 would confirm the object exists, which is
itself a leak. Isolation is enforced in the database, so from your token’s
perspective the row genuinely does not exist.
The practical consequence: a 404 on an ID you believe is correct usually means
wrong tenant or wrong region, not a deleted object.
Retry safety
Section titled “Retry safety”| Method | Safe to retry |
|---|---|
GET |
Always |
POST .../renew |
On 429 and 5xx. On 409, read state first - a renewal may already exist |
Renewal creation is not idempotent in v1: there is no idempotency key, so a blind
retry after an ambiguous timeout can open a second renewal. Check
GET /v1/requests for the certificate before retrying.