Use the HTTP API¶
The HTTP API is how every client talks to a Weave platform: your application publishes workflows, starts runs, reads their progress, and answers waiting work through it. The CLI, Studio's local host, and the Python SDK use this same API, so an application written in any language can do what they do.
This page is for integration developers. In about 15 minutes you make two
read-only requests and one compile request with curl, and you learn the rules
every request follows: scope IDs, errors, revisions, and retry keys. You need:
- a running platform: one your team operates, or the local platform on your computer;
- a current access token for that platform and a person or application that holds grants in a workspace (see Get an access token);
curland Python 3 in a terminal.
Choose how to learn the API¶
| You want to… | Open | What you will get |
|---|---|---|
| Make a first request from a terminal | Make a read-only request first | Two curl requests that check your identity and project access |
| Look up one operation's exact contract | Full API reference | Every operation and schema, with a downloadable OpenAPI document |
| Send requests from your browser | API playground | Your server's Swagger UI, how to authorize it, and a compiler request |
| Call the API from Python | Python SDK tutorial | A script that publishes, activates, starts, and reads a run |
| Add workflows to your own product | Host integration | Which responsibilities belong to your application and which to Weave |
The published API reference is documentation only. The interactive
Swagger UI lives at /docs on your own platform when its operator sets
WEAVE_DOCS_ENABLED=true. Its Try it out buttons send real requests to that
platform.
Understand the three IDs in a request¶
Every workspace has three levels, and each one is a UUID in the request path:
- A tenant is an organization or team.
- A project inside it groups definitions: workflows, Actions, and Connectors.
- An environment inside the project, such as development or production, is where versions are activated and runs execute.
Display names cannot replace the UUIDs. The first request below lists the ones you can use.
| Resource | Path after the API origin | Why it lives there |
|---|---|---|
| Catalog, definitions, drafts, compiler | /api/v1/tenants/{tenant}/projects/{project} |
Definitions belong to a project and can be used in all its environments |
| Activations, connections, runs, human tasks | The project path plus /environments/{environment} |
Execution uses one environment's bindings and permissions |
| Your identity and the workspaces you can use | /api/v1/identity |
Discover your own scopes without knowing any ID in advance |
| Published sign-in settings | /api/v1/client-configuration |
Public, new in 0.1.0a7: how people sign in; weave auth setup and Studio read it |
| Health | /health/live and /health/ready |
Public: operators check that the API runs and is ready |
For example, append /catalog to the project path to read the definitions you
can use, or /runs/{run_id} to the environment path to read one run. The
full reference gives each operation's exact path, body,
headers, and required capability.
A token proves who you are; grants decide what you may do. Every request except the public ones needs a verified bearer access token from your platform's identity provider. The platform then looks up the Weave person or application linked to that sign-in and checks its current grants for the requested scope. A successful sign-in alone grants nothing. See Give people the right access and roles and lifecycle.
Get an access token¶
The CLI, Studio, and the desktop app never print the tokens they keep, so a
curl session needs a token from another source:
| Your platform | Where the token comes from |
|---|---|
| Operated by your team | Your operator's approved method, such as a CI secret or your identity provider's tooling. Follow Use a supplied access token |
| The local platform | weave platform token refreshes the local host token in the private file .local/platform/host-token.json (it prints the path, never the token) |
| A Python application | The Python SDK can reuse your saved platform's sign-in (new in 0.1.0a7) or call your own token logic; no copying needed |
Keep the values in the same terminal. The API origin has no /api/v1 suffix; on
the local platform, weave platform status shows it as Api url:
# Ask for the API origin without a path, such as https://weave.example.com.
printf 'Weave API origin: '; read -r WEAVE_BASE_URL
export WEAVE_BASE_URL
# Prompt for the token without echoing it or keeping it in shell history.
export WEAVE_ACCESS_TOKEN="$(python3 -c 'import getpass; print(getpass.getpass("Access token: "))')"
On the local platform, read the token file instead of typing the token:
# Refresh the local host token; the command prints only the file's path.
weave platform token
# Read the token from that private file without printing it.
export WEAVE_ACCESS_TOKEN="$(python3 -c 'import json; print(json.load(open(".local/platform/host-token.json"))["access_token"])')"
Expected: Token file: …/host-token.json from the first command and no output
from the second. Run both from the folder that holds .local/platform; with
weave platform --directory PATH, read PATH/host-token.json instead. Tokens
expire: when a request returns HTTP 401, get a new one the same way.
Make a read-only request first¶
Start with requests that change nothing, so that a failure can only mean an identity, scope, or network problem.
-
Ask who you are. This request needs no IDs, and its answer lists the workspaces you can use:
# Read your identity, your grants, and the tenants, projects, and environments you can use. curl --fail-with-body --silent --show-error \ "$WEAVE_BASE_URL/api/v1/identity" \ -H "Authorization: Bearer $WEAVE_ACCESS_TOKEN"Expected: HTTP 200 and a JSON object with
principal_id,kind(human,application, orworker),grants, andworkspaces. Each workspace is a tenant with itsprojects, and each project lists itsenvironments, all withidandname. HTTP 401 means the token is invalid or expired, or the platform does not know this sign-in yet; see When a request fails. -
Keep the IDs of one workspace. Copy the tenant, project, and environment
idvalues from that answer: -
Read the project catalog. Your identity needs the
catalog.readcapability in that project:# Read the definitions this project can use before changing or running anything. curl --fail-with-body --silent --show-error \ "$WEAVE_BASE_URL/api/v1/tenants/$WEAVE_TENANT_ID/projects/$WEAVE_PROJECT_ID/catalog" \ -H "Authorization: Bearer $WEAVE_ACCESS_TOKEN"Expected: HTTP 200 and the catalog as JSON with
definitions,tasks,adapters, andschemas; a new project's lists can be empty. HTTP 403 withWV-FORBIDDENmeans you are known but hold no grant for this project.
Compile a workflow without publishing it¶
Compiling checks a workflow against the project's catalog and returns the
compiled artifact. It saves nothing, publishes nothing, and starts no run. Your
identity needs the compile capability in the project.
-
Create a workflow file. Write
.local/tutorial/echo.workflow.yamlas in the quickstart's definition step, then return to the folder that contains.local. -
Wrap the YAML in a JSON request. The API takes the source as a string, so encode it rather than pasting it:
# JSON-encode the YAML so its quotes and newlines survive the HTTP request intact. python3 - <<'PYTHON' import json from pathlib import Path request = { "source": Path(".local/tutorial/echo.workflow.yaml").read_text(), "format": "yaml", "filename": "echo.workflow.yaml", "strict": True, } Path(".local/tutorial/compiler-request.json").write_text(json.dumps(request)) PYTHON -
Send it to the compiler. Leaving out
catalogmakes the server use the project's current authorized catalog:# Compile against the project's catalog; nothing is saved or executed. curl --fail-with-body --silent --show-error \ "$WEAVE_BASE_URL/api/v1/tenants/$WEAVE_TENANT_ID/projects/$WEAVE_PROJECT_ID/compiler/compile" \ -H "Authorization: Bearer $WEAVE_ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data-binary @.local/tutorial/compiler-request.jsonExpected: a compiler result with
ok: true,partial: false, and anartifact.filenameis only a label for diagnostics; the server never opens a file with that name.
HTTP success and compiler success are separate checks. A 200 response can
still carry ok: false with diagnostics: read ok and diagnostics as well as
the status.
To publish instead, send {"source": "<the YAML text>", "format": "yaml"}
to the project's /workflows collection with an Idempotency-Key header. The
SDK lifecycle example
shows how the returned version ID and digest feed activation and the first run.
When a request fails¶
Errors arrive as application/problem+json with status, a stable code, a
safe message, a request_id, and diagnostics. Quote the request_id
(also in the X-Weave-Request-ID header) when you ask an operator for help.
| What you see | Why | What to do |
|---|---|---|
HTTP 401, WV-UNAUTHENTICATED |
The token is missing, malformed, or expired, was issued for another API, or its sign-in is not linked to a Weave person or application | Get a new token. If it still fails, ask an administrator to link your identity (People and access) |
HTTP 403, WV-FORBIDDEN |
You are known but hold no current grant with the required capability in that scope | Check the IDs in the path, then ask for the role you need |
HTTP 404, WV-NOT-FOUND |
No resource with that ID exists in the scope of the path | Check every ID in the path, including the environment |
HTTP 409, WV-IDEMPOTENCY-CONFLICT |
You reused an Idempotency-Key with a different request body |
Use a new key for a new request; reuse a key only for an exact retry |
HTTP 412, WV-ETAG |
Your If-Match revision is no longer the current one |
Read the resource again, merge your change, and resend with the new revision |
HTTP 422, WV-VALIDATION, WV-IDEMPOTENCY, or WV-ETAG |
The body does not match the contract, a required Idempotency-Key is missing, or If-Match is not a positive revision |
Compare field names and types with the full reference; send the revision as "2" or 2 |
HTTP 422, WV-FILTER |
A list query combines filters that contradict each other, or has an invalid time range (empty, or longer than 400 days); the message names the rule that failed |
Change or remove the filters the message names, then send the request again |
HTTP 501, WV-UNAVAILABLE |
This server does not serve the operation yet | Use an operation this server serves, or ask your operator for a release that serves it |
| A timeout or lost connection during a change | The outcome is unknown: the change may or may not have happened | Keep the original body and key; read the resource, and retry only with the same key |
Request rules: paths, errors, revisions, and retries¶
These rules hold for every operation. Read them before you send your first change.
Paths¶
- New code uses the versioned
/api/v1/tenants/...paths. The older/tenants/...paths remain as compatibility routes to the same handlers, authorization, and data; they do not redirect. /admin/tenantsand/admin/grantskeep their own, separately authorized paths.- Health probes, signed webhooks (
POST /webhooks/{identifier}), and provider ingress (/provider-ingress/{identifier}) stay at the root. A webhook is checked against its trigger's signature over the exact timestamp and raw bytes; a bearer token never replaces that signature. - Nothing in a request can raise your authority: identity-provider roles, a catalog lock you send, or a compiled artifact grant no execution or publication right. Each operation checks your identity and scope again.
Headers and errors¶
- Canonical responses carry
X-Weave-Wire-Version: weave/api-v1andX-Weave-Request-ID, even when authentication fails early. - Errors use
application/problem+jsonwithstatus,code,message,request_id, anddiagnostics. When an operation has a safe compiler result or an "unavailable" result,resultkeeps it. - Errors never contain a framework traceback, a token, or a resolved connection credential.
- Worker credential leasing is the one deliberate secret boundary: it answers
with
Cache-Control: no-storeandPragma: no-cache, and its schema declares the secretvaluefield. See the worker protocol.
Revisions (ETags)¶
Resources that change, such as drafts, carry a revision: a positive number that grows with each change.
- Responses send it as a quoted ETag, such as
"2". - Send it back in
If-Matchto say "change this only if it is still revision 2". Both"2"and the bare2are accepted. Weak (W/"2"), wildcard, multiple, zero, signed, and zero-padded values are invalid. - A stale draft write answers HTTP 412 (
WV-ETAG). Debug sessions and incidents keep their own conflict codes. - The SDK reports the real status and code instead of converting every revision conflict to one error.
Idempotency keys¶
An idempotency key is a name you choose for one intended change, so that a
retry cannot apply it twice. These changes require an Idempotency-Key header
of 1 to 200 characters:
- publishing and retiring definitions, and creating and retiring activations;
- starting, retrying, pausing, resuming, archiving, restoring, and purging runs;
- claiming, releasing, reassigning, and completing human tasks, and saving human assignments and groups.
The full reference shows the header on every operation that accepts it. The rules for using a key:
- Sending the same key, from the same principal and scope, with the exact same body returns the result that was already committed. The same key with a different body fails with HTTP 409.
- Clients never retry a change on their own after a timeout or another
outcome they cannot know. If you retry, send the exact same body and key. The
exceptions are rejections that mean the platform did not admit the request:
HTTP 429 with
WV-OPERATION-CAPACITYorWV-REQUEST-CAPACITY, and HTTP 503 withWV-COMPATIBILITY. For these, Studio sends a read, or a change that carries a key, again with the same key, honoringRetry-After, for at most four attempts in all. Studio sends aWV-COMPATIBILITYrefusal again only when itsRetry-Afteris 5 seconds or less. - A
WV-COMPATIBILITYrefusal carriesRetry-Afterwith the whole seconds until the server's next automatic compatibility rescan. An explicit compatibility check can lift a restricted verdict sooner. - Creating a connection revision accepts an optional key since 0.1.0a7: with one, a retry returns the revision already created; without one, every request creates a new revision. Debug commands have no idempotency guarantee.
Health probes¶
GET /health/live answers {"status":"up"} while the process runs, and
GET /health/ready answers {"status":"ready"} when it can serve requests.
When the API is not ready, /health/ready answers HTTP 503 with the same safe
problem envelope as other errors, so check the HTTP status or the status
field. Failure details, database URLs, and credentials are never included, and
the request ID is generated by the server. Only these exact paths are public.
Authoring and lifecycle¶
Read down: solid arrows are your requests and dashed arrows return the IDs that the next request needs. The API checks your grant at every step; revisions protect edits, and idempotency keys make retries safe. Open diagram at full size.
Compile and validate. compiler/compile and compiler/validate accept
source, format, an optional filename, an optional canonical catalog, and
strict.
- With an explicit catalog lock, the diagnostics, source locations, source map, and artifact digest are the same as in local compilation.
- Without
catalog, compile uses the project's current authorized catalog. - Without
catalog, validate performs partial validation:partial,validationOk,ok,artifact, and the diagnostics keep their separate meanings.strict=truethen has no effect, exactly likeweave workflow validate --strictwithout a catalog: it neither promotes warnings, rejects the request, nor substitutes an empty catalog. - Partial validation does not prove a workflow can be deployed. Publication always repeats the server's authority and catalog checks.
Drafts. Saving a draft appends a new document revision.
DELETE drafts/{identifier} retires a draft; it needs definition.write, the
current grants, and the latest revision.
- The answer carries a new lifecycle revision and the retained document revision.
- A missing draft answers HTTP 404, a stale revision HTTP 412, and repeating a retirement that already happened is a conflict rather than new work.
- Reads and exports keep every revision with its retirement metadata. Lists leave retired drafts out by default, and a later save cannot bring the ID back.
Published versions and connections never change. A change publishes a new version; retiring a version keeps its history. Updating a connection creates a new connection revision with a new ID.
Triggers. Each trigger ID is one immutable configuration revision with its own signed webhook URL and receipts. Replacing a trigger creates a new ID and disables the previous route. The switch is not atomic: there can be an overlap or a gap, and one event sent to both revisions can start two runs. Coordinate the switch with the sender, or deduplicate upstream.
Installed connectors. Since 0.1.0a7,
GET …/projects/{project}/connector-descriptors lists the connectors installed
on the platform, and …/connector-descriptors/{adapter} reads one. Each
descriptor holds the exact Connector manifest to publish (source), its
capabilities, bindings, Actions, and connection settings, plus
published_version_id once it is published in the project. Both need
catalog.read. weave connector descriptor ADAPTER prints the same view.
Discovery, debugging, and history¶
Lists. Canonical lists return { "items": [...], "next_cursor": null | "opaque" }.
limitis 1 to 100 (50 by default), and items come in stable ID order.- Pass
next_cursorback ascursorfor the next page. A cursor is bound to its tenant, project, environment, collection, and any run or schedule filter; a cursor from another scope or filter is rejected. - A cursor describes a position, not a snapshot: items created or retired meanwhile can change later pages.
- Compatibility endpoints that return plain arrays keep that shape.
Who may list what. Listing a whole collection needs the scope-wide
capability: connections connection.manage, runs and schedules run.read,
workers status.read, releases and the catalog catalog.read, triggers
trigger.manage, incidents incident.read. Grants are reloaded in the same
transaction. A resource whose classification cannot be checked appears as an
explicit safe placeholder; a list never widens access.
Debug sessions belong to a project and to the person who created them.
They expire in real time, use revisions, run Actions only against mocks, and
support breakpoints and virtual time. The response is a DebugSession envelope
that contains a view. Source-map file names are labels only. No connector or
secret provider runs during a simulation.
History and replay. Run history pages use a bounded high-water cursor and
keep the pinned source, receipt, and version facts, with explicit omissions.
Replay reports consistent, inconsistent, or incomplete: a history prefix,
or a history with unavailable or redacted parts, is never reported as success.
See history and replay.
Run summaries, steps, and logs. run_summaries.list, runs.steps, and
runs.logs are published so that clients can build against them. Until this
server serves them, an authorized request answers 501 with WV-UNAVAILABLE.
- These lists are ordered by time, not by ID: run summaries by start time (newest first by default) or by last update, steps by scheduled time, and log entries by time.
runs.stepsandruns.logsaccept alimitof 1 to 500 (200 by default).- Each cursor is bound to every filter and to the order. After you change a filter, start again from the first page.
- Test runs are left out unless you send
include_test=true, and archived runs unless you sendinclude_archived=true. - A contradictory filter, such as
versionwithoutworkflow, answers422withWV-FILTER; the message names the rule that failed. - Send times as RFC 3339 with an offset. Use
Z, or encode+as%2Bin the query string.
Answers that say "unavailable". Cancellation and task completion can return
an unavailable acknowledgment when the platform cannot classify the historical
data or compare payloads; task completion then includes
payload_match: unavailable.
Large runs. Cancelling a supported historical run whose state is larger than
the current processing budget can return CapacityRunAcknowledgment instead of
a full RunView. It holds id, the terminal status, accepted_sequence,
capacity_limited: true, an explicit omission of /state with reason
resource_limit, and external_effects_may_continue. The cancellation and its
complete history are committed; only the large state is left out of the
answer. Handle both shapes. Cancellation stops further orchestration, but it
cannot undo an external call that is already in progress.
Operation inventory¶
The table lists every operation with its canonical path and the capability it
requires. "Public probe" marks the endpoints that need no token. The contract
test in tests/contracts/test_api_documentation.py checks every row against the
platform's operation registry, so the table matches the code. GET routes also
answer HEAD, without a body. For request and response schemas, open the
operation in the full API reference; to generate a client,
export the OpenAPI document.
| Operation | Method and canonical path | Required authority |
|---|---|---|
human_files.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/files/create |
human_task.complete |
human_files.chunk |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/files/chunk |
human_task.complete |
human_files.finish |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/files/finish |
human_task.complete |
human_files.read |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/files/read |
human_task.read |
human_files.download |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/files/download |
human_task.read |
files.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/files |
file.manage |
files.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/files |
file.read |
files.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/files/{identifier} |
file.read |
files.chunk |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/files/{identifier}/chunks |
file.manage |
files.finish |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/files/{identifier}/finish |
file.manage |
files.download |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/files/{identifier}/download |
file.read |
files.delete |
DELETE /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/files/{identifier} |
file.manage |
task_files.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/files/create |
task.claim |
task_files.chunk |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/files/chunk |
task.claim |
task_files.finish |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/files/finish |
task.claim |
task_files.read |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/files/read |
task.claim |
task_files.download |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/files/download |
task.claim |
lumi.configuration.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/lumi/configuration |
lumi.manage |
lumi.configuration.write |
PUT /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/lumi/configuration |
lumi.manage |
lumi.status |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/lumi/status |
lumi.use |
lumi.ask |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/lumi/ask |
lumi.use |
compatibility.read |
GET /api/v1/tenants/{tenant}/projects/{project}/operations/compatibility |
status.read |
compatibility.check |
POST /api/v1/tenants/{tenant}/projects/{project}/operations/compatibility/check |
compatibility.check |
retention.plan |
POST /api/v1/tenants/{tenant}/projects/{project}/operations/retention/plans |
retention.plan |
retention.read |
GET /api/v1/tenants/{tenant}/projects/{project}/operations/retention/plans/{identifier} |
retention.plan |
retention.apply |
POST /api/v1/tenants/{tenant}/projects/{project}/operations/retention/plans/{identifier}/apply |
retention.apply |
teams_references.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/teams-references/{identifier} |
trigger.manage |
teams_references.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/teams-references |
trigger.manage |
teams_references.revoke |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/teams-references/{identifier}/revoke |
trigger.manage + connection.manage + connection.bind |
teams_references.reactivate |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/teams-references/{identifier}/reactivate |
trigger.manage + connection.manage + connection.bind |
whatsapp_statuses.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-sources/{identifier}/whatsapp-statuses |
run.read |
whatsapp_statuses.facts |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-sources/{identifier}/whatsapp-statuses/{state_id}/facts |
run.read |
provider_sources.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-sources |
trigger.manage + connection.manage + connection.bind + target authority |
provider_sources.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-sources/{identifier} |
run.read |
provider_sources.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-sources |
run.read |
provider_sources.disable |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-sources/{identifier}/disable |
trigger.manage + connection.bind + target authority |
provider_receipts.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-receipts/{identifier} |
run.read |
provider_receipts.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-receipts |
run.read |
provider_receipts.retry |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/provider-receipts/{identifier}/retry |
run.retry + current source/target authority |
provider_ingress.receive |
POST /provider-ingress/{identifier} |
provider verification |
provider_ingress.challenge |
GET /provider-ingress/{identifier} |
provider challenge verification |
human_tasks.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks |
human_task.read |
human_tasks.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier} |
human_task.read |
human_tasks.claim |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/claim |
human_task.claim |
human_tasks.release |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/release |
human_task.release |
human_tasks.reassign |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/reassign |
human_task.manage |
human_tasks.complete |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-tasks/{identifier}/complete |
human_task.complete |
human_assignments.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-assignments |
assignment.read |
human_assignments.put |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-assignments |
assignment.manage |
human_groups.put |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/human-groups |
assignment.manage |
runs.lifecycle |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/lifecycle |
run.read |
runs.archive |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/archive |
run.archive |
runs.restore |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/restore |
run.archive |
runs.purge |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/purge |
run.purge |
runs.pause |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/pause |
run.pause |
runs.resume |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/resume |
run.resume |
email_conversations.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/conversations |
email.read |
email_conversations.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/conversations/{identifier} |
email.read |
email_submissions.send |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/submissions |
email.send |
email_submissions.reply |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/conversations/{identifier}/reply |
email.send |
email_submissions.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/submissions/{identifier} |
email.read |
email_submissions.execute |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/submissions/{identifier}/execute |
email.send |
email_receipts.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/receipts |
email.read |
email_sources.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/sources |
email.manage |
email_sources.poll |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/sources/{identifier}/poll |
email.manage |
email_sources.rebaseline |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/sources/{identifier}/rebaseline |
email.manage |
email_receipts.correlate |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/receipts/{identifier}/correlate |
email.manage |
email_receipts.dispatch |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/receipts/{identifier}/dispatch |
email.manage |
email_tokens.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/correlation-tokens |
email.manage |
email_tokens.revoke |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/email/correlation-tokens/{identifier}/revoke |
email.manage |
principals.list |
GET /api/v1/admin/principals |
grant.admin |
principals.create |
POST /api/v1/admin/principals |
grant.admin |
principals.link |
POST /api/v1/admin/principals/{identifier}/identity-links |
grant.admin |
principals.status |
POST /api/v1/admin/principals/{identifier}/status |
grant.admin |
members.list |
GET /api/v1/tenants/{tenant}/members |
grant.manage or grant.admin |
members.grant |
POST /api/v1/tenants/{tenant}/members |
grant.manage or grant.admin |
members.revoke |
POST /api/v1/tenants/{tenant}/members/{identifier}/revoke |
grant.manage or grant.admin |
identity.read |
GET /api/v1/identity |
authenticated identity |
client_configuration.read |
GET /api/v1/client-configuration |
Public probe |
health.live |
GET /health/live |
Public probe |
health.ready |
GET /health/ready |
Public probe |
admin.tenant |
POST /admin/tenants |
tenant.create |
admin.grant |
POST /admin/grants |
grant.admin or grant.manage |
projects.create |
POST /api/v1/tenants/{tenant}/projects |
project.manage |
environments.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments |
environment.manage |
environments.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment} |
status.read |
compiler.compile |
POST /api/v1/tenants/{tenant}/projects/{project}/compiler/compile |
compile |
compiler.validate |
POST /api/v1/tenants/{tenant}/projects/{project}/compiler/validate |
compile |
compiler.evaluate_decision |
POST /api/v1/tenants/{tenant}/projects/{project}/compiler/evaluate-decision |
compile |
catalog.read |
GET /api/v1/tenants/{tenant}/projects/{project}/catalog |
catalog.read |
capabilities.read |
GET /api/v1/tenants/{tenant}/projects/{project}/capabilities |
catalog.read |
language.read |
GET /api/v1/tenants/{tenant}/projects/{project}/language |
catalog.read |
schemas.read |
GET /api/v1/tenants/{tenant}/projects/{project}/schemas |
catalog.read |
connector_descriptors.list |
GET /api/v1/tenants/{tenant}/projects/{project}/connector-descriptors |
catalog.read |
connector_descriptors.read |
GET /api/v1/tenants/{tenant}/projects/{project}/connector-descriptors/{adapter} |
catalog.read |
definitions.publish |
POST /api/v1/tenants/{tenant}/projects/{project}/{collection} |
definition.publish |
definitions.list |
GET /api/v1/tenants/{tenant}/projects/{project}/{collection} |
catalog.read |
definitions.read |
GET /api/v1/tenants/{tenant}/projects/{project}/{collection}/{identifier} |
catalog.read |
definitions.export |
GET /api/v1/tenants/{tenant}/projects/{project}/{collection}/{identifier}/export |
catalog.read |
definitions.retire |
POST /api/v1/tenants/{tenant}/projects/{project}/{collection}/{identifier}/retire |
release.retire |
drafts.save |
PUT /api/v1/tenants/{tenant}/projects/{project}/drafts/{identifier} |
definition.write |
drafts.retire |
DELETE /api/v1/tenants/{tenant}/projects/{project}/drafts/{identifier} |
definition.write |
activations.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/activations |
release.activate |
activations.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/activations |
catalog.read |
activations.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/activations/{identifier} |
catalog.read |
activations.export |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/activations/{identifier}/export |
catalog.read |
activations.retire |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/activations/{identifier}/retire |
release.retire |
connections.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/connections |
connection.manage |
connections.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/connections |
connection.manage |
connections.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/connections/{identifier} |
connection.manage |
connections.test |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/connections/{identifier}/test |
connection.manage |
runs.start |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs |
run.start |
runs.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs |
run.read |
runs.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier} |
run.read |
runs.signal |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/signals |
run.signal |
runs.cancel |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/cancel |
run.cancel |
runs.retry |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/retry |
run.retry |
runs.history |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/history |
run.read |
runs.export |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/export |
run.read |
runs.replay |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/replay |
run.read |
run_summaries.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/run-summaries |
run.read |
runs.steps |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/steps |
run.read |
runs.logs |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/logs |
run.read |
incidents.run_list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/runs/{identifier}/incidents |
incident.read |
incidents.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/incidents |
incident.read |
incidents.resolve |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/incidents/{identifier}/resolve |
incident.resolve |
releases.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/worker-releases |
release.activate |
releases.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/worker-releases |
catalog.read |
releases.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/worker-releases/{identifier} |
catalog.read |
workers.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/workers |
worker.register |
workers.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/workers |
status.read |
workers.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/workers/{identifier} |
status.read |
workers.revoke |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/workers/{identifier}/revoke |
release.retire |
workers.grant |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/worker-connection-grants |
connection.manage |
tasks.claim |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/claim |
task.claim |
tasks.context |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/context |
task.claim |
tasks.heartbeat |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/heartbeat |
task.heartbeat |
tasks.complete |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/complete |
task.complete |
tasks.fail |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/fail |
task.complete |
tasks.credentials |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/tasks/credentials |
credential.lease |
subscriptions.save |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/subscriptions |
subscription.manage and connection.manage and connection.bind and source authority |
subscriptions.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/subscriptions |
delivery.read |
subscriptions.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/subscriptions/{identifier} |
delivery.read |
subscriptions.disable |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/subscriptions/{identifier}/disable |
subscription.manage and source authority |
deliveries.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deliveries |
delivery.read |
deliveries.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deliveries/{identifier} |
delivery.read |
deliveries.retry |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deliveries/{identifier}/retry |
delivery.retry and current source authority |
deliveries.history |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deliveries/{identifier}/attempts |
delivery.read |
source_bindings.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/connection-source-bindings |
connection.manage |
source_bindings.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/connection-source-bindings/{identifier} |
connection.manage |
source_bindings.revoke |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/connection-source-bindings/{identifier}/revoke |
connection.manage |
broker_triggers.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/broker-triggers |
trigger.manage and connection.manage and connection.bind and target authority |
broker_triggers.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/broker-triggers |
trigger.manage |
broker_triggers.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/broker-triggers/{identifier} |
trigger.manage |
broker_triggers.disable |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/broker-triggers/{identifier}/disable |
trigger.manage |
broker_triggers.retry |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/broker-triggers/{identifier}/retry |
trigger.manage and current source authority |
broker_triggers.incidents |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/broker-incidents |
trigger.manage |
triggers.create |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/triggers |
trigger.manage |
triggers.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/triggers |
trigger.manage |
triggers.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/triggers/{identifier} |
trigger.manage |
triggers.disable |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/triggers/{identifier}/disable |
trigger.manage |
webhooks.receive |
POST /webhooks/{identifier} |
signed webhook and pinned principal authority |
schedules.save |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/schedules |
trigger.manage and run.start |
schedules.list |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/schedules |
run.read |
schedules.read |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/schedules/{identifier} |
run.read |
schedules.history |
GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/schedules/{identifier}/occurrences |
run.read |
schedules.enable |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/schedules/{identifier}/enable |
trigger.manage |
schedules.disable |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/schedules/{identifier}/disable |
trigger.manage |
schedules.delete |
POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/schedules/{identifier}/delete |
trigger.manage |
debug.create |
POST /api/v1/tenants/{tenant}/projects/{project}/debug/sessions |
simulate |
debug.read |
GET /api/v1/tenants/{tenant}/projects/{project}/debug/sessions/{identifier} |
simulate |
debug.command |
POST /api/v1/tenants/{tenant}/projects/{project}/debug/sessions/{identifier}/commands |
simulate |
| deployment_plans.approval | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-plans/{identifier}/approval | deployment.read |
| deployment_jobs.reconcile | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-jobs/{identifier}/reconcile | deployment.apply and deployment.approve |
| deployment_targets.list | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-targets | deployment.read |
| deployment_targets.read | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-targets/{identifier} | deployment.read |
| deployments.list | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployments | deployment.read |
| deployments.read | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployments/{identifier} | deployment.read |
| deployment_observations.list | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-observations | deployment.read |
| deployment_observations.read | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-observations/{identifier} | deployment.read |
| deployment_plans.list | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-plans | deployment.read |
| deployment_plans.read | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-plans/{identifier} | deployment.read |
| deployment_jobs.list | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-jobs | deployment.read |
| deployment_jobs.read | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-jobs/{identifier} | deployment.read |
| deployment_runners.list | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-runners | deployment.read |
| deployment_runners.read | GET /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-runners/{identifier} | deployment.read |
| deployment_targets.create | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-targets | target.manage |
| deployments.create | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployments | target.manage |
| deployment_observations.create | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-observations | deployment.plan |
| deployment_plans.create | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-plans | deployment.plan |
| deployment_targets.update | PUT /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-targets/{identifier} | target.manage |
| deployments.update | PUT /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployments/{identifier} | target.manage |
| deployment_plans.approve | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-plans/{identifier}/approve | deployment.approve |
| deployment_plans.apply | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-plans/{identifier}/apply | deployment.apply |
| deployment_jobs.cancel | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-jobs/{identifier}/cancel | deployment.cancel |
| deployment_runners.create | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-runners | runner.register |
| deployment_runners.claim | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-runners/claim | runner.claim |
| deployment_runners.renew | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-runners/renew | runner.renew |
| deployment_runners.report | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-runners/report | runner.report |
| deployment_runners.revoke | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/deployment-runners/{identifier}/revoke | target.manage |
| workers.drain | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/workers/{identifier}/drain | worker.drain |
| workers.resume | POST /api/v1/tenants/{tenant}/projects/{project}/environments/{environment}/workers/{identifier}/resume | worker.drain |
Deployment Operations authority¶
Follow Manage container deployments for the complete Studio and CLI sequence.
Deployment targets, desired deployments, observations, plans, approvals, jobs,
and runner registrations belong to one environment. Child-resource reads check
the target grant. Lists filter authorized target IDs before pagination; use
target_id to select a target, and deployment_id to narrow plan history.
An observation is a dated snapshot, not a promise of current health.
The server creates an immutable plan from the desired revision and a fresh,
complete observation. Approval records its exact digest. Applying checks the
current target and desired revisions, freshness, and the approver's current
authority again. deployment_plans.approval returns the recorded approval or
null; a recorded approval does not bypass those final checks.
| Role | Responsibility |
|---|---|
deployment_reader |
Read authorized target inventory and evidence |
deployment_planner |
Register target metadata, edit desired deployment, observe, and plan |
deployment_approver |
Approve the exact immutable plan |
deployment_operator |
Apply or cancel work |
deployment_runner |
Dedicated application's registration, claims, renewals, and reports |
worker_operator |
Drain or resume a specific worker instance |
Provider credentials and configuration templates stay on the outbound runner. The API accepts typed intent, immutable image digests, and local configuration aliases; it does not accept commands or cloud credentials. API/scheduler components require exactly one instance. Worker components require an admitted release. Available actions are bounded by both the registered target and the runner's local adapter policy.
Only one job may be active per target. Losing authority after external changes begin requires reconciliation, never automatic re-execution. An operator with both apply and approve capabilities must acknowledge that the external operation stopped and select a new complete, settled observation to close the ambiguous job. Closing it does not reverse changes or apply another plan. Worker drain prevents new claims and lets existing leases settle; scaling a provider replica count to zero is a different operation.
Compatibility and retention authority¶
Compatibility. A project viewer with status.read can read the project's
compatibility report; starting a fresh check needs compatibility.check.
Reports leave out other projects' findings, and both operations reload your
current grants.
Retention. A retention plan is an immutable set of items chosen by the server.
- Only the plan's creator, with the matching current project capability, can read or apply it. An environment-only or resource-limited grant is not enough.
- Another person's plan answers exactly like an unknown plan (not found).
- Applying a plan checks authorization and eligibility again; a client cannot replace the items in it.
The CLI retention commands show the complete plan-then-apply sequence.
Next steps¶
- Look up any operation's full contract in the full API reference.
- Publish, activate, and start a run from Python with the SDK tutorial and the SDK reference.
- Run the same requests from a terminal with the CLI, which signs in for you and remembers your workspace.
- Generate a client in another language from the native OpenAPI export.