API Reference

REST API for programmatic access to ZeroDeploy.

OpenAPI Spec: Machine-readable API specification available at api.zerodeploy.dev/openapi.json

Base URL

text
https://api.zerodeploy.dev

Authentication

API requests require a token sent as a Bearer header. Tokens use fine-grained permissions in resource:action format.

http
Authorization: Bearer zd_xxxxxxxxxxxx

Each endpoint below shows the required permission (e.g., sites:read). Endpoints marked JWT only are not accessible via API tokens.

Create tokens via the dashboard or zerodeploy token create CLI command.


Drop API

Deploy with one HTTP call. No login, no CLI, no setup. Sites expire in 72 hours unless claimed.

POST /drop Public

Upload a single file or tar.gz archive to deploy a site. Returns a live URL, claim token, and expiration time. Sites expire in 72 hours unless redeployed or claimed. Send Content-Type: text/html for single files, application/gzip for tar.gz archives. Use X-Claim-Token header to redeploy (update) an existing drop site.

Headers: Content-Type (text/html or application/gzip), X-Filename (optional, default: index.html), X-Claim-Token (optional, for redeployment). Rate limit: 5 deploys per hour per IP. Max file size: 10 MB, max files: 1000, max total: 25 MB.

Request Body

json
{
  "body": "value"
}

Example

bash
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"body":"value"}' \
  https://api.zerodeploy.dev/drop

Response

json
{
  "data": {
    "data.url": "https://my-project.zerodeploy.app",
    "data.claim_token": "value",
    "data.expires_at": "2024-01-15T10:30:00Z",
    "next_steps.redeploy": {},
    "next_steps.claim": {}
  }
}
POST /drop/claim Token JWT only

Transfer an ephemeral drop site to your account. Requires authentication. Optionally provide a new slug to rename the site.

Request Body

json
{
  "claim_token": "value",
  "slug": "my-org"
}

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"claim_token":"value","slug":"my-org"}' \
  https://api.zerodeploy.dev/drop/claim

Response

json
{
  "data": {
    "data.site.id": "550e8400-e29b-41d4-a716-446655440000",
    "data.site.slug": "value",
    "data.url": "https://my-project.zerodeploy.app",
    "message": "Operation completed successfully"
  }
}

Organizations

Manage organizations (workspaces) that contain sites.

GET /orgs Token orgs:read

List all organizations the authenticated user owns or has access to.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/orgs

Response

json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "slug": "my-project",
      "plan": "free",
      "owner_user_id": "550e8400-e29b-41d4-a716-446655440000",
      "storage_used_bytes": 10485760,
      "created_at": "2024-01-15T10:30:00Z",
      "deleted_at": null
    }
  ]
}
GET /orgs/:orgSlug Token orgs:read

Get a single organization by slug.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/orgs/my-org

Response

json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "slug": "my-project",
      "plan": "free",
      "owner_user_id": "550e8400-e29b-41d4-a716-446655440000",
      "storage_used_bytes": 10485760,
      "created_at": "2024-01-15T10:30:00Z",
      "deleted_at": null
    }
  ]
}

Sites

Manage sites within organizations.

GET /sites Token sites:read

List all sites across all user organizations.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites

Response

json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "slug": "my-project",
      "org_id": "550e8400-e29b-41d4-a716-446655440000",
      "github_repo": null,
      "current_deployment_id": null,
      "storage_used_bytes": 10485760,
      "suspended_at": null,
      "suspension_reason": null,
      "password_protection_scope": "none",
      "is_ephemeral": 0,
      "ephemeral_expires_at": null,
      "ephemeral_ip_address": null,
      "created_at": "2024-01-15T10:30:00Z",
      "deleted_at": null
    }
  ]
}
POST /sites Token sites:write

Create a new site in an organization. Org slug is provided in the request body.

Request Body

json
{
  "slug": "my-org",
  "org_slug": "my-org",
  "github_repo": "value"
}

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"slug":"my-org","org_slug":"my-org","github_repo":"value"}' \
  https://api.zerodeploy.dev/sites

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "slug": "my-project",
    "org_id": "550e8400-e29b-41d4-a716-446655440000",
    "github_repo": null,
    "current_deployment_id": null,
    "storage_used_bytes": 10485760,
    "suspended_at": null,
    "suspension_reason": null,
    "password_protection_scope": "none",
    "is_ephemeral": 0,
    "ephemeral_expires_at": null,
    "ephemeral_ip_address": null,
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null
  }
}
GET /sites/:slug Token sites:read

Get a single site by slug.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site

Response

json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "slug": "my-project",
      "org_id": "550e8400-e29b-41d4-a716-446655440000",
      "github_repo": null,
      "current_deployment_id": null,
      "storage_used_bytes": 10485760,
      "suspended_at": null,
      "suspension_reason": null,
      "password_protection_scope": "none",
      "is_ephemeral": 0,
      "ephemeral_expires_at": null,
      "ephemeral_ip_address": null,
      "created_at": "2024-01-15T10:30:00Z",
      "deleted_at": null
    }
  ]
}
PATCH /sites/:slug Token sites:write

Update site GitHub repository.

Request Body

json
{
  "github_repo": "value"
}

Example

bash
curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"github_repo":"value"}' \
  https://api.zerodeploy.dev/sites/my-site

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "slug": "my-project",
    "org_id": "550e8400-e29b-41d4-a716-446655440000",
    "github_repo": null,
    "current_deployment_id": null,
    "storage_used_bytes": 10485760,
    "suspended_at": null,
    "suspension_reason": null,
    "password_protection_scope": "none",
    "is_ephemeral": 0,
    "ephemeral_expires_at": null,
    "ephemeral_ip_address": null,
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null
  }
}
DELETE /sites/:slug Token sites:write

Delete a site and all its deployments. This also removes all assets from storage.

Example

bash
curl -X DELETE \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site

Response

json
{
  "success": true,
  "message": "Operation completed successfully"
}
PATCH /sites/:slug/password Token sites:write

Enable or disable password protection for a site. Requires Pro plan.

Request Body

json
{
  "scope": "none",
  "password": "s3cret"
}

Example

bash
curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"scope":"none","password":"s3cret"}' \
  https://api.zerodeploy.dev/sites/my-site/password

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "slug": "my-project",
    "org_id": "550e8400-e29b-41d4-a716-446655440000",
    "github_repo": null,
    "current_deployment_id": null,
    "storage_used_bytes": 10485760,
    "suspended_at": null,
    "suspension_reason": null,
    "password_protection_scope": "none",
    "is_ephemeral": 0,
    "ephemeral_expires_at": null,
    "ephemeral_ip_address": null,
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null
  }
}

Deployments

Deploy and manage site versions.

POST /deployments Token / Deploy deployments:write

Create a new deployment for a site. Returns upload URL for the tar.gz archive.

Request Body

json
{
  "site_slug": "my-org",
  "pr_number": 0
}

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"site_slug":"my-org","pr_number":0}' \
  https://api.zerodeploy.dev/deployments

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "pending",
    "url": "https://my-project.zerodeploy.app",
    "error_message": null,
    "pr_number": null,
    "pr_title": null,
    "commit_sha": null,
    "commit_message": null,
    "branch": null,
    "file_count": 42,
    "total_size_bytes": 10485760,
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null,
    "org_slug": "value",
    "site_slug": "value",
    "preview_url": "https://my-project.zerodeploy.app",
    "upload_url": "https://my-project.zerodeploy.app",
    "upload_and_finalize_url": "https://my-project.zerodeploy.app",
    "limits": {}
  }
}
GET /sites/:slug/deployments Token deployments:read

List all deployments for a site, including which one is current.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/deployments
GET /sites/:slug/deployments/by-commit Token deployments:read

Find a ready deployment for one or more commit SHAs. Used by CLI to check if a preview can be promoted instead of re-deploying. Accepts comma-separated SHAs for merge commit support.

Query Parameters

  • commits — Comma-separated list of commit SHAs to check

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/example/deployments/by-commit

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "pending",
    "url": "https://my-project.zerodeploy.app",
    "error_message": null,
    "pr_number": null,
    "pr_title": null,
    "commit_sha": null,
    "commit_message": null,
    "branch": null,
    "file_count": 42,
    "total_size_bytes": 10485760,
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null
  }
}
GET /deployments/:id Token / Deploy deployments:read

Get deployment details by ID.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/deployments/abc12345

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "pending",
    "url": "https://my-project.zerodeploy.app",
    "error_message": null,
    "pr_number": null,
    "pr_title": null,
    "commit_sha": null,
    "commit_message": null,
    "branch": null,
    "file_count": 42,
    "total_size_bytes": 10485760,
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null
  }
}
GET /deployments/:id/files Token deployments:read

List all files in a deployment. Paginated with cursor.

Query Parameters

  • cursor — Pagination cursor from previous response
  • limit (default: 500) — Max files to return (default 500, max 1000)

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/deployments/abc12345/files

Response

json
{
  "data": [
    {
      "key": "index.html",
      "size": 10485760
    }
  ]
}
GET /deployments/:id/logs Token / Deploy deployments:read

Get structured logs from the deployment finalize process.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/deployments/abc12345/logs

Response

json
{
  "data": {
    "timestamp": "value",
    "level": "info",
    "phase": "value",
    "message": "Operation completed successfully",
    "metadata": {},
    "duration_ms": 0
  }
}
POST /deployments/:id/upload-and-finalize Token deployments:write

Upload a tar.gz archive and finalize the deployment in a single request. Uses multipart/form-data with an optional "archive" part and a required "metadata" part (JSON string with finalize options).

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/deployments/abc12345/upload-and-finalize

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "pending",
    "url": "https://my-project.zerodeploy.app",
    "error_message": null,
    "pr_number": null,
    "pr_title": null,
    "commit_sha": null,
    "commit_message": null,
    "branch": null,
    "file_count": 42,
    "total_size_bytes": 10485760,
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null,
    "preview": false
  }
}
POST /deployments/:id/diff Token deployments:read

Compare a manifest against the current deployment to determine which files need uploading.

Request Body

json
{
  "manifest": {}
}

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"manifest":{}}' \
  https://api.zerodeploy.dev/deployments/abc12345/diff

Response

json
{
  "data": {
    "upload_files": [],
    "copy_files": [],
    "removed_files": [],
    "previous_deployment_id": null,
    "is_incremental": false
  }
}
POST /sites/:slug/diff Token deployments:read

Compare a manifest against the site's current deployment without creating a new one. Used by CLI to skip deploys when nothing changed.

Request Body

json
{
  "manifest": {}
}

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"manifest":{}}' \
  https://api.zerodeploy.dev/sites/my-site/diff

Response

json
{
  "data": {
    "upload_files": [],
    "copy_files": [],
    "removed_files": [],
    "previous_deployment_id": null,
    "is_incremental": false
  }
}
POST /deployments/:id/rollback Token deployments:write

Set a previous deployment as the current one. Supports full ID or 8-char prefix.

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/deployments/abc12345/rollback

Response

json
{
  "data": {
    "deployment": {}
  }
}

Custom Domains

Add custom domains with automatic SSL to your sites.

POST /sites/:slug/domains Token domains:write

Add a custom domain to a site. Returns DNS verification instructions.

Request Body

json
{
  "domain": "example.com"
}

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domain":"example.com"}' \
  https://api.zerodeploy.dev/sites/my-site/domains

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com",
    "verification_status": "pending",
    "verification_token": "zerodeploy-verify=abc123",
    "verified_at": null,
    "redirect_mode": "none",
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null,
    "verification": {},
    "dns_provider": null,
    "existing_records": null
  }
}
GET /sites/:slug/domains Token domains:read

List all custom domains for a site.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/domains

Response

json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "site_id": "550e8400-e29b-41d4-a716-446655440000",
      "domain": "example.com",
      "verification_status": "pending",
      "verification_token": "zerodeploy-verify=abc123",
      "verified_at": null,
      "redirect_mode": "none",
      "created_at": "2024-01-15T10:30:00Z",
      "deleted_at": null
    }
  ]
}
GET /sites/:slug/domains/:domainId Token domains:read

Get a single custom domain by ID.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/domains/123e4567-e89b-12d3-a456-426614174000

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com",
    "verification_status": "pending",
    "verification_token": "zerodeploy-verify=abc123",
    "verified_at": null,
    "redirect_mode": "none",
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null
  }
}
DELETE /sites/:slug/domains/:domainId Token domains:write

Remove a custom domain from a site. Also removes Cloudflare custom hostname.

Example

bash
curl -X DELETE \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/domains/123e4567-e89b-12d3-a456-426614174000

Response

json
{
  "success": true,
  "message": "Operation completed successfully"
}
POST /sites/:slug/domains/:domainId/verify Token domains:write

Check DNS records to verify domain ownership. Creates Cloudflare custom hostname on success.

Example

bash
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/domains/123e4567-e89b-12d3-a456-426614174000/verify

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com",
    "verification_status": "pending",
    "verification_token": "zerodeploy-verify=abc123",
    "verified_at": null,
    "redirect_mode": "none",
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null,
    "site_slug": "value",
    "message": "Operation completed successfully",
    "cloudflare": {}
  }
}
PATCH /sites/:slug/domains/:domainId/redirect Token domains:write

Set www/apex redirect behavior for a domain.

Request Body

json
{
  "redirect_mode": "none"
}

Example

bash
curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"redirect_mode":"none"}' \
  https://api.zerodeploy.dev/sites/my-site/domains/123e4567-e89b-12d3-a456-426614174000/redirect

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "site_id": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com",
    "verification_status": "pending",
    "verification_token": "zerodeploy-verify=abc123",
    "verified_at": null,
    "redirect_mode": "none",
    "created_at": "2024-01-15T10:30:00Z",
    "deleted_at": null
  }
}

Forms

Manage form submissions from deployed sites.

GET /sites/:slug/forms Token forms:read

List all forms for a site. Forms are auto-created when submissions are received.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/forms

Response

json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "my-project",
      "submission_count": 42,
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}
GET /sites/:slug/forms/:formName Token forms:read

Get a single form by name.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/forms/contact

Response

json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "my-project",
    "submission_count": 42,
    "notification_email": null,
    "created_at": "2024-01-15T10:30:00Z"
  }
}
PATCH /sites/:slug/forms/:formName Token forms:write

Update form settings like notification email.

Request Body

json
{
  "notification_email": "user@example.com"
}

Example

bash
curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"notification_email":"user@example.com"}' \
  https://api.zerodeploy.dev/sites/my-site/forms/contact

Response

json
{
  "success": true,
  "form": {}
}
DELETE /sites/:slug/forms/:formName Token forms:write

Delete a form and all its submissions.

Example

bash
curl -X DELETE \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/forms/contact

Response

json
{
  "success": true,
  "message": "Operation completed successfully"
}
GET /sites/:slug/forms/:formName/submissions Token forms:read

Get paginated form submissions with parsed data.

Query Parameters

  • limit (default: 20) — Number of items to return (1-100)
  • offset (default: 0) — Number of items to skip
  • filterall, inbox, spam (default: all)

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/forms/contact/submissions?filter=all

Response

json
{
  "data": {
    "form": {},
    "submissions": [],
    "total": 42,
    "limit": 0,
    "offset": 0
  }
}
GET /sites/:slug/forms/:formName/export Token forms:read

Export all form submissions as a CSV file (up to 10,000 submissions).

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/forms/contact/export

Analytics

Privacy-friendly site traffic analytics.

GET /sites/:slug/analytics Token analytics:read

Get traffic analytics for a site including requests, visitors, top pages, countries, and more.

Query Parameters

  • period24h, 7d, 30d, 90d (default: 7d)
  • page
  • country
  • city
  • referrer
  • browser
  • os
  • devicedesktop, mobile, tablet
  • utm_source
  • utm_medium
  • utm_campaign
  • event_name
  • user_id

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/analytics?period=24h&device=desktop

Response

json
{
  "data": {
    "configured": true,
    "message": "Operation completed successfully",
    "period": "24h",
    "active_filters": {},
    "overview": {},
    "time_series": [],
    "top_pages": [],
    "countries": 42,
    "status_codes": [],
    "referrers": [],
    "cities": [],
    "browsers": [],
    "operating_systems": [],
    "device_types": [],
    "campaigns": [],
    "events": [],
    "not_found_pages": []
  }
}
GET /sites/:slug/analytics/realtime Token analytics:read

Get the number of distinct visitors on the site in the last 5 minutes.

Example

bash
curl \
  -H "Authorization: Bearer $TOKEN" \
  https://api.zerodeploy.dev/sites/my-site/analytics/realtime

Response

json
{
  "data": {
    "current_visitors": 0
  }
}

Error Responses

All errors follow a consistent format:

json
{
  "error": "Error message",
  "code": "ERROR_CODE",
  "hint": "Helpful suggestion to resolve the error"
}

Common Error Codes

Status Code Description
400VALIDATION_ERRORInvalid request body or parameters
401UNAUTHORIZEDMissing or invalid authentication
403FORBIDDENInsufficient permissions
404NOT_FOUNDResource not found
409CONFLICTResource already exists
429RATE_LIMITEDToo many requests
500INTERNAL_ERRORServer error