Skip to content
MacrofoldDocs
Reference

API conventions

Authentication, idempotency, errors, pagination, and asynchronous operations.

Use the REST API to create workspaces, start runs, follow progress, and retrieve saved work. The dashboard, CLI, and SDKs use the same resource model and authorization rules.

Start with the API quickstart. The application serves an interactive reference at /reference and its complete OpenAPI contract at /openapi.json.

Authentication and organizations

Send a scoped API key or customer OAuth token in Authorization: Bearer …. Generate keys in API keys and save the secret when it is shown once. Keep credentials on your server or in a secret store, never in browser bundles or URLs.

A key belongs to one organization and can restrict scopes and workspaces. X-Organization-Id selects an authorized membership for credentials that support it; it cannot move an organization-bound key into another tenant. Resource IDs do not grant access.

Resource conventions

All customer routes start with /v1. JSON fields use snake_case, timestamps use RFC 3339 UTC, and resource IDs are opaque. Money uses decimal-string micro-USD; 1000000 means $1. Large counts also use strings where required by the schema.

TaskRoutes
Identity and catalogs/me, /harnesses, /models
Workspace files/workspaces, /worktrees/{id}/files, /worktrees/{id}/file
Execution/runs, /sessions, /sessions/{id}/messages
Status and output/runs/{id}, /runs/{id}/result, /runs/{id}/stream
Recovery and Git/worktrees/{id}/checkpoints, /worktrees/{id}/restore, /worktrees/{id}/sync
Triggers and schedules/triggers, /triggers/{id}/deliveries, /slack-connections
Tools and access/connections, /api-keys
Usage and billing/usage, /requests, /billing, /billing/usage

The table shows route families; use OpenAPI for exact parameter names, required fields, and operation IDs. Incoming triggers use separate signed Slack or bearer webhook endpoints under /events; those provider callbacks do not accept a normal Macrofold API key.

Idempotency

Supply a unique Idempotency-Key for each intended mutation. Reuse it with the identical request when recovering a lost response. The server retains fingerprints and results for 30 days. Reusing a key with a different body returns 409 idempotency_conflict.

Run creation, session messages, checkout, file mutations, restore, sync, transfer planning/apply, exports, and immediate inference require idempotency. All five SDKs generate mutation keys through their resource methods. Other operations retain TypeScript/Python bounded retries and Go/Rust/Java single-attempt REST behavior. Immediate inference makes one attempt by default in every SDK; its explicit retries apply only to confirmed pre-admission refusals and preserve the same key/body under one total deadline. All clients retain uncertain mutation identities in errors. Supply and store your own key to recover across process restarts. cURL and low-level Go/Rust/Java operations require an explicit key.

Asynchronous work

A run request returns 202 with run_id, related resource IDs, and URLs for status, events, result, and cancellation. File and worktree maintenance may return an operation ID instead. Poll /v1/operations/{id} and inspect its final status before using its result.

Result retrieval reports final=true after terminalization. Available partial output can be returned earlier. A canceled stream is not a canceled run; use the run cancellation endpoint explicitly.

Immediate model calls

POST /v1/inferences executes one provider request directly and returns HTTP 200 with the finalized result, including terminal execution failures. Inspect status and result.inference.outcome; only value carries usable output. Exceptional HTTP 202 means that the same admitted invocation is still running or recovering, identified by recovery_reason and its five receipt URLs. It is never queued acceptance. Its input, usage and billing use the same durable Run identity.

Prefer: respond-async is rejected with async_inference_not_supported; queue_timeout_seconds belongs to queued agent/task APIs. Native/bounded execution keeps its existing queue behavior. For direct SSE use inferences.stream; HTTP 200 starts delivery and its committed terminal event determines execution outcome.

Busy capacity/dependencies return a prompt HTTP 429/503 refusal. Only confirmed pre-admission refusals marked retryable:true are safe for automatic same-key retry after Retry-After. inference_admission_unknown is explicitly non-retryable automatically because a Run may exist. Resolve the same identity deliberately; never create a replacement automatically. See the full delivery/recovery contract.

Pagination and rate limits

Lists use limit and a cursor, returning next_cursor. The default page size is 25 and maximum is 100. Follow the returned cursor rather than constructing one.

Each credential has independent per-minute budgets within its organization: 12,000 reads, 1,200 writes, and 1,200 Run cancellations/input answers by default. Polling cannot consume submission or cancellation capacity. Deployments may configure each budget. A 429 includes Retry-After. HTTP limits, run concurrency, and spending caps are independent.

Errors and retries

Errors include error.code, message, request_id, details, and retryable. Preserve request IDs for diagnosis.

An admitted direct inference keeps its existing terminal receipt contract: result.inference.reason_code classifies the failure, and optional result.inference.provider_error carries the upstream HTTP status, exact message (subject to credential redaction and a 16 KiB bound), optional provider code and truncation flag. This also appears in terminal SSE results and authorized replay; it does not turn a failed inference receipt into an HTTP admission error or grant permission to retry. See result interpretation.

ResponseWhat to do
401Refresh authorization or sign in again
403Check membership, scopes, workspace restrictions, and current grants
409 worktree_busyWait for the writer or select an independent worktree
409 idempotency_conflictRestore the original body for that key
412 stale_revisionRead the current file revision and reconcile your change
429Honor Retry-After and reduce request rate
Provider or transport failureCheck whether the outcome is known before repeating a mutation

Do not automatically repeat an external side effect whose outcome is uncertain. See troubleshooting for recovery paths.

Streaming, clients, and protocols

Read streaming and webhooks and the SDK guides for TypeScript, Python, Go, Rust, and Java.

Protocol details cover transfer preconditions, OAuth discovery, event delivery, and endpoint inventory. Customer REST, authentication protocols, provider webhooks, and operator MCP are separate authorization surfaces.