Pipelines

Run several capabilities over one set of files in a single call.
View as Markdown

POST /v1/pipeline takes one file set and a list of steps. Every file is parsed once, then each step runs over the parsed set. It is the JSON, inline-config successor to the multipart /process API.

Steps run in parallel over the same files, not chained. A step never consumes another step’s output — “redact the form that fill produced” is not expressible today. Each step reads the original file set.

How it works

  1. You send files (URLs or file ids) and steps.
  2. Each step is one of {"extract": {…}}, {"redact": {…}}, {"fill": {…}}, {"sign": {…}} — the same inline config the matching verb takes — or {"action": "<id or slug>", "params": {…}} for a saved action. There is no parse step: parsing is automatic.
  3. The response is 202 with the pipeline id (plr_…) and a typed id per step, in the order you sent them.
  4. GET /v1/runs/plr_… carries steps[] — each with its own id, capability, status, and result.

Quickstart

$curl -X POST https://api.cloudraker.com/v1/pipeline \
> -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "files": [{ "url": "https://www.irs.gov/pub/irs-pdf/fw9.pdf", "name": "w9.pdf" }],
> "steps": [
> { "extract": { "schema": { "type": "object", "properties": { "form_number": { "type": ["string", "null"] } } } } },
> { "redact": { "categories": ["ein"], "mode": "targeted" } }
> ],
> "ttl": 86400
> }'

Example response

The create call returns the handle and the step ids:

1{
2 "object": "pipeline_run",
3 "id": "plr_01KYD7F40BGQA7WXB50ENSQEK1",
4 "status": "queued",
5 "statusUrl": "/v1/runs/plr_01KYD7F40BGQA7WXB50ENSQEK1",
6 "steps": [
7 { "id": "exr_01KYD7F40B35TT7XR1KPMFZXJ6", "capability": "extract" },
8 { "id": "rdr_01KYD7F40BDN07JRKXRERJYTRE", "capability": "redact" }
9 ]
10}

Polling GET /v1/runs/plr_… returns the same step ids with results attached:

1{
2 "object": "pipeline_run",
3 "id": "plr_01KYD7F40BGQA7WXB50ENSQEK1",
4 "status": "processed",
5 "expiresAt": "2026-07-26T18:09:16.204Z",
6 "statusUrl": "/v1/runs/plr_01KYD7F40BGQA7WXB50ENSQEK1",
7 "files": [
8 { "id": "39c1759c-5f47-425a-9ef2-6b9efe51fb7a", "name": "w9.pdf", "status": "processed" }
9 ],
10 "steps": [
11 {
12 "id": "exr_01KYD7F40B35TT7XR1KPMFZXJ6",
13 "capability": "extract",
14 "status": "processed",
15 "output": {
16 "value": { "form_number": "W-9" },
17 "citations": {
18 "form_number": [
19 {
20 "fileId": "39c1759c-5f47-425a-9ef2-6b9efe51fb7a",
21 "page": 0,
22 "bbox": { "x": 0.0918, "y": 0.0376, "width": 0.0653, "height": 0.0364 },
23 "text": "Form W-9",
24 "confidence": 5
25 }
26 ]
27 },
28 "documents": [ /* one entry per input document */ ]
29 }
30 },
31 {
32 "id": "rdr_01KYD7F40BDN07JRKXRERJYTRE",
33 "capability": "redact",
34 "status": "processed",
35 "output": {
36 "file": { "id": "e130ad59-6309-44c7-bb27-1106a1c32621", "name": "w9 (redacted).pdf", "url": "https://cdn.cloudraker.com/…/latest?token=…" },
37 "files": [ /* one redacted file per input document */ ],
38 "entities": { "ein": 11 },
39 "skipped": 0
40 }
41 }
42 ]
43}

Key fields

FieldWhat it is
objectAlways pipeline_run.
idThe pipeline id (plr_…).
statusThe pipeline’s own status — queued, processing, needs_input, processed, failed, cancelled, or expired.
files[]The shared, parsed-once input set.
steps[].idThe typed step id — exr_, rdr_, flr_, sgr_. null for a bare {"action": …} step.
steps[].capabilityextract, redact, fill, sign, or action.
steps[].statusThat step’s own status. One step failing does not erase the others’ results.
steps[].outputExactly the output the matching verb returns.

Sub-routes that address a single step — /task, /envelope, /void, /audit, /signers/:id/resend — resolve against the run’s matching step: /task* goes to the fill step, the rest to the sign step. A pipeline without that step answers 404 not_found.

Configuration

FieldTypeWhat it does
files[]array of {url, name?, processing?} or {id}, 1–100Required. Parsed once, shared by every step.
steps[]array, 1–20Required. The capabilities to run.
metadataobjectYour own key/values, echoed back on the run body (not on webhook deliveries). Max 10 KB.
webhook{url} or {id}Where to deliver events. See Webhooks.
ttlinteger seconds, 1–604800How long the pipeline and its files live. Default 24 hours, max 7 days. A pipeline containing a sign step is exempt while the envelope is open.

Step configs are validated exactly like the standalone verbs: an extract step with neither schema nor action fails with 400 invalid_request, and a schema that breaks the schema dialect fails with 400 invalid_schema — same codes, same messages, as POST /v1/extract.

Sync vs async

Always asynchronous — POST /v1/pipeline returns 202 and takes no ?wait=. Poll GET /v1/runs/plr_…?wait=<seconds> (0–120) to long-poll for a terminal state, or subscribe a webhook and wait for processing.completed.

Sending an idempotency-key makes retries safe. A replay returns the original pipeline — its id, its current status, and its original step ids — with an idempotent-replay: true response header, not a second run.

Save as an action

Each step accepts a saved action instead of inline config, and the two can be combined — inline fields win:

1{
2 "files": [{ "id": "a04d6597-4e34-4a99-94ea-964c289a4c68" }],
3 "steps": [
4 { "extract": { "action": "medical-intake" } },
5 { "action": "hr-offboarding" }
6 ]
7}

{"extract": {"action": …}} keeps the step typed (its id is exr_…) and lets you override fields inline. A bare {"action": …} step runs the saved action as-is and its step id is null. See Saved actions.

Next steps