> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blinkpdf.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Fill a form from an MCP client

> inspect_form, validate_fill, and fill_form on the Blink PDF MCP server. Same bp_ key as render_pdf. fill_form spends 1 unit.

The Blink PDF [MCP server](/mcp/overview) exposes fill next to `render_pdf`. Do not rename `render_pdf`. Fill is a second verb: inspect names, map values, dry-run, then fill.

Same `bp_` key (or the same OAuth credential) as render. Do not mint a fill key. `fill_form` spends **1 unit**. `inspect_form` and `validate_fill` do not.

Published skill: [fill-form](https://mcp.blinkpdf.io/.well-known/agent-skills/fill-form/SKILL.md). Markdown → PDF remains [render-pdf](https://mcp.blinkpdf.io/.well-known/agent-skills/render-pdf/SKILL.md).

## Loop

```text theme={null}
inspect_form → map values to names → validate_fill → fill_form → signed /d/:token
```

Do not guess field names. Do not set `/NeedAppearances`. Do not claim a fill succeeded when the tool errored.

<Steps>
  <Step title="Stage or store the blank">
    A small PDF can go in `pdf` as Base64. A large form should use `upload_template` (same chunked path as `upload_image`) and pass the `blink://staged/…` handle as `pdf`. That handle is **not** a `templateId` and is **not** the account library.

    To fill the same blank many times, call `store_template` (`pdf` + `title`) and keep the returned `id`. `store_template` already returns `fields`.
  </Step>

  <Step title="Inspect">
    Call `inspect_form` with `pdf` (Base64 or `blink://staged`). Read `fields[].name` and `kind`. No unit. Does not store. MCP `inspect_form` and `validate_fill` do **not** accept `templateId` — for a stored blank, use the `fields` from `store_template` / `get_template`.
  </Step>

  <Step title="Map values">
    Build `{ "givenName": "Ada", "agree": true }` from those names. Omitted names stay unchanged. `false` is a value.
  </Step>

  <Step title="Validate">
    Call `validate_fill` with the same `pdf` (bytes or staged handle) and `values`. Read `written` and `missingRequired`, or fix named errors. No download. No unit. Does not accept `templateId` or `flatten`.
  </Step>

  <Step title="Fill">
    Call `fill_form` with `pdf` XOR `templateId` and `values`. It returns a signed `/d/:token` — never raw PDF bytes. **1 unit**. Appearances are written. Optional `flatten: true` stamps and strips widgets; default overlay keeps them. Optional `persist: true` keeps the file (MCP only; REST `POST /v1/fill` rejects `persist`).
  </Step>
</Steps>

The MCP server mints `x-idempotency-key` from the fill-body fingerprint (same seam as `render_pdf`). The agent does not invent a key. A retry of the same template and values does not spend a second unit. Changed values are a new fill.

## Tools

| Tool | REST | Unit | Notes |
| - | - | - | - |
| `inspect_form` | `POST /v1/inspect` | No | `pdf` is Base64 or `blink://staged`. Does not accept `templateId` or `values`. No store. |
| `validate_fill` | `POST /v1/validate-fill` | No | Same `pdf` + `values`. `{ written, missingRequired }` or a named error. Does not accept `templateId` or `flatten`. |
| `fill_form` | `POST /v1/fill` | **1** | `pdf` XOR `templateId` (`pdf` = bytes or `blink://staged`). Signed download URL. `persist` is MCP-only. |
| `upload_template` | — | No | Ephemeral `blink://staged/…` handle. Not `templateId`. Not the account store. |
| `store_template` | `POST /v1/templates` | No | Bytes + `title` → `id` + fields. |
| `list_templates` | `GET /v1/templates` | No | Blank library `{ id, title }`. Never mixed with `list_pdfs`. |
| `get_template` | `GET /v1/templates/{id}` | No | One id: title, `createdAt`, `byteSize`, `fieldCount`, `downloadUrl`, inspect cache. Does not page `list_templates`. |
| `update_template` | `PATCH /v1/templates/{id}` | No | Title and/or bytes on the **same** id. Inspect refreshes when bytes change. |
| `delete_template` | `DELETE /v1/templates/{id}` | No | Gone. A later `fill_form` by that id is not found. |

`list_pdfs`, `persist_pdf`, and `delete_pdf` apply to filled (and rendered) outputs the same way as after `render_pdf`. They are not the template library.

`inspect_form` / `validate_fill` / `fill_form` map REST `429` to the same `rate_limited` envelope as `render_pdf`.

<Note>
  REST `POST /v1/inspect`, `POST /v1/validate-fill`, and `POST /v1/fill` all accept `templateId` XOR `pdf`. On MCP, only `fill_form` takes `templateId`. Stage a one-off form with `upload_template`; keep a reusable blank with `store_template`.
</Note>

## After every fill

* Read `warnings` on the result. A too-long text field can still return a PDF and name `overflow.clipped`.
* The download URL expires in **24 hours** (`expiresAt`). Default storage is 24-hour ephemeral. `persist: true` or `persist_pdf` keeps the object; the **link** still expires in 24 hours — call `list_pdfs` for a fresh URL.
* Present the delivery receipt verbatim. Do not claim success when the tool errored.

Named errors match REST: unknown name, type mismatch, skipped name, NeedAppearances, encrypted PDF, XFA, signed template, unencodable appearance. One bad key fails the whole fill. See [Fill](/fill/fill#named-errors).

## REST vs MCP

| | REST | MCP |
| - | - | - |
| Fill output | PDF bytes on the response. Not stored. | Signed `/d/:token`. |
| `persist` | Rejected on `POST /v1/fill`. | `persist: true` on `fill_form`, or `persist_pdf`. |
| Template store | `/v1/templates` | `store_template` and friends |
| One-off large PDF | Multipart `pdf` | `upload_template` → `blink://staged` |

Connect a client with the same steps as [Connect a Client](/mcp/setup). The Cursor `mcp.json` (and Claude `.mcp.json`) is **one paste** with the same `bp_` key as `render_pdf` — the tool list includes `inspect_form` and `fill_form`. No extra OAuth step and no `pdf:fill` scope. Then ask: *"Inspect this form, fill givenName with Ada and agree with true, and give me the download link."*


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.