API context for agents
The whole CloudRaker API contract on one page — written to be fetched as Markdown by a coding agent.
Point a coding agent at https://docs.cloudraker.com/developers/agents.md and it has everything it needs to write a working integration: auth, the request and error envelopes, all six verbs, the run lifecycle, multi-step agent runs, the schema dialect, and the limits.
Every page on this site has the same .md twin, and https://docs.cloudraker.com/llms.txt indexes them all. This page is the one to start from.
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 is the tenant, so no tenant, account, or workspace id is ever passed. Keys are created in the app under Admin → API keys and shown once. Staging (https://api.staging.raker.one) and development (https://api.dev.raker.one) are separate environments with separate keys.
The six verbs
Each is a single POST that creates a run, 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. Send "citations": true on POST /v1/extract, on POST /v1/extract/batch, or on an extract step inside a pipeline to get them; on a saved action 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 one with POST /v1/actions {capability, name, config}; discover configurable shapes with GET /v1/actions/catalog.
File references
Anywhere a file is taken, the value is 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). Sending both is a 400.
Register a persistent file with POST /v1/files — either {url, name?} (the source must serve a Content-Length) or {name, mimeType}, which returns an uploadUrl valid 15 minutes that you PUT the bytes to 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 human is required — a fill review (tasks[]) or an open signature envelope (envelopeUrl).
A synchronous call that doesn’t 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} and is eventually consistent — GET /v1/runs/:id is authoritative.
Agents and agent runs
A separate surface from the verbs and from /v1/runs. An agent is a saved, versioned, multi-step automation (steps + saved actions + sign-off gates); an agent run (agr_…) is one execution of it that 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:
- A
queuedagent run must be polled — reading it is what picks it up once its files are prepared. A webhook alone leaves itqueued. - No list, no cancel, no delete, and 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: an unfinished run parks for good past it. - Only
executor: "human"steps are completable (422otherwise); unmetdependsOnor an already-closed step is409. Rejecting an approval requiresnote. Deciding the same approval twice 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). Same signature and JWKS as every other delivery, withprocessingIdcarrying 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 doesn’t contain comes back null, which is why every property should be declared nullable.
Grounding is guaranteed-or-flagged: when citations are on, every filled field comes back with 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 entirely, never an empty object. citationsOmitted: true on output means citations were dropped because the result exceeded the size budget; it is output-level only and never appears 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 fine). Constrain values withenum; describe formats indescription. - The serialized schema must stay under 64 KB.
Making every primitive nullable — {"type": ["string", "null"]} — is recommended, never enforced: a non-nullable field pressures the extractor into inventing a value instead of returning null. It is the single highest-impact change to extraction quality. With citations on, an absent value is also marked notFound rather than 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
At least 67 requests per minute per organization, shared across every /v1 endpoint — a guaranteed floor enforced per edge location, so a distributed caller may sustain more. Over it: 429, code: "rate_limited", Retry-After: 60. Nothing is started and nothing is billed. Respect Retry-After, then back off exponentially with jitter. One batch call and one long-poll each cost a single request, which is why both beat looping.
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 verified against GET /v1/webhooks/jwks.json (public, unauthenticated, never rate limited). Run metadata is not included in deliveries — re-fetch the run by id.
Rules that save you a debugging session
- Nothing a
/v1run touches appears in the CloudRaker app until youPOST /v1/runs/:id/keep. That 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 —schemaandhintsare rejected, not ignored — and always returns202.citationsis accepted there.- 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 thenoutput.file.urland/output/:namereturn409 output_not_ready(retryable, never404). Wait a moment and ask again. - Reuse
fileIds instead of re-sending URLs: the document is neither re-fetched nor re-parsed.
Full reference
- OpenAPI:
https://docs.cloudraker.com/openapi.json— the full gateway spec, includingPOST /v1/extract/batchandGET /v1/runs. It is re-exported whenever the surface changes; where it and this page ever 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