# Fill with context

Fill a form from supporting context documents. By default, fill a form you've already created (POST /forms/{form_id}/with-context); or upload a brand-new flat PDF to extract and fill it in one call (POST /forms/with-context). Both run asynchronously: poll the job, then download the resulting session's PDF.

## Fill an existing form with context

```
POST /forms/{form_id}/with-context
```

Authentication: Bearer API key required.

Fill a form you've already created, from one or more context files. Returns 202 with a job id; bills one context fill.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| form_id | path | string | yes | The id of a form you've already created (status ready). |
| context | body | file (multipart, repeatable) | no | Supporting document(s) to infer values from. |
| policy | body | string | no | Optional. safe (the default) writes high- and medium-confidence values; strict writes only high-confidence ones and leaves the rest for you to confirm. Anything else is 400. |
| Idempotency-Key | header | string | no | Optional. Retrying with the same key answers 200 with the original job instead of starting a new one. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. A request that is rejected (any 4xx) does not consume the key: fix the cause and retry with the same key. |
| callback_url | body | string (url) | no | Optional. A public https URL Emboss POSTs the result to when the job finishes (ready or failed), signed with X-Emboss-Signature using your account's callback signing secret (shown on the API Keys page of the dashboard). See the Callbacks guide. Private or non-https URLs are rejected with 400. |
| retention | body | string | no | Optional. ephemeral or account_default; default account_default. See the Ephemeral processing guide. |

```curl
curl -X POST https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/with-context \
  -H "Authorization: Bearer sk_..." \
  -F "context=@./profile.pdf"
```

```js
const body = new FormData();
body.append("context", profileBlob, "profile.pdf");

const res = await fetch("https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/with-context", {
  method: "POST",
  headers: { Authorization: "Bearer sk_..." },
  body,
});
const { job_id, status } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/with-context",
    headers={"Authorization": "Bearer sk_..."},
    files=[
        ("context", open("profile.pdf", "rb")),
    ],
)
job = res.json()  # {"job_id": ..., "status": "processing"}
```

### Response

```json
{
  "job_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "processing"
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 202 | Accepted; fill job started. |
| 400 | policy is not safe or strict. |
| 401 | Missing or invalid API key. |
| 402 | No payment method on file and either the monthly free allowance is used up or the request is over the free tier's 5-page cap. The body's detail carries code (over_free_tier or over_page_cap), message and billing_url, the page where a payment method can be added. |
| 404 | No such form, or owned by another key. |
| 409 | Form not ready. |
| 410 | The form's documents have been deleted under its retention policy. |
| 413 | Too many context files (max 5), file too large (max 10 MB), or request over 30 MB. |
| 422 | document_same_as_form: a context file is this form's own original, with nothing typed, ticked or chosen in it. The body's detail carries code, message and document_index (the refused file's position among the context files, from 0); nothing is charged. |
| 429 | Rate limit exceeded. |

## Fill with context

```
POST /forms/with-context
```

Authentication: Bearer API key required.

Submit a PDF plus one or more context files. Returns 202 with a job id; detection and fill run in the background.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| file | body | file (multipart) | no | The flat PDF. Send this or library: one of the two is required. |
| context | body | file (multipart, repeatable) | no | Supporting document(s) Emboss reads to infer field values. Repeat for multiple files. |
| policy | body | string | no | Optional. safe (the default) writes high- and medium-confidence values; strict writes only high-confidence ones and leaves the rest for you to confirm. Anything else is 400. |
| Idempotency-Key | header | string | no | Optional. Retrying with the same key answers 200 with the original job instead of starting a new one. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. A request that is rejected (any 4xx) does not consume the key: fix the cause and retry with the same key. |
| callback_url | body | string (url) | no | Optional. A public https URL Emboss POSTs the result to when the job finishes (ready or failed), signed with X-Emboss-Signature using your account's callback signing secret (shown on the API Keys page of the dashboard). See the Callbacks guide. Private or non-https URLs are rejected with 400. |
| retention | body | string | no | Optional. ephemeral or account_default; default account_default. See the Ephemeral processing guide. |
| library | body | string | no | Optional. Fill a form already in the library instead of uploading a file: the slug of one of the entries at GET /library. Mutually exclusive with file; sending both is 400. |

```curl
curl -X POST https://api.getemboss.ai/forms/with-context \
  -H "Authorization: Bearer sk_..." \
  -F "file=@./w9.pdf" \
  -F "context=@./profile.pdf"
```

```js
const body = new FormData();
body.append("file", fileBlob, "w9.pdf");
body.append("context", profileBlob, "profile.pdf");

const res = await fetch("https://api.getemboss.ai/forms/with-context", {
  method: "POST",
  headers: { Authorization: "Bearer sk_..." },
  body,
});
const { job_id, status } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/forms/with-context",
    headers={"Authorization": "Bearer sk_..."},
    files=[
        ("file", open("w9.pdf", "rb")),
        ("context", open("profile.pdf", "rb")),
    ],
)
job = res.json()  # {"job_id": ..., "status": "processing"}
```

### Response

```json
{
  "job_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "processing"
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 202 | Accepted; fill job started. |
| 400 | Missing file and library: "field required: file"; unreadable PDF; both file and library: "send a file or a library slug, not both"; "invalid callback_url"; a bad retention value; or policy is not safe or strict. |
| 401 | Missing or invalid API key. |
| 402 | No payment method on file and either the monthly free allowance is used up or the request is over the free tier's 5-page cap. The body's detail carries code (over_free_tier or over_page_cap), message and billing_url, the page where a payment method can be added. |
| 404 | The library slug does not match any library form: "no library form named <slug>". |
| 413 | Too many context files (max 5), file too large (max 10 MB), or request over 30 MB. |
| 422 | document_same_as_form: a context file is the uploaded form itself, with nothing typed, ticked or chosen in it. The body's detail carries code, message and document_index (the refused file's position among the context files, from 0); nothing is charged. Also pdf_unsafe: the PDF's form fields are built in a way that could compromise the service, so it is refused before any price, charge or stored file. The body's detail carries code and message ("Emboss does not process PDF files that could compromise the service."). |
| 429 | Rate limit exceeded. |
| 503 | The library form's stored copy could not be read: "library copy unavailable"; retry. |

## Get the fill job

```
GET /forms/with-context/{job_id}
```

Authentication: Bearer API key required.

Poll the fill job. When complete, returns the session_id; on failure, error is an object { code, message }: a stable code plus a human-readable message. Codes: context_too_large, unsupported_context_file, context_fill_failed, apply_rejected, form_processing_failed, commit_failed (writing or checking the PDF broke), interrupted (a restart cut the job off; submit it again), reading_failed (pay-per-call only), job_failed (fallback). A ready job whose report.warnings holds no_values_found wrote nothing; report.message says why, and on an account the fill is not counted against the plan.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| job_id | path | string | yes | The job_id returned by POST /forms/with-context. |

```curl
curl https://api.getemboss.ai/forms/with-context/6c47f7f5-f921-4698-910f-95dd7d81310b \
  -H "Authorization: Bearer sk_..."
```

```js
const res = await fetch("https://api.getemboss.ai/forms/with-context/6c47f7f5-f921-4698-910f-95dd7d81310b", {
  headers: { Authorization: "Bearer sk_..." },
});
const { status, session_id, error } = await res.json();
```

```python
import requests

res = requests.get(
    "https://api.getemboss.ai/forms/with-context/6c47f7f5-f921-4698-910f-95dd7d81310b",
    headers={"Authorization": "Bearer sk_..."},
)
job = res.json()  # {"job_id": ..., "status": "processing" | "ready" | "failed"}
```

### Response

```json
{
  "job_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "form_id": "0b5a9e7c-3d2f-4e1a-9c8b-7d6e5f4a3b2c",
  "status": "ready",
  "session_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "error": null
}

// On failure, status is "failed" and error is { code, message }:
{
  "job_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "failed",
  "session_id": null,
  "error": { "code": "context_too_large", "message": "context too large: 512000 > 500000 tokens" }
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The job state (processing \| ready \| failed). |
| 401 | Missing or invalid API key. |
| 404 | No such job, or owned by another key. |

## Preview a fill

```
POST /forms/{form_id}/preview-fill
```

Authentication: Bearer API key required.

Try filling a form's fields from documents without rendering a PDF or saving anything, for a live preview while a person adds documents. Returns candidate values with a confidence, values that would change a locked field, and topics still missing. Not billed.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| form_id | path | string | yes | A ready form. |
| context | body | file (multipart, repeatable) | no | Supporting document(s) to read. |
| locked | body | string (JSON object) | no | Optional. Values the person already settled, as {field_id: value}; the preview never overwrites them. Not a JSON object is 400. |
| asked_field_ids | body | string (JSON array) | no | Optional. Field ids already asked about, so they are not suggested again. |

```curl
curl -X POST https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/preview-fill \
  -H "Authorization: Bearer sk_..." \
  -F "context=@./profile.pdf"
```

```js
const body = new FormData();
body.append("context", profileBlob, "profile.pdf");

const res = await fetch("https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/preview-fill", {
  method: "POST",
  headers: { Authorization: "Bearer sk_..." },
  body,
});
const preview = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/preview-fill",
    headers={"Authorization": "Bearer sk_..."},
    files={"context": open("profile.pdf", "rb")},
)
preview = res.json()
```

### Response

```json
{
  "filled": [
    { "id": 1, "label": "Full Name", "value": "Grace Hopper", "confidence": "high" },
    { "id": 2, "label": "Date of Birth", "value": "1906-12-09", "confidence": "low" }
  ],
  "changed": [],
  "directive": "review",
  "gap_topics": [],
  "photo_notes": []
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The preview. |
| 400 | locked is not a JSON object of {field_id: value}. |
| 401 | Missing or invalid API key. |
| 404 | No such form, or owned by another key. |
| 409 | Contract not available: detection not ready. |

## See also

- [Quickstart](https://getemboss.ai/docs/quickstart)
- [Pre-fill forms from context documents](https://getemboss.ai/use-cases/prefill-from-context)
