Reference
Errors
The HTTP status is the contract, and every body comes in the same envelope — a human-readable error message plus a machine-stable code, with hint, upgrade_url or docs_url attached when they help:
json400 Bad Request
{
"error": "ttl must be an integer number of seconds (min 60)",
"code": "invalid_ttl",
"docs_url": "https://ship.page/docs/errors"
}Status catalogue
| Status | When |
|---|---|
400bad request | Unparseable bodies, bad paths, invalid ttl/name values, per-request file caps, invalid zips. |
401unauthorized | Account routes without a credential, ?name= without a key, minting keys without an ID token — see Authentication. |
402payment required | Subscriber features (?name=, append, vanity) on a free account — a ttl past the plan cap is a 400 instead. See Limits & plans. |
404not found | Missing drops, keys or files — also returned for resources owned by someone else. |
405method not allowed | Wrong verb on a real path, e.g. POSTing to a served drop. |
409conflict | Vanity sub already taken, or the account already owns one. |
410gone | The drop is offline after expiry — it may still be privately claimable or restorable; see Expiry. Browsers get an “expired” page. |
413payload too large | A non-zip body over 10 MB, a zip over the plan cap or past its 4× decompression ceiling, or a drop hitting its 10,000-file total. |
429rate limited | 10 deploys/min per IP anonymous and free, 120/min per account on paid plans; 429s carry Retry-After: 60, so back off and retry. |
451unavailable for legal reasons | The drop was taken down — see Abuse & takedown. |
502 / 503upstream trouble | The billing backend or drop index is briefly unreachable. Retry shortly — deploys themselves fail open where safe. |
Browsers vs. API clients
On served drops (*.shipped.run and *.shipped.page), requests with Accept: text/html get small branded error pages for not-found, expired and removed drops; everything else gets the JSON envelope. The API origin (ship.page) always speaks JSON.
Last updated Jun 12, 2026