Operations
Routes, scopes, idempotency requirements, and purposes for all 18 HTTP API operations.
Call every operation with POST /api/v1/<operation> and a JSON object body. The operation name in the tables is the exact suffix after /api/v1/.
Test Cases
| Operation | Scope | Idempotency | Purpose |
|---|---|---|---|
test_case.list | autonomy:read | None | List Test Cases in the organization, newest first. Filter by platform or a name query. Use before creating a case so existing coverage is reused. |
test_case.get | autonomy:read | None | Fetch one Test Case with its full step list. |
test_case.create | autonomy:test_cases:write | Required | Create a Test Case from explicit steps. Fill values are literal, agent (Agent-chosen at run time), or environment (named Environment runtime value); credential-shaped literals are rejected unless explicitly relocated to an Environment secret. |
test_case.update_steps | autonomy:test_cases:write | Required | Replace a Test Case's whole step list. Requires confirm: true; without it the response describes what would change and nothing is written. |
Test Plans
| Operation | Scope | Idempotency | Purpose |
|---|---|---|---|
test_plan.list | autonomy:read | None | List Test Plans (named selections of Test Cases) in the organization. |
test_plan.get | autonomy:read | None | Fetch one Test Plan with its ordered member Test Cases. |
test_plan.create | autonomy:test_plans:write | Required | Create a Test Plan and optionally its initial ordered member Test Cases. |
test_plan.set_members | autonomy:test_plans:write | Required | Replace a Test Plan's ordered membership. Removing cases requires confirm: true; without it the response lists the cases that would be dropped and nothing is written. |
Runs
| Operation | Scope | Idempotency | Purpose |
|---|---|---|---|
run.trigger | autonomy:runs:write | Required | Queue Runs. Give exactly one of testCaseId or testPlanId (a plan queues one Run per member case). Target a saved Environment by slug, or pass explicit targets for a fresh deployment or artifact. Returns immediately; follow with run.get. |
run.list | autonomy:read | None | List recent Runs, newest first. Filter by status, Test Case, Environment, or branch. Check here before triggering duplicate work. |
run.get | autonomy:read | None | Fetch a Run's state. Pass the previous cursor and waitMs (≤ 25000) to block until something changes; timedOut: true means nothing changed and is not an error. next is advice, never authority. |
run.evidence | autonomy:read | None | Get External Evidence for a Run: what the product showed and expected per step, the verdict and diagnosis, neutral actions, and short-lived media links. Model, prompt, token, and runner internals are never included. Filter with step. |
Environments
| Operation | Scope | Idempotency | Purpose |
|---|---|---|---|
environment.list | autonomy:read | None | List Environments (named deployment targets) with their per-platform targets. Runtime value names are shown; values never are. |
environment.get | autonomy:read | None | Fetch one Environment by slug. |
environment.upsert | autonomy:environments:write | Required | Create an Environment, or update one by slug. Updating an existing slug overwrites the given targets and requires confirm: true; without it the response describes the change and nothing is written. |
Notes
Notes are HTTP-only and do not appear in the MCP tool catalog.
| Operation | Scope | Idempotency | Purpose |
|---|---|---|---|
note.list | autonomy:read | None | List Notes on an Environment, newest first. Filter by status. |
note.create | autonomy:notes:write | Required | File a Note on an Environment. The body is plain text, where each newline starts a paragraph. Cite Runs with runIds. |
note.comment | autonomy:notes:write | Required | Add a plain-text comment to a Note's activity. |
Idempotent mutations
Every mutation marked Required must include an idempotencyKey string in its JSON body. Reuse the same key when retrying the same intended mutation; use a new key for a different intended mutation. Read operations do not use an idempotency key.
Create a Test Case
This request uses only fields accepted by test_case.create. The valueSpec objects distinguish an ordinary literal from an Environment value resolved at Run time.
curl --request POST "$AUTONOMY_API_BASE/api/v1/test_case.create" \
--header "Authorization: Bearer $AUTONOMY_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"idempotencyKey": "ci-test-case-checkout-smoke-v1",
"name": "Checkout smoke",
"description": "A customer can complete checkout.",
"platforms": ["web"],
"tags": ["checkout", "smoke"],
"steps": [
{
"action": "navigate",
"target": "/checkout"
},
{
"action": "fill",
"target": "Email",
"valueSpec": { "kind": "literal", "text": "qa@example.com" }
},
{
"action": "fill",
"target": "Password",
"valueSpec": { "kind": "environment", "variable": "LOGIN_PASSWORD" }
},
{
"action": "click",
"target": "Place order"
}
]
}'Set AUTONOMY_API_BASE to NEXT_PUBLIC_CONVEX_SITE_URL and store the aut_ key in AUTONOMY_API_KEY.
Trigger a Run
Give exactly one of testCaseId or testPlanId. This example targets a fresh web preview; use environmentSlug instead when the target is saved.
curl --request POST "$AUTONOMY_API_BASE/api/v1/run.trigger" \
--header "Authorization: Bearer $AUTONOMY_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"idempotencyKey": "ci-run-pr-128-checkout-smoke-9f3a2c1",
"testCaseId": "jh7exampletestcaseid",
"platforms": ["web"],
"targets": {
"web": { "baseUrl": "https://preview-128.example.com" }
},
"branch": "feature/checkout-copy",
"pr": "128",
"deployment": { "commitSha": "9f3a2c1d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b" },
"scope": "changed",
"changedFiles": ["src/checkout/page.tsx"]
}'The response contains runIds and, for a Test Plan, may contain planGroupRunId. Triggering returns immediately; follow each id with run.get.
Confirmation before replacement
confirm: true is never required for a create or for run.trigger. It is required only when an operation would replace existing configuration:
test_case.update_stepsalways requires it because the whole step list is replaced.test_plan.set_membersrequires it only when cases would be removed.environment.upsertrequires it when an existing slug would be updated with supplied fields or targets.
Without confirmation, the API returns INVALID_ARGUMENT with details.confirmRequired: true and a details.wouldChange preview. Inspect that preview before retrying; do not add confirm: true automatically.
Cursor pagination
Every *.list request accepts an optional limit and opaque cursor:
1{2 "limit": 20,3 "cursor": "<nextCursor from the previous response>"4}limit defaults to 20 and must be an integer from 1 through 100. Each response has { items, nextCursor }. Pass nextCursor unchanged to fetch the next page; null means there are no more pages. Filter arguments belong in the same body and should remain unchanged across pages.