Fill from context docs
Hand Emboss a form plus one or more supporting documents, prior filings, a profile sheet, anything that holds the values, and it reads your documents and fills what it can match.
The default is filling a form you've already created: you ran detection once, and now you want to fill that same form from context. There's also a convenience path that takes a brand-new flat PDF and extracts and fills it in a single call.
Already have the values as structured data? Use direct fill instead (Fill from your data): it's deterministic and skips the inference step.
Fill an existing form
If you've already created a form (see the Quickstart or
POST /forms) and it's ready, fill it from context with
POST /forms/{form_id}/with-context. The form is identified by {form_id} in
the URL, so the request body carries only context file parts: no file.
curl -X POST https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/with-context \
-H "Authorization: Bearer sk_..." \
-F "context=@./w9-prior-year.pdf" \
-F "context=@./company-profile.txt"
{ "job_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "status": "processing" }
This bills a single context fill at 3¢, which is
flat to 5 pages, then 2¢ per page, counting the form and its context documents
together, with the first 5 each month free. That
price includes verifying the rendered document, effective 09-06-2026.
The form must be ready and owned by your key: an unready form returns 409,
and one you don't own returns 404. Then poll the job
below.
Choosing how sure Emboss must be
Both endpoints take an optional policy field alongside context, with two
values: safe and strict. safe is the default: Emboss writes any value
it reported as high or medium confidence. strict writes only high-confidence
values and leaves medium-confidence ones for you to confirm. Either way you get
back a response of the same shape: a filled PDF and a report, just with a
different line drawn between what's written and what's flagged.
curl -X POST https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/with-context \
-H "Authorization: Bearer sk_..." \
-F "context=@./w9-prior-year.pdf" \
-F "context=@./company-profile.txt" \
-F "policy=strict"
When documents disagree
When two documents give a box different answers, an AI check reads both
quotes and the boxes around it. If it is at least 85% sure which reading
belongs, the fill writes that one at medium confidence: under safe it goes
into the PDF, under strict it waits for you to confirm. If the two readings
are the same fact written two ways, it keeps one. The receipt marks such a value
with origin tiebreak and a note naming the reading chosen and the one
passed over. When the check is not sure, the box is left blank and reported as
a conflict. To decide every disagreement yourself, use
prepare and commit: there the check only merges
readings that are the same fact and puts the others in order, and every real
conflict waits for your answer.
Start from a brand-new PDF
If you don't have a form yet, POST /forms/with-context takes the flat PDF and
the context in one shot: Emboss detects the form's fields and fills them. The
request is multipart/form-data: the file (the flat PDF) plus one or more
context file parts.
curl -X POST https://api.getemboss.ai/forms/with-context \
-H "Authorization: Bearer sk_..." \
-F "file=@./vendor-onboarding.pdf" \
-F "context=@./w9-prior-year.pdf" \
-F "context=@./company-profile.txt"
{ "job_id": "6c47f7f5-f921-4698-910f-95dd7d81310b", "status": "processing" }
Because this both extracts and fills, it bills an extraction plus a context
fill. A non-PDF form returns 400.
Either way, limits per request are: up to 5 context files, 10 MB per
file, 30 MB total, and 100 pages on the form. Past these you'll get a
413. Going over the free tier with no card on file returns 402. For a fill
from documents the free tier's page limit counts the form and its documents together.
Poll for the result
Both endpoints return a job_id you poll the same way:
curl https://api.getemboss.ai/forms/with-context/6c47f7f5-f921-4698-910f-95dd7d81310b \
-H "Authorization: Bearer sk_..."
While running, status is processing. When it's ready you get a
session_id; on failure it's failed with an error message.
{
"job_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
"form_id": "0b5a9e7c-3d2f-4e1a-9c8b-7d6e5f4a3b2c",
"status": "ready",
"session_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"proposal_id": "3e714663-ff2c-45ac-ae11-3c7015facfef",
"result": "complete",
"receipt_url": "https://api.getemboss.ai/proposals/3e714663-ff2c-45ac-ae11-3c7015facfef/receipt",
"pdf_url": "https://api.getemboss.ai/proposals/3e714663-ff2c-45ac-ae11-3c7015facfef/pdf",
"report": {
"filled": [
{ "id": 3, "confidence": "high" },
{ "id": 7, "confidence": "high" },
{ "id": 14, "confidence": "med" }
],
"dropped": [],
"verification": {
"result": "complete",
"checked_at": "2026-09-06T18:33:02.114921+00:00",
"issues": [],
"adjustments": [],
"counts": { "fields": 24, "written": 24, "required_unfilled": 0, "issues_blocking": 0, "issues_review": 0 }
}
},
"error": null
}
A finished fill carries form_id, the form it filled, and four fields beyond
the session_id. result is the verification result, one of complete,
review_required or incomplete; a job that breaks ends with status
failed instead. receipt_url and pdf_url point at the receipt and the filled
document. report holds filled, one entry per field that was written, each
with the field's integer id and the confidence it was written at (high,
med or low), and dropped, alongside verification, the full verification
report: its own result, checked_at, issues, adjustments and counts.
Nothing was removed from the response, so a caller reading only session_id
keeps working.
When nothing was found
A fill can finish ready without writing anything, when the documents don't
hold the form's answers or can't be read (a blurry or sideways photo, say).
The report then carries no_values_found in warnings, and a message you
can show the person as it is:
{
"job_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
"status": "ready",
"result": "incomplete",
"report": {
"filled": [],
"dropped": [],
"warnings": ["no_values_found"],
"message": "<why nothing was filled, to show the person as it is>"
}
}
Check warnings, not result: on a form with no required fields, a fill that
wrote nothing can still verify as complete.
On an account, the fill isn't counted against your plan (making the form
fillable still is), and the message says so when that applies. The form
stays made, so you can fill it again from a different document with
POST /forms/{form_id}/with-context (the job's form_id is the one to use), which bills only the fill.
The same file as the form
A supporting document that is byte-for-byte the form you're filling, with
nothing typed, ticked or chosen in it, holds nothing to copy. Emboss refuses
the request with 422 and code document_same_as_form before anything is
charged:
{
"detail": {
"code": "document_same_as_form",
"message": "The document you added is the same blank form you're filling, so there's nothing to copy from it. Add the document that holds your answers, such as a statement, an ID, or a filled copy from before.",
"document_index": 0
}
}
document_index is the refused file's position among the context files,
counting from 0. A filled copy of the same form goes through.
A PDF that could compromise the service
A PDF whose form fields are built in a way that could compromise the service is
refused with 422 and code pdf_unsafe before any price, quote, charge or
stored file:
{
"detail": {
"code": "pdf_unsafe",
"message": "Emboss does not process PDF files that could compromise the service."
}
}
Replace the form with a different PDF; nothing was charged.
Emboss verifies every context fill against the form's contract as part of the
fill, with no extra call: that check is arithmetic and geometry. Separately, a
second AI model looks over each written value against its box's label and the
boxes around it, and any doubt it raises lands in the receipt's checks block.
If you would rather see the proposed
answers before anything is written, split this into two calls: see
Prepare, commit and verify.
The resulting session is already completed and its PDF is already
rendered: use it to download the PDF, not to edit or render it again.
(PUT /sessions/{sid}/fields on a completed session returns 409,
and so does POST /sessions/{sid}/fill.)
Download the filled PDF
curl https://api.getemboss.ai/sessions/a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d/pdf \
-H "Authorization: Bearer sk_..." \
-o filled.pdf
Want to see what Emboss detected before or after the fill? Read the contract shape.
Retention
Every create and with-context call takes an optional retention body field:
ephemeral or account_default. Leave it out and the account's own default
applies. It applies only when the call creates a form: on
POST /forms/{id}/with-context the form already exists and keeps the setting it
was created with, so the field changes nothing there. See Ephemeral processing for the
window and what a 410 means once a form is swept.
Once a fill is complete, the submission package hands the filled form and its supporting attachments over as one file.