Fill
Configure a form once, then fill it many times — from exact values, or drafted from your source documents.
POST /v1/fill fills a form PDF and returns the completed file. Send exactly one of two inputs:
values— the field values to write, keyed by field name. Deterministic: no drafting pass, no model call.files— source documents. CloudRaker drafts one value per field.
Fill works best as a two-step flow. Configure once: upload the blank form as a template, inspect its fields, curate them, and save the result on a fill config. Fill many times: call POST /v1/fill with action and either values or files. See Configure a form once.
How it works
- You pick the form. Send
templateinline —{"id": "…"}for a saved template, or{"url": "…"}for a one-off. Or sendactionnaming a saved config that carries one. Inline wins when both are present. - You pick the input.
valueswrites your JSON straight into the form.filesparses the sources and drafts a value per field. A fill run never re-detects fields: it uses the fields saved on the config, or the form’s own field inventory when none are saved. - In
filesmode, CloudRaker writes the drafted values into the PDF. - The completed file comes back as
output.file. It isflattened(values baked in) oreditable(still a fillable form). - The run and its files expire on their own (
ttl, 24 hours by default) unless you keep them.
Quickstart
The sample drafts a blank IRS Form W-9 from one source document. Both are public URLs. Nothing is local.
The TypeScript and Python samples are plain HTTP, so they run with nothing installed. This endpoint is also a top-level method on both SDKs as of 0.3.0: client.fill(…). That page has a full worked example.
Example response
Key fields
The output file’s bytes are registered a moment after the run reports processed. In that window, output.file can arrive without its url, and the /output/ alias can answer 404. Re-fetch GET /v1/runs/:id and the URL will be there.
Configure a form once
Curating a form once makes every later fill predictable. The saved fields fix the schema: field names, human labels, per-field guidance, and which fields to skip.
Save the blank form as a template
POST /v1/templates with a url, or the presigned-upload shape. See Templates.
Inspect it
POST /v1/templates/:id/inspect returns { fields, schema, pageBoxes, pageCount, detected, templateHash }. Each field carries name, type, label, page, and box. CloudRaker detects fields when the PDF has none of its own — detected says so. Templates over 32 MB answer 413 template_too_large.
A fill config accepts exactly these keys: template (a template or file id), instructions, output, fields, and templateHash. An unknown key answers 400 instead of being stored dead. PATCH /v1/fill/configs/{idOrSlug} deep-merges the keys you send and keeps all other saved keys.
From then on, every call is one line of config:
template is optional when action carries one — the saved template applies, and sending template inline still wins. Any other inline field also wins over its saved counterpart.
A fill run never re-inspects the form. Inspect runs at configure time only. A run uses the config’s saved fields; with none saved, it uses the form’s own field inventory and labels.
GET, PATCH and DELETE /v1/fill/configs/{idOrSlug} manage a config. GET /v1/fill/configs lists them. /v1/actions still works as a deprecated alias. See Saved configs.
Fill from values
values mode is deterministic. Your JSON is coerced to each field’s type and written into the PDF. No model is called.
Key values by field name — the names come from inspect, or from the fields saved on the config. Its schema describes the exact object values accepts.
A key that matches no field fails the run fast, before anything is written or metered. The run reports status: "failed" with error.code: "unknown_fields", and error.message lists the offending keys.
Configuration
An ephemeral template: {url} is fetched at run time. It is not added to your template library. The fetched copy is registered as a file in your API workspace. GET /v1/files lists it while the run is alive. But the copy belongs to the run: it is reclaimed when the run expires. POST /v1/runs/:id/keep moves it into the target space with everything else.
Pass {id} when you fill the same blank form repeatedly. A saved template is persistent. A run’s TTL never touches it.
Sync vs async
Synchronous by default, with ?wait= between 0 and 120 seconds, exactly like extract.