Errors & rate limits
BASE https://api.rii.link/v1AUTH: BEARER → AUTHENTICATION
One envelope, stable codes, honest headers. Match on code, never on message.
The error envelope
Every non-2xx response is this shape. code is stable and machine-matchable; message names the exact field or conflict; doc_url deep-links back into this page.
EXAMPLE · 409
{
"error": {
"code": "slug_taken",
"message": "\"summer\" is already claimed on rii.link.",
"doc_url": "https://rii.link/docs/api/errors#slug_taken"
}
}
Error codes
The full set. Codes are append-only — none of these will ever change meaning.
validation_failed · 400A field is missing or malformed — message names the field.invalid_key · 401Key missing, malformed, or revoked.scope_denied · 403The key exists but lacks the scope for this call.plan_upgrade_required · 403The call needs a higher plan — e.g. routing rules on Free.plan_limit_reached · 403A plan limit, such as active links or custom domains, is used up.not_found · 404No such id in this workspace.slug_taken · 409Also domain_in_use when deleting a host that still carries links.link_claimed · 409An anonymous shared link was already claimed or shut down.link_expired · 410The link passed its expires_at.rule_invalid · 422A routing rule references an unknown condition or malformed target.destination_unsafe · 422The destination URL is flagged as malware or phishing, or is on our blocklist. Every destination is checked when a link is created or updated.rate_limited · 429Budget exhausted — honor Retry-After.destination_check_unavailable · 503The destination could not be checked right now, so a link on a rii.link domain was not created. Retry after Retry-After.Rate limits
Per key, rolling window — 60 requests per minute on Free, 600 on Premium, custom on Enterprise. The budget rides on every response; 429s add Retry-After. Bulk import is why the CSV pipeline is on the roadmap — until it ships, pace writes.
HEADERS RIDE ON EVERY RESPONSE, NOT JUST 429S — BUDGET IS ALWAYS VISIBLE
RESPONSE HEADERS · 429
HTTP/2 429
x-ratelimit-limit: 600
x-ratelimit-remaining: 0
x-ratelimit-reset: 2026-08-12T09:17:00Z
retry-after: 14