Skip to content

Direct Static API Reference

The CLI coordinates this protocol. This reference exists to define the customer-visible boundary, not to encourage a second client implementation.

Use only the explicit HTTPS API endpoint supplied for the operator authorization. Every customer request carries:

Authorization: Bearer <CUSTOMER_TOKEN>

Dashboard OIDC credentials and minted customer tokens use the authenticated customer boundary. A revoked token is rejected.

JSON mutation requests accept exactly one valid UTF-8 JSON value, reject unknown fields, and reject trailing values.

The 16 KiB app-create JSON body cap applies to POST /v1/apps. The 4 KiB customer-token and deploy-session mutation body cap applies to token mint plus deploy heartbeat, finalize, and abort requests. The 128 KiB manifest/admission body cap applies to deploy lock requests.

The direct-upload file, aggregate, path, content-type, session, attempt, and rate boundaries are listed in Invite-Beta Limits.

MethodRoutePurpose
POST/v1/appsCreate one static app.
GET/v1/appsList customer-owned apps.
GET/v1/apps/{name}Read one customer-owned app.
DELETE/v1/apps/{name}Delete one customer-owned app.
GET/v1/me/tokensList token metadata without plaintext secrets.
POST/v1/me/tokensMint a customer token; plaintext is returned once.
DELETE/v1/me/tokens/{id}Revoke a customer token.
POST/v1/apps/{name}/deploy/lockAdmit one exact session and complete manifest.
PUT/v1/apps/{name}/deploy/lockHeartbeat the exact admitted session.
PUT/v1/apps/{name}/files/{canonical-path}Upload exact bytes for one admitted entry.
POST/v1/apps/{name}/deploy/finalizeFinalize the exact session.
POST/v1/apps/{name}/deploy/abortAbort the exact session with bounded cleanup.

There are no raw file-list/delete and no domain mutation routes in the beta. Repository build, connect, webhook, rollback, and container routes are server-side closed.

POST /v1/apps
Authorization: Bearer <CUSTOMER_TOKEN>
Content-Type: application/json
{"name":"my-site"}

The request is static-only. The response’s URL and platform hostname are the generated-hostname source of truth.

OIDC-authenticated dashboard requests can mint a token with a human-readable label:

POST /v1/me/tokens
Authorization: Bearer <OIDC_ACCESS_TOKEN>
Content-Type: application/json
{"name":"walkthrough-cli"}

The mint response is the only plaintext-secret view. Revoke by token ID through the authenticated customer route, then prove a request carrying that revoked token is rejected.

Generate one canonical UUID for the session. Send every intended file with its canonical relative POSIX path, exact byte size, lowercase 64-hex sha256, and admitted content_type:

POST /v1/apps/{name}/deploy/lock
Authorization: Bearer <CUSTOMER_TOKEN>
Content-Type: application/json
{
"deploy_session_id": "550e8400-e29b-41d4-a716-446655440000",
"manifest": [
{
"path": "index.html",
"size": 31,
"sha256": "<LOWERCASE_SHA256>",
"content_type": "text/html; charset=utf-8"
}
]
}

The manifest is the complete desired set, not a changed-file list. Admission binds the session to the authenticated customer, app incarnation, validated client IP, and canonical manifest digest.

The URL path is the canonical manifest path. The session header, explicit content length, and content type must exactly match admission; the request body must contain the exact admitted bytes and no content encoding:

PUT /v1/apps/{name}/files/{canonical-path}
Authorization: Bearer <CUSTOMER_TOKEN>
X-Zerokie-Deploy-Session: 550e8400-e29b-41d4-a716-446655440000
Content-Length: <EXACT_BYTE_COUNT>
Content-Type: <ADMITTED_CONTENT_TYPE>
<EXACT_BYTES>

Each provider upload, stale-path delete, cleanup action, and cache purge has at most the documented provider-attempt budget.

PUT /v1/apps/{name}/deploy/lock
Authorization: Bearer <CUSTOMER_TOKEN>
Content-Type: application/json
{"deploy_session_id":"550e8400-e29b-41d4-a716-446655440000"}

The body contains the exact session and no other field.

Finalize only after every manifest entry has uploaded:

POST /v1/apps/{name}/deploy/finalize
Authorization: Bearer <CUSTOMER_TOKEN>
Content-Type: application/json
{"deploy_session_id":"550e8400-e29b-41d4-a716-446655440000"}

Abort the same session after an interrupted or failed client operation:

POST /v1/apps/{name}/deploy/abort
Authorization: Bearer <CUSTOMER_TOKEN>
Content-Type: application/json
{"deploy_session_id":"550e8400-e29b-41d4-a716-446655440000"}

Both bodies contain only the exact session. There are no caller-supplied final file or byte totals; the server derives the receipt from admitted state.

Errors use a structured body with a stable code and message:

{"error":{"code":"rate_limited","message":"Too many requests. Try again later."}}

Customer-relevant stable codes include:

  • app_capacity_reached when the operator-authorization grant’s app-create capacity is exhausted;
  • app_changes_suspended when app creation or deploy admission is suspended for that grant;
  • rate_limited for an exhausted customer or validated-client-IP admission bucket;
  • manifest_conflict for a changed manifest replay;
  • deploy_session_mismatch for a session identity mismatch;
  • deploy_session_inactive for an inactive or expired session;
  • deploy_session_active when a session blocks app deletion;
  • deploy_incomplete when finalization precedes complete upload;
  • attempt_exhausted when the provider attempt budget is spent; and
  • cleanup_failed when bounded cleanup cannot complete.

Provider-visible static content may be non-atomically changed by a failed overwrite. cleanup_failed means stop and contact the operator. It does not authorize a private rescue route, provider action, or undocumented workaround.