ShipStatic Docs llms.txt llms-full.txt

Ship API

The REST API that powers all ShipStatic interfaces. Everything the Web, CLI, and SDK can do, the API can do directly.

https://api.shipstatic.com

Authentication

Anonymous deploys work without authentication — the response includes a claim URL the user can visit to keep the site permanently. For permanent deploys and management operations, pass an API Key or a deploy token in the Authorization header. The prefix determines the credential type:

Method Format Use case
API key Bearer ship-{64 hex} Persistent access, full account
Deploy token Bearer token-{64 hex} Scoped to deploys, optional TTL

When both are present, the deploy token takes precedence.

Endpoints

Deployments

Method Path Description
POST /deployments Upload a new deployment (multipart)
GET /deployments List all deployments (paginated)
GET /deployments/:id Get deployment details
PATCH /deployments/:id Update labels
DELETE /deployments/:id Delete deployment (async)

POST /deployments accepts an optional password field (6–128 characters) to protect the deployment with an unlock page. The plaintext is hashed with SHA-256 server-side; only the hash is stored. Deployment responses expose password: boolean indicating whether protection is active.

Domains

Method Path Description
PUT /domains/:name Create, link, switch, or label (upsert)
GET /domains List all domains (paginated)
GET /domains/:name Get domain details
DELETE /domains/:name Delete domain
POST /domains/:name/validate Pre-flight availability check
POST /domains/:name/verify Trigger DNS verification
GET /domains/:name/dns DNS provider for the domain (Cloudflare, Namecheap, etc.)
GET /domains/:name/records Required DNS records
GET /domains/:name/share Shareable DNS setup hash

Tokens

Method Path Description
POST /tokens Create token (full secret returned only here)
GET /tokens List all tokens (short identifiers only)
DELETE /tokens/:token Revoke token

Account

Method Path Description
GET /account Get current account
POST /account/claim Claim a public deployment with a claim hash
GET /activities Account audit log (paginated)
GET /labels Distinct labels in use across the account
GET /limits Plan-based platform limits (max file size, file count, total size)
GET /ping Health check

/config is a 301 alias for /limits, kept for older CLI versions.

Examples

Anonymous public deploy

curl -X POST https://api.shipstatic.com/deployments \
  -F 'files[]=@dist/index.html' \
  -F 'files[]=@dist/styles.css' \
  -F 'checksums=["d41d8cd98f00b204e9800998ecf8427e","..."]'

Response (201):

{
  "deployment": "happy-cat-abc1234",
  "url": "https://happy-cat-abc1234.shipstatic.com",
  "claim": "https://my.shipstatic.com/claim/...",
  "files": 2,
  "size": 4321,
  "status": "success",
  "password": false,
  "via": "sdk",
  "created": "...",
  "expires": "..."
}

claim and expires are present only on anonymous deploys. Visiting claim while signed in transfers the deployment to your account.

Authenticated deploy

curl -X POST https://api.shipstatic.com/deployments \
  -H 'Authorization: Bearer ship-...' \
  -F 'files[]=@dist/index.html' \
  -F 'checksums=["d41d8cd98f00b204e9800998ecf8427e"]' \
  -F 'labels=["production"]' \
  -F 'password=hunter22'

Response is the same shape minus claim and expires.

List with pagination

List endpoints return nextCursor when more pages exist. Pass it as cursor to fetch the next page.

curl -H 'Authorization: Bearer ship-...' \
  'https://api.shipstatic.com/deployments?limit=50'
{
  "deployments": [...],
  "nextCursor": "eyJpZCI6ImhhcHB5LWNhdC1hYmMxMjM0In0"
}

Custom domain — full flow

# 1. Validate the name
curl -X POST -H 'Authorization: Bearer ship-...' \
  https://api.shipstatic.com/domains/www.example.com/validate

# 2. Create + link to a deployment
curl -X PUT -H 'Authorization: Bearer ship-...' \
  -H 'Content-Type: application/json' \
  -d '{"deployment":"happy-cat-abc1234"}' \
  https://api.shipstatic.com/domains/www.example.com

# 3. Get required DNS records
curl -H 'Authorization: Bearer ship-...' \
  https://api.shipstatic.com/domains/www.example.com/records

# 4. After configuring DNS, trigger verification
curl -X POST -H 'Authorization: Bearer ship-...' \
  https://api.shipstatic.com/domains/www.example.com/verify

Claim a public deployment

curl -X POST https://api.shipstatic.com/account/claim \
  -H 'Authorization: Bearer ship-...' \
  -H 'Content-Type: application/json' \
  -d '{"claim":"<claim-hash-from-deploy-response>"}'

Returns the claimed deployment, now bound to your account.

Multipart upload shape (POST /deployments)

Field Type Notes
files[] File parts One per file. The filename carries the path (webkitRelativePath style)
checksums JSON-encoded string[] One MD5 per file, in the same order as files[]
labels JSON-encoded string[] Optional
password string Optional, 6–128 characters
via string Optional origin tag (cli, sdk, mcp, etc.)

Status Codes

Code Meaning Example
200 Success Read, update, synchronous delete
201 Created POST /deployments, POST /tokens
202 Accepted DELETE /deployments/:id (async cleanup)
400 Validation error Invalid input, missing fields
401 Authentication error Missing or invalid credentials
403 Forbidden Account terminated, plan limit reached, operation not permitted
404 Not found Resource doesn't exist or belongs to another account
413 Payload too large Bundle exceeds plan limits
422 Business rule Resource state doesn't allow this operation
429 Rate limited Too many requests; retry after Retry-After seconds

Pagination

List endpoints (/deployments, /domains, /tokens, /activities) return cursor-paginated results:

{ "deployments": [...], "nextCursor": "..." }

Pass the cursor as ?cursor=... to fetch the next page. nextCursor is absent on the final page. Default page size is 50; pass ?limit=N to override (capped at 100).

Rate Limits

Per-account global limiter; deploy endpoints additionally limited per-credential to prevent abuse. On exhaustion, the API returns 429 with a Retry-After header (seconds). Anonymous public deploys have a tighter per-IP limit than authenticated requests.

Conventions

Content type. All requests and responses use application/json, except deployment upload which uses multipart/form-data.

Domain names in paths are URL-encoded. The API normalizes casing and Unicode (e.g. Example.COMexample.com).

Async operations. Only deployment deletion is asynchronous (returns 202). All other deletes are synchronous (200).

Errors return a consistent shape:

{
  "error": "not_found",
  "message": "Deployment not found",
  "status": 404
}

error is the type tag (e.g. validation_failed, not_found, forbidden, rate_limit). message is the human-readable description. Some errors include a details object with structured context.