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, 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.
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.
Extract output
page is 0-based; bbox is normalized 0–1 with a top-left origin; confidence is 0–5. A field the document doesn’t contain comes back null, which is why every property should be declared nullable.
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.
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.- 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