# The submission package

Once a form's answers are committed, hand the whole submission over in one
file: the filled form, every attachment the form asked for in the order it
asked for them, and a receipt embedded inside the PDF itself.

## Attach a document before you commit

`POST /proposals/{proposal_id}/attachments` takes a multipart `file` and an
optional `for`, naming which of the form's `attachments_required` entries
this file satisfies.

```bash
curl -X POST https://api.getemboss.ai/proposals/3e714663-ff2c-45ac-ae11-3c7015facfef/attachments \
  -H "Authorization: Bearer sk_..." \
  -F "file=@./passport.pdf" \
  -F "for=Proof of identity"
```

```json
{ "n": 1, "for": "Proof of identity", "filename": "passport.pdf", "bytes": 182334, "sha256": "e3b0c...b855" }
```

Rules, all checked at upload so the commit itself never fails because of an
attachment:

- `for`, when given, must equal the `name` of one of the contract's
  `attachments_required` entries. Anything else: `400` `"unknown requirement: <for>"`.
- Only PDF, PNG or JPEG files are accepted, sniffed from the bytes, at the
  usual upload size limit. Anything else: `400` "attachment must be a PDF, PNG or JPEG".
- Up to 20 attachments per proposal, and 20 MB across all of them together.
  Either limit: `400` "attachment limit reached".
- Uploading the same `for` again replaces the earlier file.
- Attachments can only be added while the proposal is `proposed`. Once it is
  committed or has expired: `409`.

`DELETE /proposals/{proposal_id}/attachments/{n}` removes one by its number.

```bash
curl -X DELETE https://api.getemboss.ai/proposals/3e714663-ff2c-45ac-ae11-3c7015facfef/attachments/1 \
  -H "Authorization: Bearer sk_..."
```

`GET /proposals/{proposal_id}` lists what has been attached so far and which
requirements are already satisfied:

```json
{
  "attachments": [{ "n": 1, "for": "Proof of identity", "filename": "passport.pdf", "bytes": 182334, "sha256": "e3b0c...b855" }],
  "requirements": { "attachments": [{ "name": "Proof of identity", "source": "page 2", "satisfied": true }] }
}
```

## Build the package at commit

`POST /proposals/{proposal_id}/commit` takes an optional `"package": true` in
its JSON body (default `false`). When true, after the filled PDF renders,
Emboss assembles one package PDF:

1. The filled form, all pages.
2. The attachments whose `for` matches an `attachments_required` entry, in that requirement list's own order.
3. Any unlabelled attachments, in upload order.
4. Each image attachment becomes one page, scaled to fit the form's first
   page size and centred.
5. The receipt is embedded inside the package as a file attachment named
   `receipt.json`, so the package carries its own record without a second
   download.

A commit with `package: true` and no attachments still produces a package:
the form plus the embedded receipt, with every requirement listed as
outstanding.

```bash
curl -X POST https://api.getemboss.ai/proposals/3e714663-ff2c-45ac-ae11-3c7015facfef/commit \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"package": true}'
```

Once the commit job finishes, its status carries `package_url`. Unlike the
`pdf_url` and `receipt_url` API addresses, which need your key, it is a
download link on the website (`https://getemboss.ai/d/<token>`) that
needs no key and expires 24 hours after it is made. After that, fetch the
package by its `artifact_id` (its entry in the job's `artifacts` has role
`package`) at `GET /artifacts/{artifact_id}/content`.

```json
{ "job_id": "8c9d0e1f-2a3b-4c5d-9e6f-a1b2c3d4e5f6", "status": "processing" }
```

Once the job is `ready`, `package_url` sits alongside `receipt_url` and
`pdf_url` on the poll response.

## The receipt's outstanding list

The receipt's `requirements.attachments` becomes one entry per requirement:

```json
{ "name": "Proof of identity", "source": "page 2",
  "satisfied_by": { "n": 1, "bytes": 182334, "sha256": "e3b0c...b855" } }
```

`satisfied_by` is `null` when nothing was attached for that requirement. The
receipt's `unresolved` block is `{"fields": [...], "attachments": [...]}`:
the fields with their candidates, and the attachments still outstanding,
alongside the missing signatures, so an agent reads one list of everything
still standing between the person and a filing, values and attachments
together.

## Retention

Attachments and packages are documents, and they follow the same retention
rule as everything else Emboss stores: Ephemeral processing: source and output documents are deleted 60 to 70 minutes after the last activity on a form. Once a form is
swept, its package and attachment routes answer `410 Gone` with that same
sentence as the problem detail, exactly like the filled PDF and the fillable
copy. `DELETE /forms/{id}` removes them along with everything else on the
form. See [Security](/security) for the full list of what is kept and what
is deleted.

## Not on the one-call path

A one-call context fill has no proposal to attach a document to, so `package`
is not offered on that path: there is nowhere to call the attachments route
before the fill runs. Use [prepare and commit](/docs/prepare-commit-verify)
when a submission needs attachments or a package.

## On the pay-per-call API

On the [pay-per-call API](/docs/pay-per-call) the commit takes no payment, so
a package has to be bought at prepare: declare `package=true` on the prepare
call and the quote prices it in. A commit there asking for a package the quote
did not carry is refused with `400` "package was not quoted; prepare again with package=true".

## Pricing

A package is billed once per commit that produces one, as one `package` at
2¢, which is flat, any length. The first
5 each month are free, and the free page cap is read
off the form's own pages, not the package's. A second commit on the same
proposal with `package: true` produces, and bills, a second package. See
[Pricing](/pricing) for the full schedule.

## Also available as a tool

`add_attachment` on [MCP](/docs/mcp-tools) and the `attach` skill on
[A2A](/docs/a2a) take the same `proposal_id`, a file, and an optional `for`;
`commit_proposal` and the `commit` skill both take the same `package`
argument. See [Read a filled form back](/docs/read-filled-form) for the
matching read-side call, and [pricing](/pricing) for the free tier.

Once a submission is filed, [batch fill](/docs/batch-fill) is the pattern to
reach for when the same form has to be filled, and packaged, many times over.

## See also

- [Pre-fill forms from context documents](https://getemboss.ai/use-cases/prefill-from-context)
- [Fillable PDF](https://getemboss.ai/glossary/fillable-pdf)
- [Batch fill](https://getemboss.ai/docs/batch-fill)
- [Read a filled form and the submission package](https://getemboss.ai/docs/reference/read-and-package)
