The control-plane API is JSON over HTTP. In a production control-plane process it listens on 0.0.0.0:8787 by default; TINY_BIND_HOST and TINY_API_PORT override that. The embedded application gateway separately defaults to port 8080 (TINY_GATEWAY_PORT). Start both with pnpm api and terminate TLS at the deployment’s reverse proxy.

Conventions

Except for health/readiness/metrics, platform capabilities, and organization bootstrap, routes require Authorization: Bearer <token>. Human sessions and service-account tokens are both resolved to an organization-scoped actor.
In organization paths, the literal self refers to the token’s organization. An explicit ID from another organization returns 404 — not 403, which would confirm the ID exists.

Errors

Errors have a stable envelope:
Branch on code and retryable, never on message. See Error codes.

Body size

The API accepts bodies up to 70 MiB, leaving room for a 50 MiB artifact encoded as base64 JSON.

Meta and bootstrap

Organization bootstrap returns the organization, runtime target, a once-visible apiToken, and a human sessionToken.
GET /v1/platform/capabilities is the call to make before generating or deploying an app. It is what lets a plan refuse upfront instead of a deploy failing halfway.

Artifacts and deployments

Remote clients upload source bytes before planning or deploying. The server never accepts a caller-selected filesystem path.
Deploy returns 202 after desired state and a durable job have been stored. The background reconciler provisions resources, applies migrations, starts and health-checks the candidate, then switches traffic. Poll GET /v1/deployments/:deploymentId for the outcome.

Apps, environments, and access

Lifecycle

Restore does not deploy a worker. Deploy again to resume traffic.

Connections, capabilities, and secrets

The broker route requires an app workload token, not a human API token. It accepts an optional Tiny-User-Token and Idempotency-Key from the runtime SDK.

Data

These routes serve running applications, not operators. They authenticate with an app workload token alone — no organization is named in the path, because the token is what decides which database the caller may address. A token bound to a deployment that is no longer live is refused. Statements inside a transaction carry a Tiny-Transaction header. A transaction not committed before expiresAt is rolled back and its session released. Statement size, parameter count, result rows, and result bytes are all bounded; exceeding one returns RESOURCE_LIMIT_EXCEEDED rather than a truncated answer.

Object storage

The same rules as Data: a workload token alone, and the token decides which namespaces the caller may address. Keys travel in the query string because they contain slashes, and object bodies are raw application/octet-stream rather than base64 in JSON. An object is at most 32 MiB and a key at most 1024 bytes; exceeding either returns PAYLOAD_TOO_LARGE or VALIDATION_FAILED. Filling the namespace quota returns RESOURCE_LIMIT_EXCEEDED.
A missing object returns 404 with details.reason = "object-not-found", which is what lets a client tell an absent key apart from an unreachable namespace. Failures are always JSON, even on the routes that carry bytes.

Audit, usage, and webhooks

Verifying a webhook

Webhook URLs must be public HTTPS destinations. Deliveries include:
The HMAC-SHA256 input is <timestamp>.<raw-json-body>.
Sign against the raw body, before any JSON parse-and-restringify. Reserializing changes the bytes and the signature will not match.