Skip to content
Dashboard
Menu Account API · List & delete drops

Account API

List & delete drops

Drops deployed with an Authorization header belong to your account, and these routes manage them — plus the API keys behind them. All paths are relative to https://ship.page and expect a Bearer credential as described in Authentication.

Drops

These endpoints cover the lifecycle: list what you've deployed, delete what you no longer need, claim drops you deployed anonymously, restore expired drops, manage passwords, and pull view stats.

GET

/drops

sp_ key or ID token

Returns the drops owned by the account, newest first. expires_at is null on subscriber drops, since those never expire.

Query parameters

limit
Drops per page — up to 500, default 100.
offset
Number of drops to skip; combine with limit to page through large accounts.
json 200 OK
{
"total": 12,
"drops": [
{
"slug": "launch-metrics-c2dse",
"url": "https://launch-metrics-c2dse.shipped.run/",
"name": "launch-metrics",
"file_count": 3,
"redeploy_count": 7,
"password_protected": false,
"created_at": "2026-06-02T09:14:00.000Z",
"updated_at": "2026-06-09T16:41:00.000Z",
"expires_at": null
}
]
}
DELETE

/drops/<slug>

sp_ key or ID token

Removes a drop. The <slug> is the subdomain part of the drop's URL — for launch-metrics-c2dse.shipped.run that's launch-metrics-c2dse.

json 200 OK
{
"deleted": "launch-metrics-c2dse"
}

Deletion is permanent. Files and the drop's index entry are purged immediately and can't be restored. The edge cache may keep serving the page for up to 60 seconds after the call returns.

POST

/drops/<slug>/claim

sp_ key or ID token

Attaches an anonymously deployed drop to your account. Every anonymous POST /deploy response carries a one-time claim_token (spc_…, shown once) — send it here and the drop becomes yours: listable, deletable, and redeployable on paid plans. Claiming extends the drop to the free-account lifetime of 90 days — including anonymous drops recovered during the 30 days after expiry, when they are offline but remain privately claimable.

json request body
{
"claim_token": "spc_7xk3m9q2vj8n4p1w6z5y0r2t"
}
json 200 OK
{
"slug": "launch-metrics-c2dse",
"claimed": true,
"restored": false,
"expires_at": "2026-10-02T14:00:00.000Z",
"url": "https://launch-metrics-c2dse.shipped.run/"
}

Answers 403 on a wrong token, 409 when another account claimed the drop first, and 404 for unknown slugs, and 410 once the 30-day claim window has closed. Re-claiming a drop you already own is a no-op 200.

POST

/drops/<slug>/restore

sp_ key or ID token

Brings an expired drop you own back online while its files are still retained (90 days past expiry). Free accounts restore up to 30 days past expiry and the drop comes back at the free 90-day lifetime; subscribers restore up to 90 days and the drop never expires again.

Answers 402 when the drop is too old for a free account (upgrade to restore), 410 once the files are purged for good, 409 on a concurrent state change (retry), and 404 for unknown or unowned slugs. Restoring a drop that is still live is a no-op 200.

GET

/drops/<slug>/stats

sp_ key or ID token

Pageview analytics for a drop you own: all-time totals (within the 90-day retention window), the last 24 hours and 7 days, and a daily views series. Bots and crawlers are excluded; views count page loads of HTML pages, not raw asset requests. The same numbers power the stats dialog on the dashboard Drops page.

Free accounts get a 7-day history window (window_days); paid plans get 90 days plus top_referrers and top_paths (up to 5 entries each; a direct referrer means none was sent).

json 200 OK
{
"slug": "vast-juice-c2dse",
"total": 128,
"last_24h": 9,
"last_7d": 41,
"window_days": 90,
"daily": [{ "day": "2026-08-21", "views": 12 }],
"top_referrers": [{ "label": "chatgpt.com", "views": 30 }],
"top_paths": [{ "label": "index.html", "views": 120 }]
}

Manage password protection

PUT /drops/<slug>/password with JSON {"password":"…"} sets or rotates the password. It requires ownership and active paid Pro/Team. Passwords are 8–128 Unicode characters, at most 512 UTF-8 bytes; billing that cannot be verified returns 503 without changing protection.

DELETE /drops/<slug>/password removes protection with no body. It remains available to the owner after a plan lapses; canceling alone does not remove the gate. Both endpoints return {slug, password_protected}, never a password. Unknown or unowned slugs return 404.

Browser unlock

Protected pages and assets return 401 until unlocked. The gate sends POST /_ship/password on the drop’s own HTTPS origin, with JSON {password} and an Origin header matching that exact origin. Success sets a host-only browser session lasting 12 hours. An account API key is not a visitor session; protected responses bypass caching. Never put a password in a URL.

Live named redeploys without a password and file appends preserve protection. Recreating an expired or purged named drop is a new deploy: send the password again. The /_ship/ namespace is reserved for service endpoints. Protection cannot recall content downloaded, copied, or cached while public; reuploading does not invalidate old downloads.

API keys

Keys are what curl and CI authenticate with: mint them from a dashboard session, list their metadata, revoke them when they leak or retire. Formats and scoping are covered in API keys.

POST

/keys

Firebase ID token

Mints a new API key. This is the one route that requires a Firebase ID token from your dashboard session — existing sp_ keys can't mint new keys.

json 201 Created
{
"accountId": "9f1c2c4e-7b2a-4f5e-a1d3-2c8b51b6f0aa",
"apiKey": "sp_QffDmo0uWxx_BKbZjjtSwdgPaksp58XTGgj0tsLZfhU",
"keyId": "8c1f4b2e6a9d35c7e0b8a2f41d6c9e3b5a7d0f82c4e6b1a39d5f7c0e2b4a6d81",
"note": "Shown once — store it. Send as 'Authorization: Bearer <key>' …"
}

The key is shown once — we only store a hash. Copy it into your secret manager before closing the response; there's no way to retrieve it later.

GET

/keys

sp_ key or ID token

Lists the keys on the account. Only metadata comes back — the secret itself is never returned, just the prefix so you can tell keys apart.

json 200 OK
{
"keys": [
{
"id": "8c1f4b2e6a9d35c7e0b8a2f41d6c9e3b5a7d0f82c4e6b1a39d5f7c0e2b4a6d81",
"prefix": "sp_QffDmo0",
"created_at": "2026-05-28T11:02:00.000Z",
"last_used_at": "2026-06-10T07:55:00.000Z"
},
{
"id": "2f9e7c4b1a6d8e3c5b0a9f7d4e2c6b8a1d3f5e7c9b0a2d4f6e8c1b3a5d7f9e0c",
"prefix": "sp_b7Rt2wX",
"created_at": "2026-04-12T15:30:00.000Z",
"last_used_at": null
}
]
}
DELETE

/keys/<id>

sp_ key or ID token

Revokes a key by its id (from GET /keys) — the id is the key’s SHA-256, 64 hex chars. Takes effect on the very next request.

json 200 OK
{
"revoked": "2f9e7c4b1a6d8e3c5b0a9f7d4e2c6b8a1d3f5e7c9b0a2d4f6e8c1b3a5d7f9e0c"
}

Any CI still using this key fails immediately. Revocation is instant — rotate the secret in your pipelines before you delete the key here.

Last updated Jun 12, 2026