API context for agents
Point a coding agent at https://docs.cloudraker.com/developers/agents.md. The page gives it all it needs to write a working integration. It covers auth, the request and error envelopes, all six verbs, and the run lifecycle. It also covers multi-step agent runs, the schema dialect, and the limits.
Every page on this site has a .md twin. https://docs.cloudraker.com/llms.txt indexes them all. Start from this page.
Base URL and auth
Base URL: https://api.cloudraker.com. Every request carries an organization API key as a bearer token:
One key belongs to one organization. The key identifies the tenant, so you never pass a tenant, account, or workspace id. Create keys in the app under Admin → API keys. The value is shown once.
The six verbs
Each verb is a single POST that creates a run. Each is synchronous by default and accepts ?wait= (0–120 seconds, 60 default). Minimal bodies:
Shared optional fields on every verb: metadata (your own key/values, ≤10 KB, echoed back and filterable), webhook ({url} or {id}), ttl (seconds, default 86400, max 604800), and the idempotency-key request header.
Citations are off by default everywhere. To get them, send "citations": true on POST /v1/extract, on POST /v1/extract/batch, or on an extract step in a pipeline. On a saved config, the grounding install setting does the same and also defaults to false.
extract, redact, fill, and sign also accept action: "<id or slug>" instead of inline config. Inline fields win over the saved ones. Save a config with POST /v1/{extract|redact|fill}/configs {name, config}. The flat POST /v1/actions {capability, name, config} is a deprecated alias. Discover configurable shapes with GET /v1/actions/catalog.
File references
Every file input takes one of two shapes, never a multipart upload:
processing: auto (default), ocr, simple, transcribe, transcribe_diarize. Single-file verbs take file. Multi-file verbs take files[] (up to 100). A request with both is a 400.
Register a persistent file with POST /v1/files. Send {url, name?} — the source must serve a Content-Length. Or send {name, mimeType} to get an uploadUrl valid for 15 minutes. PUT the bytes to it with the identical Content-Type. Poll GET /v1/files/:id until status: "ready". Files a run creates inline expire with the run. Files you register do not.
Runs
Id prefixes: exr_ extract, par_ parse, rdr_ redact, flr_ fill, sgr_ sign, plr_ pipeline. Treat ids as opaque strings.
Statuses: queued, processing, processed, failed, cancelled, expired, needs_input. output exists only at processed. needs_input means a signature envelope is open; read it through envelopeUrl.
A synchronous call that does not finish within ?wait= returns 202 with the run handle, never a timeout error. Poll statusUrl or use a webhook. Sign runs are exempt from the TTL purge while the envelope is open. Every other run and its inline files are purged at expiresAt.
GET /v1/runs takes object, status (the six values above minus queued), limit (1–50, default 20), cursor, and up to three metadata.<key>=<value> pairs. It returns {object:"list", data:[…handles…], has_more, cursor}. The list is eventually consistent. GET /v1/runs/:id is authoritative.
Agents and agent runs
This surface is separate from the verbs and from /v1/runs. An agent is a saved, versioned, multi-step automation (steps + saved configs + sign-off gates). An agent run (agr_…) is one execution of an agent, and it can wait days on a person.
Statuses: queued, processing, waiting, paused, completed, failed, cancelled, expired. A completed run with unfinished work also carries incomplete: true. paused (paused.reason) is resumable, not a failure. The run carries tasks[] (executor: "agent"|"human", status: pending|ready|in_progress|completed|skipped), approvals[] (kind: "before"|"output", with the proposed params and files), waiting: {approvals, tasks, summary}, progress.tasks, result, output.files[] (signed ~1 h), error, metadata, expiresAt (~7 days).
Rules that differ from capability runs:
- Poll a
queuedagent run. A read starts it once its files are prepared. A webhook alone leaves itqueued. - No list, no cancel, no delete. Agent runs never appear in
GET /v1/runs. Keep theagr_id, or tag runs withmetadata. - No
ttl. Files passed by URL become persistent files.expiresAt(~7 days) is the deadline. Past it, an unfinished run parks permanently. - Only
executor: "human"steps are completable (422otherwise). An unmetdependsOnor an already-closed step is409. A rejection requiresnote. A second decision on the same approval is409. - Webhook events:
agent_run.waiting,agent_run.approval_requested(minimal; re-read the run forparams),agent_run.task_ready,agent_run.completed,agent_run.failed(also carriescancelled/expired; trustdata.status). Deliveries use the same signature and JWKS as every other delivery.processingIdcarries theagr_id.
Extract output
page is 0-based. bbox is normalized 0–1 with a top-left origin. confidence is 0–5. Audio grounds with a timecode instead of page/bbox. A notFound entry carries only fileId: no page, bbox, timecode, text, or confidence. A field the document does not contain comes back null. Declare every property nullable for this reason.
Grounding is guaranteed-or-flagged. When citations are on, every filled field returns at least one citation or an explicit notFound declaration. A deterministic second model pass cites or declares absent anything the first pass left uncited. When the run was not grounded, the citations key is absent, never an empty object. citationsOmitted: true on output means the result exceeded the size budget, so citations were dropped. It appears at output level only, never per document.
Extraction schema dialect
Plain JSON Schema with four constraints, checked before the run starts (400 invalid_schema, with the offending path):
- The root must be
{"type": "object"}. - Nesting may not exceed 5 levels.
- No
$defs,$ref,oneOf,anyOf,allOf,const, orpattern. These are the only rejected keywords, and only in keyword positions (a property namedpatternis valid). Constrain values withenum. Describe formats indescription. - The serialized schema must stay under 64 KB.
Make every primitive nullable: {"type": ["string", "null"]}. This is recommended, never enforced. A non-nullable field pressures the extractor to invent a value instead of a null. This change has the highest impact on extraction quality. With citations on, an absent value is also marked notFound, not left ambiguous.
Add a description per property. It is the strongest accuracy lever. unit controls cardinality: per_document (default), across_documents, rows_per_document.
Errors
Every /v1 failure is the same envelope, with x-request-id also on the response headers:
Branch on code, never on message. Common codes: unauthorized, invalid_token (401); invalid_request, invalid_schema, action_unknown, file_ineligible, run_too_large, schema_too_large (400); not_found (404); file_not_ready, output_not_ready, already_kept, pipeline_running (409); run_expired (410); file_fetch_failed, webhook_endpoint_not_found, webhook_endpoint_disabled (422); rate_limited (429); internal_error, file_unreadable, file_upload_failed (5xx). Retry only where retryable is true.
Rate limits
The limit is at least 67 requests per minute per organization, shared across every /v1 endpoint. This is a guaranteed floor enforced per edge location, so a distributed caller can sustain more. Over the limit, you get 429, code: "rate_limited", Retry-After: 60. Nothing starts, and nothing is billed. Respect Retry-After, then back off exponentially with jitter. One batch call and one long-poll each cost one request. Both beat looping for this reason.
Webhooks
Send webhook: {"url": "https://…"} on any verb, or register an endpoint with POST /v1/webhooks and reference it as webhook: {"id": …}. Deliveries are signed JWTs. Verify them against GET /v1/webhooks/jwks.json (public, unauthenticated, never rate limited). Deliveries do not include run metadata. Re-fetch the run by id.
Rules that save you a debugging session
- No
/v1run data appears in the CloudRaker app until youPOST /v1/runs/:id/keep. This is deliberate: ephemeral by default. - Schema inference (
hints, noschema) picks its own field names and can differ between runs. Use it once to discover the shape, then pinconfig.schemaor save it as an action. hintswith aschemaor anactionis a400. Useinstructionsinstead.POST /v1/extract/batchhas a strict body: it rejectsschemaandhints, not ignores them. It always returns202. It acceptscitations.- Pipeline steps run in parallel over the same files. A step never consumes another step’s output.
- A produced file is registered a moment after
processed. Until then,output.file.urland/output/:namereturn409 output_not_ready(retryable, never404). Wait a moment and ask again. - Reuse
fileIds instead of URLs. The API does not fetch or parse the document again.
Full reference
- OpenAPI:
https://docs.cloudraker.com/openapi.json— the full gateway spec, withPOST /v1/extract/batchandGET /v1/runs. It is re-exported when the surface changes. Where the two disagree, this page is right. - Markdown index for agents:
https://docs.cloudraker.com/llms.txt - MCP server:
https://mcp.cloudraker.com— see MCP server - Human-readable start: Agent quickstart, Quickstart