Errors and rate limits

The error format, every error code, and the request rate limit.

Error format

Errors use a non-2xx status and the same JSON shape:

{
  "error": {
    "message": "Your Pro plan includes 100 dynamic codes. Upgrade or archive a code to add another.",
    "code": "PLAN_LIMIT"
  }
}

message is written for people and safe to show to your users. Branch on code, not on the message text.

Invalid input returns INVALID_REQUEST with an issues list that says which field failed and why:

{
  "error": {
    "message": "Invalid request",
    "code": "INVALID_REQUEST",
    "issues": [
      {
        "code": "invalid_format",
        "format": "url",
        "path": ["url"],
        "message": "Invalid URL"
      }
    ]
  }
}

Error codes

StatusCodeMeaning
400INVALID_REQUESTA field is missing or invalid, or the body isn't JSON. See issues
401UNAUTHORIZEDMissing, wrong or revoked key. See Authentication
402PLAN_FEATUREThe workspace's plan doesn't include this. The message names the plan that does
402PLAN_LIMITA plan quota is full, for example dynamic codes or bio pages. The message gives the limit
403EMAIL_UNVERIFIEDThe person who created the key must verify their email address before creating dynamic codes
404NOT_FOUNDThe id doesn't exist in this workspace
409EDIT_LOCKEDThe code is over the plan's limit after a downgrade. It can't be edited until you upgrade or archive another code, and it stops redirecting 14 days after the workspace went over
409INVALID_STATEThe change doesn't fit the code's current state, for example changing the URL of a code that isn't a URL code
409INVALID_KEY_OWNERThe person who created the key no longer exists. Create a new key
422DESTINATION_BLOCKEDThe destination failed a safety check (for example a known phishing or malware site), or too many destination changes were made in a short time. The message says which
429RATE_LIMITEDToo many requests. Wait for the number of seconds in Retry-After
500INTERNALSomething went wrong on our side. Retry later

Plan errors look like this:

{
  "error": {
    "message": "This needs the Pro plan or higher (redirect rules; this workspace is on Starter). Upgrade at dynaqr.app/pricing.",
    "code": "PLAN_FEATURE"
  }
}

Rate limits

Each API key can make 120 requests per minute. Over the limit, the API returns 429 with a Retry-After header giving the seconds to wait:

HTTP/1.1 429 Too Many Requests
Retry-After: 23

{"error": {"message": "Rate limit exceeded", "code": "RATE_LIMITED"}}

Each key has its own limit. Retry 429 and 5xx responses with a backoff. Don't retry other 4xx errors without changing the request.