Publish via API
Publish a static site to IPFS with one anonymous HTTP request — no account, no key. This is the same endpoint the Drop page uses. It is aimed at agents and tools that just built a site and want to hand their user a live URL plus an ownership link.
Publishing by hand instead? Drop a folder walks through the same flow in the browser, including what claiming gets you.
Publish
zip -r site.zip ./dist/. # index.html must be at the zip root
curl -F artifact=@site.zip \
-F source=my-agent \
https://api.stasho.xyz/api/drop{
"dropId": "drop_…",
"claimToken": "…",
"url": "https://…", // the live gateway URL — share this
"cid": "bafy…", // IPFS CIDv1 — pin it anywhere
"expiresAt": 1765990000000, // ms epoch — claim deadline
"claimUrl": "https://app.stasho.xyz/drop/claim?drop=…#claim=…&exp=…"
}Request fields
| field | required | notes |
|---|---|---|
artifact | yes | a .zip with index.html at its root |
source | no | who you are, for attribution (≤64 chars, A-Za-z0-9 ._:/@-). Invalid values are ignored. |
Hand both links to your user
urlis live immediately — share it, open it, embed it.claimUrlturns the drop into an owned Stasho project: one click, sign in with email or a wallet, done. Unclaimed drops are removed 4 hours after publish — the claim link is how your user keeps the site. The token inclaimUrlrides the URL fragment, so it never reaches a server; whoever holds the link can claim the site.
Say what claiming unlocks, not just that it exists: it is free, and it turns the drop into a Stasho project with its own page, where your user can connect a custom domain and publish updates by dragging a new folder onto the project page. A claimed drop has no repo behind it, so the repo-connected affordances (GitHub push-to-deploy, build settings) belong to a separate repo-connected project, not to this one. Updating a claimed drop happens from its page in the browser; there is no authenticated API endpoint for updates yet.
Current limits
These are operational values, not contract — they can change with a note in this page's changelog.
| limit | value |
|---|---|
| zip size (compressed) | 10 MB |
| extracted size | 40 MB, max 1000 files |
| claim window | 4 hours |
| drops per IP | 10/hour, 20/day |
| concurrent uploads per IP | 1 |
Errors
| status | meaning |
|---|---|
| 400 | missing artifact, unsafe zip, or no root index.html |
| 413 | zip too large |
| 429 | per-IP rate limit, or an upload already in flight from your IP |
| 500 | publish failed — safe to retry |
| 503 | drops paused (busy, daily budget, or feature disabled) |
Stability
The endpoint path, request shape, response fields, and error statuses above are stable. Browser (CORS) access is deliberately not enabled: call this server-side. If keyed access ships in the future it will use an Authorization: Bearer header and per-key quotas layered above the per-IP limits — unkeyed callers will keep working unchanged.