creek

HTTP API

Deploy websites programmatically via the Sandbox API. No API key required.

Overview

The Sandbox API lets you deploy websites with a single HTTP request. No account, no API key, no CLI installation needed.

curl -X POST https://sandbox-api.creek.dev/api/sandbox/deploy \
  -H "Content-Type: application/json" \
  -d '{
    "assets": {
      "index.html": "<base64-encoded-content>"
    },
    "source": "my-agent"
  }'

Endpoints

POST /api/sandbox/deploy

Deploy files to a sandbox preview (60 min TTL).

Request body:

{
  "assets": {
    "index.html": "PGh0bWw+Li4u",
    "style.css": "Ym9keSB7fQ==",
    "app.js": "Y29uc29sZS5sb2coKQ=="
  },
  "source": "my-agent"
}
FieldTypeRequiredDescription
assetsRecord<string, string>YesFile path → base64-encoded content
sourcestringNoSource identifier for tracking
manifestobjectNoOptional — derived from assets keys
frameworkstringNoFramework hint

Response (202):

{
  "sandboxId": "a1b2c3d4",
  "status": "queued",
  "statusUrl": "https://sandbox-api.creek.dev/api/sandbox/a1b2c3d4/status",
  "previewUrl": "https://a1b2c3d4.creeksandbox.com",
  "expiresAt": "2026-03-27T16:00:00.000Z"
}

Rate limit: 10 deploys per hour per IP. Demo deploys (source: "cli-demo") are exempt.

Rate limit headers:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1774624000
Retry-After: 3200  (only on 429)

GET /api/sandbox/:id/status

Poll deployment status.

{
  "sandboxId": "a1b2c3d4",
  "status": "active",
  "source": "my-agent",
  "renderMode": "spa",
  "assetCount": 3,
  "previewUrl": "https://a1b2c3d4.creeksandbox.com",
  "deployDurationMs": 9234,
  "createdAt": "2026-03-27T15:00:00.000Z",
  "expiresAt": "2026-03-27T16:00:00.000Z",
  "expiresInSeconds": 3200,
  "claimable": true,
  "failedStep": null,
  "errorMessage": null
}

Status values: queueddeployingactive (or failed, expired).

DELETE /api/sandbox/:id

Delete a sandbox before expiry. Only the creator (same IP) can delete.

POST /api/sandbox/:id/claim

Mark a sandbox as claimed (after creek login + creek claim).

POST /api/sandbox/:id/report

Report abuse on a sandbox deployment.

Error Format

All errors return structured JSON:

{
  "error": "rate_limited",
  "message": "Sandbox deploy limit reached (10/hr).",
  "hint": "Create a free account for unlimited deploys: npx creek login"
}
Error codeHTTPDescription
validation400Invalid input (empty assets, bad JSON, too large)
content_policy400Content scanning blocked the deploy
rate_limited429Deploy limit reached
not_found404Sandbox not found
forbidden403Not authorized (e.g., delete by different IP)

Agent Challenge

Creek does not use CAPTCHAs. Instead, AI agents can prove they are capable callers via a "reverse CAPTCHA" — a small task that requires fetching a URL, extracting structured data, and computing a hash. Passing the challenge yields a signed agent token that grants elevated rate limits.

TierRate limit (per hour)
Unverified caller3
Human (UI / browser)10
Verified agent (via challenge)60

Protocol

  1. Start a challenge
curl -X POST https://sandbox-api.creek.dev/api/sandbox/agent-verify/start

Response:

{
  "challengeId": "a1b2c3d4e5f6",
  "nonce": "8f3e8a90-...",
  "task": {
    "url": "https://creek.dev/docs/cli",
    "instruction": "Fetch the Creek CLI documentation page. Extract all CLI command names...",
    "format": "Comma-separated, sorted alphabetically"
  },
  "expiresIn": 300,
  "tos": {
    "url": "https://creek.dev/legal/terms",
    "aupUrl": "https://creek.dev/legal/acceptable-use",
    "note": "Include tosAccepted: true and tosVersion in your submit request."
  }
}
  1. Solve the task

The agent fetches the URL, extracts data per the instruction, and computes:

digest = SHA-256(nonce + "|" + canonicalAnswer)

The canonical answer must be exactly the format requested (e.g. comma-separated, sorted alphabetically — no extra whitespace).

  1. Submit the digest
curl -X POST https://sandbox-api.creek.dev/api/sandbox/agent-verify/a1b2c3d4e5f6/submit \
  -H "Content-Type: application/json" \
  -d '{
    "digest": "<hex-encoded SHA-256>",
    "tosAccepted": true,
    "tosVersion": "v3"
  }'

Response:

{
  "ok": true,
  "token": "crk_agent_<payload>.<signature>",
  "expiresAt": "2026-04-10T12:00:00.000Z",
  "expiresIn": 3600,
  "tier": "verified_agent",
  "rateLimit": 60
}
  1. Use the token

Pass the token in the X-Creek-Agent-Token header on subsequent sandbox API calls. Verified agents get 60/hr instead of the default 10/hr.

curl -X POST https://sandbox-api.creek.dev/api/sandbox/deploy \
  -H "Content-Type: application/json" \
  -H "X-Creek-Agent-Token: crk_agent_..." \
  -d '{"assets": {...}}'

Properties

  • Tokens are bound to your IP hash — they cannot be shared.
  • One challenge = one token. Replays are rejected.
  • Token TTL: 1 hour. Re-challenge for a fresh token.
  • Questions rotate — solutions cannot be cached or hardcoded. The nonce changes every challenge.
  • TLS-grade fairness — humans pass via the dashboard sign-in flow; agents pass via this protocol. Neither needs the other.

Why a reverse CAPTCHA?

CAPTCHAs are designed to block bots. But AI agents are legitimate callers — they should not be locked out of deployment APIs just because they aren't human. The Agent Challenge inverts the problem: instead of proving you're human, you prove you can read documentation and follow instructions — exactly what an agent should be able to do.

GitHub Actions Example

- name: Deploy Preview
  run: |
    ASSETS=$(node -e "
      const fs = require('fs'), path = require('path');
      const a = {}; (function w(d,p=''){
        for(const f of fs.readdirSync(d)){
          const fp=path.join(d,f), k=p?p+'/'+f:f;
          fs.statSync(fp).isDirectory()?w(fp,k):a[k]=fs.readFileSync(fp).toString('base64');
        }
      })('dist');
      console.log(JSON.stringify(a));
    ")

    curl -sf -X POST https://sandbox-api.creek.dev/api/sandbox/deploy \
      -H "Content-Type: application/json" \
      -d "{\"assets\": $ASSETS, \"source\": \"github-actions\"}"

Or use the GitHub Action for a simpler setup.

On this page