Errors and limits

Every error code the API returns, what causes it and how to handle it, plus rate limits and plan caps.

Errors come back as JSON with a human-readable error message you can show to a person, and, where your code should react differently, a stable machine-readable code. Branch on code and the HTTP status, never on the message text.

403 Forbidden
{
  "error": "You can keep 20 links on your plan. Delete one, or upgrade to Pro for unlimited links.",
  "code": "plan_limit"
}

Error codes#

StatuscodeWhat happenedWhat to do
401unauthorizedMissing, malformed or revoked API key.Check the Authorization header. See Authentication.
403bannedThe account is suspended.Contact support. Do not retry.
403plan_limitLink limit reached on the Free plan.Delete a link or upgrade.
403storage_limitThe upload would go over your total storage.Delete files or upgrade.
400size_limitThe file is bigger than your plan allows per file, but Pro would allow it.Upgrade, or send a smaller file.
400noneBad input: unsupported or blocked file type, the bytes don't match the extension, empty file, or a taken link name.Fix the request. Read error for details.
409path_in_useThat upload path was already used for a link.Start a new upload.
429rate_limitedToo many requests for this API key, or too many uploads this hour.Wait the number of seconds in the Retry-After header, then retry.
503retryA temporary problem finishing the upload.Retry with the same idempotencyKey.
500noneSomething failed on our side.Retry with the same idempotencyKey.

Rate limits#

Each API key has a request budget, counted in units. An analytics call (/api/v1/analytics, /api/v1/links/{slug}/analytics and the MCP analytics tools) costs 5 units; every other call costs 1. CORS preflight requests are free. The minute is a clock minute; the day is a UTC day.

PlanPer minutePer day (UTC)
Free60 units2,000 units
Pro and Lifetime300 units20,000 units

Every response carries X-RateLimit-Limit and X-RateLimit-Remaining for the current minute. Over the limit, the API answers 429 with a Retry-After header and a body like the one below (the MCP server returns a JSON-RPC error with the same details in data). A refused request does not use up your budget. scope says which limit you hit: minute, day, burst, auth (too many invalid keys from one address) or upload_hour (the hourly upload cap). One MCP batch that costs more than the whole per-minute limit can never succeed, so it gets 400 with code batch_too_expensive instead: split it into smaller batches. Analytics reports are cached on the server for 60 seconds, so asking for the same report more often returns the same numbers.

429 Too Many Requests
{
  "error": "Too many API requests (60 units per minute). Try again in 12 seconds.",
  "code": "rate_limited",
  "scope": "minute",
  "retryAfter": 12
}

Limits#

  • Hourly uploads: 30 per hour for Free accounts using an API key, on top of the rate limit above. Paid plans and new-account protections use the website's normal limits.
  • Plan caps: links, per-file size and total storage follow your plan. See Plans and limits.
  • Signed URLs expire after 10 minutes and accept exactly the size you declared.
  • MCP inline uploads (upload_file) take files up to 3 MB; use create_upload_url for larger ones.

Retry the right things

Retry 429 after its Retry-After, and 500 and 503 with a backoff, using the same idempotencyKey. Do not retry 400, 401 or 403: the same request will fail the same way.

Last updated 4 October 2026. Something unclear or missing? Tell us.