API Reference.
Build OctopusLab into your own tooling — the same API our dashboard uses. REST over HTTPS, JSON payloads, bearer-token auth. Stable since v1.
Base URL & authentication
All requests hit a single global endpoint. Per-region routing (US-East, EU-West, AP-Southeast) ships with v1.1 — your bearer token will work unchanged.
https://api.octopus-lab.app/api/v1Pass an API key as a Bearer token on every request. Keys are scoped to one org and inherit your member role. Manage them in /app/settings → API Keys.
curl https://api.octopus-lab.app/api/v1/projects \
-H "Authorization: Bearer ok_live_3f8c2a1e9b7d4f6e8a2c5b1d3e9f7a4c" \
-H "Content-Type: application/json"ok_live_ for production, ok_test_ for the sandbox env.Resource map
Create, list, get, and delete projects scoped to an org.
GET /projects?orgId=org_1aB2cTrigger a deploy, list history, poll status for a build.
POST /projects/{id}/deploymentsGenerate HTML mockups from a prompt, refine, convert to a project, share.
POST /designsAttach a custom domain to a project and check verification state.
POST /projects/{id}/domainsRead, write, and list files inside a project sandbox.
GET /projects/{id}/files?path=app/page.tsxRun SEO / AEO audits against a deployment, fetch the latest run.
POST /projects/{id}/auditsList members, send invites, update roles, remove seats.
GET /orgs/{id}/membersCreate, list, and revoke keys. New secrets are returned once.
POST /api-keysprj_, dpl_, org_). Timestamps are ISO-8601 UTC. Cursor-based pagination via ?cursor=&limit=. Idempotency through Idempotency-Key.Rate limits & errors
Rate limit: 60 req/min per API key by default, burstable to 120 for short windows. 429 is returned with a Retry-After header in seconds. Higher limits ship per plan and on request. Errors follow RFC 7807 problem-detail JSON with a stable code field — match on that, not the human title.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/problem+json
{
"type": "https://docs.octopus-lab.app/errors/rate-limited",
"title": "Rate limit exceeded",
"status": 429,
"code": "rate_limited",
"detail": "60 requests/minute per API key. Retry after 12s.",
"instance": "/api/v1/projects",
"requestId": "req_01HX9V7M3K2QPYF4N8DB6ZTRWE"
}unauthenticated— missing or malformed bearer token.forbidden— token valid, role lacks permission.not_found— resource gone or scoped to another org.conflict— idempotency clash or stale write.validation_failed— schema check; seeerrors[]in body.rate_limited— back off per Retry-After.internal— open a ticket withrequestId.
Webhooks
Webhooks fire on deployment success / failure, payment confirmation, and audit completion. Configure endpoints at /app/integrations. Each delivery is signed with HMAC-SHA256 over {timestamp}.{rawBody} and sent in the X-Octopuslab-Signature header. Reject anything with a timestamp older than 5 minutes.
POST /your-endpoint HTTP/1.1
Host: example.com
Content-Type: application/json
X-Octopuslab-Event: deployment.succeeded
X-Octopuslab-Delivery: dlv_01HX9V7M3K2QPYF4N8DB6ZTRWE
X-Octopuslab-Timestamp: 1733654400
X-Octopuslab-Signature: t=1733654400,v1=5b2c8d4e9f1a3c7b6d8e2f4a9c1b3d5e7f8a0c2b4d6e8f0a1c3b5d7e9f1a3c5b
{
"id": "evt_01HX9V7M3K2QPYF4N8DB6ZTRWE",
"type": "deployment.succeeded",
"createdAt": "2026-06-08T12:00:00.000Z",
"data": {
"projectId": "prj_aurora",
"deploymentId": "dpl_8c2a1e9b7d4f",
"url": "https://aurora.octopus-lab.app",
"commitSha": "9f4b2c1",
"durationMs": 18420
}
}import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(
header.split(',').map((p) => p.split('=') as [string, string]),
);
const expected = createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1);
return a.length === b.length && timingSafeEqual(a, b);
}