# 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](/docs/fill-from-data)): it's deterministic and skips the
inference step.

## Fill an existing form

If you've already created a form (see the [Quickstart](/docs/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`.

```bash
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"
```

```json
{ "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](#poll-for-the-result)
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.

```bash
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](/docs/prepare-commit-verify): 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.

```bash
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"
```

```json
{ "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:

```bash
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.

```json
{
  "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:

```json
{
  "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:

```json
{
  "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:

```json
{
  "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](/docs/prepare-commit-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

```bash
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](/docs/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](/docs/ephemeral-processing) for the
window and what a 410 means once a form is swept.

Once a fill is complete, [the submission package](/docs/submission-package)
hands the filled form and its supporting attachments over as one file.

## See also

- [Pre-fill forms from context documents](https://getemboss.ai/use-cases/prefill-from-context)
- [OCR for forms](https://getemboss.ai/glossary/ocr-for-forms)
- [Prepare, commit and verify](https://getemboss.ai/docs/prepare-commit-verify)
- [Use Emboss in Claude](https://getemboss.ai/docs/claude)
- [Prepare, commit and verify](https://getemboss.ai/docs/prepare-commit-verify)
- [Ephemeral processing](https://getemboss.ai/docs/ephemeral-processing)
- [The submission package](https://getemboss.ai/docs/submission-package)
- [Fill with context](https://getemboss.ai/docs/reference/fill-with-context)
- [Prepare and verify](https://getemboss.ai/docs/reference/prepare-and-verify)
- [Fill PDF forms in n8n workflows](https://getemboss.ai/integrations/n8n)
- [Fill PDF forms in Zapier workflows](https://getemboss.ai/integrations/zapier)
