Management API
The Flow Management API exposes projects, enabled chains, immutable function releases, executables, execution history and logs, profiles, executable storage, project secrets, and executable webhooks.
Use the HTTP API base URL for the deployment you intend to manage. Development and production have separate resources and credentials. Examples use:
export THYME_API_URL='https://YOUR_FLOW_API_HOST/http'Replace this placeholder with the supplied API base, including any deployment path prefix. A Console website URL is not necessarily its HTTP API base. The CLI's packaged default is documented under API URL configuration; select the development URL explicitly when working with the development rollout.
All versioned routes start with /api/v1. Function bundle upload currently uses
POST /api/task/upload because it accepts multipart form data.
Authentication
Create a workspace-bound management credential through the CLI:
thyme login --managementThe browser consent screen requires an owner or admin to select one workspace. The resulting token cannot access a different workspace. Send it as a bearer token:
curl "$THYME_API_URL/api/v1/projects" \
-H "Authorization: Bearer $THYME_AUTH_TOKEN"Legacy unbound keys must also send X-Workspace-Id. When both the header and a
workspaceId query parameter are present, they must match. A bound key rejects
either value when it names another workspace.
Scopes
Every route checks one narrow scope. Management consent grants the complete Flow management bundle:
| Resource | Read | Write or privileged action |
|---|---|---|
| Projects | projects:read | projects:write |
| Chains | chains:read | — |
| Functions | functions:read | functions:upload, functions:delete, functions:source |
| Executables | executables:read | executables:write, executables:run |
| Executions | executions:read | — |
| Storage | storage:read | storage:write |
| Profiles | profiles:read | profiles:write |
| Secrets | secrets:read | secrets:write |
| Webhooks | webhooks:read | webhooks:write |
| Usage | usage:read | — |
Management access intentionally does not cover project deletion, private-key import, billing, workspace/member administration, or API-key administration. Read operations require active workspace membership and the corresponding scope. Mutations additionally require an owner or admin role. Losing membership or revoking the key removes access even when the client still has a stored token.
The profile creation route is the legacy account creation path. It does not replace the owner wallet signatures used to onboard a Safe or Roles profile in the Console. Legacy creation can be disabled by the deployment.
Idempotency and request IDs
Send Idempotency-Key on a mutating request to make its response replayable for
24 hours. Use a unique key for each intended operation and target resource. Reusing
the key for the same method, route template, credential, workspace, and canonical
JSON body returns the original status and body with
Idempotency-Replayed: true. Reusing it with a different request returns
409 idempotency_conflict when the recorded request fingerprint differs.
The current fingerprint uses the route template, and some actions do not
include the resource ID in their body. Reusing a key across two resource IDs can
therefore replay the first response. Include the target ID in your key, for
example pause-EXECUTABLE_ID-CHANGE_ID, even when the request body is identical.
The CLI generates a key automatically for mutations and retries a network failure once with that same key. For a manual retry, provide your own stable key:
curl -X POST "$THYME_API_URL/api/v1/projects" \
-H "Authorization: Bearer $THYME_AUTH_TOKEN" \
-H "Idempotency-Key: project-acme-production" \
-H "Content-Type: application/json" \
--data '{"name":"Acme","slug":"acme","environment":"production"}'Every management response includes an X-Request-Id header. Include it when
reporting an API failure. Errors use a stable shape:
{
"error": "Pause the executable before changing its function",
"code": "executable_must_be_paused",
"requestId": "3e6d..."
}Unknown server failures are deliberately opaque; provider messages, stack frames, and configuration values are not returned.
The multipart upload endpoint uses release name, version tag, and archive checksum for deduplication; it does not use the management mutation replay mechanism. See uploading a function.
See Errors & Retries for in-progress requests, permission refusals, and recovery steps. Save both the idempotency key and request ID with your automation logs; never log the bearer token.
Pagination
Collection routes that may grow large accept limit (default 50, maximum 200)
and cursor. The response is:
{
"data": [],
"pagination": {
"cursor": "opaque-convex-cursor",
"isDone": false
}
}Pass the returned cursor unchanged on the next request.
Stop when isDone is true. Projects, chains, secrets, and executable webhook
lists return { "data": [...] } without a pagination object. Execution lists
at /api/v1/executions also accept a status filter.
Function releases
A function is an immutable release identified by (projectId, name, versionTag). A new name defaults to v1; another upload or copy into that name
must supply a tag. Tags are lowercase, 1–32 characters, match
^[a-z0-9][a-z0-9._-]{0,31}$, and latest is reserved. A deleted tag remains
reserved.
Repeating the same active name, tag, and checksum returns the existing function.
The same tag with different code returns version_tag_conflict, together with
reservedVersionTags and suggestedVersionTag.
Changing an executable's function is not an in-place code edit. Pause the
executable, then call its function patch route with the target function ID.
The API returns 202 with a switch request ID and rebuilding state. A new
sandbox is built asynchronously and committed atomically; the previous function
and sandbox remain live if the build fails.
Storage and secrets
Executable storage is stored directly in Convex file storage; R2 or another
external object store is not required. The runtime storage ceiling is 100 MiB,
but this JSON HTTP endpoint accepts and returns at most 16 MiB so its envelope
stays below Convex's 20 MiB HTTP-action boundary. Writes require
expectedVersion, providing optimistic concurrency and protecting state while
an execution holds the storage lock.
Project secret values are write-only. Create and rotate operations send a value, but list and mutation responses return metadata only. Values are never returned through the management API.
Permissions and execution environments
An uploaded permissions.json is part of the checksummed archive. Creating an
executable, switching its function/profile, changing args, and resuming can reject
a release whose permissions are not covered by its profile. A binding refusal
returns 409 permissions_not_covered, with diagnostic fields
described in Errors & Retries. Edit the task's manifest and upload
a new release or extend the on-chain role through its owner; an API key cannot
grant wallet permissions.
Real execution checks permissions again asynchronously. An accepted /run
request can later fail that check; read the execution and logs for its outcome.
API clients must supply valid JSON-encoded args matching the function schema;
the management API does not run all of the Console's args validation before
storing an update. The task runtime validates args when it runs.
sandboxRuntime selects daytona or gvisor when creating an executable. The
default is daytona. The deployment must have the selected runtime available.
The sandbox runs task code; the profile separately controls on-chain execution.
See runtime limits and profiles.
See Resources for routes and examples, browse the interactive reference, or download the OpenAPI 3.1 document.