---
name: fill-form
description: "Fill an AcroForm by field name with BlinkPDF's hosted MCP server. Use when an agent must inspect a PDF, map values to those names, validate, and return signed filled-PDF links. fill_form takes items[] (N=1 is length 1); one unit per item filled, delivered or not. A retry of the same ordered batch does not bill twice. Same API key as render_pdf."
license: Proprietary
---

# Fill a PDF form by name with BlinkPDF

BlinkPDF fills an AcroForm by field name and returns a short-lived, signed
download URL. It is exposed to agents over the Model Context Protocol
(MCP); there are no inline PDF bytes to handle. Markdown→PDF is the
`render-pdf` skill — this skill is fill, not that verb.

## Connect

- MCP endpoint: `https://mcp.blinkpdf.io/mcp` (Streamable HTTP, stateless).
- Auth: send your BlinkPDF API key as a bearer token —
  `Authorization: Bearer bp_...` (or `x-api-key: bp_...`). Same key as
  `render_pdf`. A `401` means the key is wrong or revoked; fix the key, do
  not retry blindly.

## Loop

inspect_form → map values to names → validate_fill → fill_form → download.
Do not guess field names. Do not set NeedAppearances. Do not claim a fill succeeded when the tool errored.

1. Prefer a stored blank: `store_template` with an `upload_template`
   handle (or REST `POST /v1/templates`, each PDF a binary
   `items/<index>/pdf` part, or the dashboard) then `templateId`. Do not emit a
   multi-page clinical PDF as Base64 through the model. `upload_template`
   returns an ephemeral `blink://staged` handle — pass it as `pdf` on
   form tools. Not `templateId`. Not an account store. That handle does
   not work on `api.blinkpdf.io`.
2. Call `inspect_form` with `templateId` or `pdf`. Read the catalog
   `fields[].name`, `kind`, `fillable`, `label`, `page`. If
   `nextCursor` is set, call again with `cursor`. Complete widgets and
   appearances are REST `POST /v1/inspect`, not this tool. Do not guess
   field names. No unit.
3. Map values to those names (`{ "givenName": "Ada", "consent.agreed": false }`).
   Omitted names stay unchanged. `false` is a value.
4. Call `validate_fill` with the same `pdf` and an `items: [{ values,
   clientItemId? }]` batch. Read each indexed outcome: OK rows carry
   `written`, `missingRequired`, and `warnings` (the overlay advisories
   `fill_form` would return for that item, such as `overflow.clipped`);
   failed rows carry a code. Send every
   map for this source in one call. No download. No unit.
5. Call `fill_form` with the same `pdf` and a non-empty
   `items: [{ values, clientItemId? }]` array. Use one item for one fill;
   send many maps for the same source in one request rather than looping
   single-item fills. It returns a signed `/d/:token` for every delivered
   item and code/detail for failed items. Units equal the items REST filled:
   an item filled but not delivered (`storage_error`, …) is a failed row
   that keeps its unit and says whether it is `retryable`, beside the URLs
   of the items delivered. When `retryable` is true, retry the same request
   to deliver it (not billed again); otherwise follow its `detail`. A
   timeout retry of the same ordered batch does not spend units again. Do not
   invent an idempotency key. Appearances are written. Optional shared
   `flatten: true` stamps and strips every successful item; top-level
   `persist: true` keeps every successful delivery.
6. Present the delivery receipt verbatim. Do not claim a fill succeeded
   when the tool errored. Do not set NeedAppearances.

To fill the same blank form many times: `store_template` with `items[{pdf,title}]`
returns `id` and `revision`. Then `inspect_form({ templateId })` for the field
catalog and `fill_form` with `templateId` XOR `pdf`. `update_template` /
`delete_template` take `items` with `id` and `expectedRevision`.
`list_templates` lists the library (ids and revisions in the tool text);
`list_pdfs` lists filled/generated outputs.

Unknown names, type mismatches, skipped names, NeedAppearances, encrypted
PDFs, XFA, signed templates, and unencodable values fail that item by name;
successful siblings still return their signed URLs.

## 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 is signed and expires 24 hours after it is issued; read
  the exact instant from `structuredContent.expiresAt`. Default storage is
  24h ephemeral. Persistent files remain, but links still expire in 24h —
  call `list_pdfs` for a fresh URL.
- Reuse `persist_pdf`, `list_pdfs`, and `delete_pdf` the same way as after
  `render_pdf`.

## Billing

`fill_form` records one unit per item filled, delivered or not. A retry of the same
ordered batch does not spend units again. Do not invent an idempotency key.
Changed items are a new fill. `inspect_form` and `validate_fill` record
none. Free-tier fills may hit rate limits or return `402 spend_cap_reached`.
Upgrades are **human-in-the-loop**: the operator signs in on Blink PDF Platform
(`/login`) and upgrades on `/billing` — agents cannot open Stripe on their own.
API keys are created on `/api-keys`. Plan limits and billed verbs are published
as `agent_commerce` on `/.well-known/oauth-authorization-server` and
`/.well-known/blinkpdf-commerce.json`. See `https://mcp.blinkpdf.io/auth.md#billing`.
