> ## 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 an AcroForm by name

> JSON Base64 `pdf` plus a `values` map and optional `flatten`, or multipart field `pdf` plus a `values` JSON object (same shape). Or `templateId` XOR `pdf` for a stored blank template (same store as `GET /v1/templates/:id`). Inspect and validate-fill accept the same XOR. Same `x-api-key` as render. Returns a filled PDF with written appearances. Streams the PDF on the response and does not keep the output. Does not accept `persist`. Preview and print show the values without a viewer repair pass. Omit `flatten` or set it false. Widgets stay interactive with written `/AP`. `flatten: true` stamps appearances and strips the form. Not the default. Password fields still do not flatten in the clear. Never `/NeedAppearances`. Overlay advisories (`overflow.clipped`, `overflow.autosized`, `font.substituted`, `widget.tiny`) ride `X-Fill-Warnings` (base64url JSON). Always present. Empty when every appearance fit. The PDF still returns. Silent clip is not a 200 with no note. A successful fill records one unit. Inspect and validate-fill do not. A caller at the hard cap receives the same 402 `spend_cap_reached` as `POST /v1/render`. Optional `x-idempotency-key` retries the same body without a second unit. Reusing the key with a different `values` object or `flatten` returns 409 `idempotency_conflict`. Request/response only: no job id and no poll. Fill-by-bytes (JSON or multipart `pdf`) uses the plan `bodyBytes` ceiling (oversize is 413 `payload_too_large`). A `templateId` fill does not re-check stored PDF bytes against `bodyBytes`. Produce must finish within 120 seconds; an overrun or aborted produce is 504 `service_unavailable`. Inspect and validate-fill spend no unit; they still sit on plan `ratePerMin` and `concurrency`. A successful fill sets `Content-Disposition` to `{PDF /Title or form}-filled.pdf`. Title-less templates download as `form-filled.pdf`. Safe ASCII `filename=`. Optional RFC 5987 `filename*` when `/Title` is not ASCII. Not `download`. Not a uuid. The client does not send a `filename` field. Inspect and validate-fill stay JSON. `values` keys are ISO fully qualified names (or the unique `/T` when there is only one). Omitted names stay unchanged. `false` is a value. Unknown names are `unknown_field_name` with close-match suggestions. A type mismatch is `type_mismatch`. A skipped import name is `skipped_field_name`. Fill injects the hosted appearance face. The client does not send a TTF or a `font` field. A value that face cannot encode is `appearance_unencodable` (`PdfPreserveFieldAppearanceError`). One bad key fails the whole request. An empty required field is not a 400. A template with `/NeedAppearances` is rejected as `need_appearances` (`PdfNeedAppearancesUnsupportedError`). Password, XFA, and signed or certified templates are rejected as `encrypted_pdf` (`PdfEncryptionUnsupportedError`), `xfa_unsupported` (`PdfXfaUnsupportedError`), or {SIGNED_REJECT}. Fill is not a second verb on `POST /v1/render`.



## OpenAPI

````yaml /openapi.json post /v1/fill
openapi: 3.1.0
info:
  title: Blink PDF API
  description: >-
    Render Markdown into accessible, PDF/UA-conformant PDFs over HTTP. Send
    Markdown plus optional document metadata, fonts, page layout, viewer hints,
    and per-block style overrides to `POST /v1/render`, or use a structured
    template such as `POST /v1/templates/sandwich-document/render`. Fill by name
    is a separate verb: template (PDF bytes or stored id) plus `{ name: value }`
    returns a filled PDF. Inspect the field list at `POST /v1/inspect`, dry-run
    at `POST /v1/validate-fill`, and fill at `POST /v1/fill`. `POST /v1/fill`
    streams the PDF and does not keep the output. Stored templates live at
    `/v1/templates` (store, get, list, update, delete, download). Names are ISO
    fully qualified names, or the unique `/T` when there is only one. Omitted
    names stay unchanged. `false` is a value. Unknown names reject the request.
    The filled PDF never includes `/NeedAppearances`. A PDF with no widgets
    inspects to `fields: []` plus reason `no_widgets`; make it a form in studio
    first. Fill is request/response: plan `bodyBytes` and a 120 second produce
    ceiling. No job id. Fill is not a second verb on `POST /v1/render`.
    Authentication is via an `x-api-key` header. Unknown routes return HTTP 404
    with body `{ "error": "not_found" }`.
  version: 1.5.0
  contact:
    name: Blink PDF Support
    email: support@blinkpdf.io
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
  - url: https://api.blinkpdf.io
    description: Production
security: []
tags:
  - name: Discovery
    description: Machine-readable API entry point
  - name: Health
    description: Liveness probes
  - name: Render
    description: Markdown-to-PDF rendering
  - name: Fonts
    description: Hosted font catalog and Google Fonts capability discovery
  - name: SandwichDocument
    description: >-
      Sandwich documents — a first-page header (logo, professional identity,
      subject/context data) and a last-page footer (signature, name) wrapping a
      Markdown body
  - name: Fill
    description: Fill an AcroForm by name
  - name: Templates
    description: Stored AcroForm template library
paths:
  /v1/fill:
    post:
      tags:
        - Fill
      summary: Fill an AcroForm by name
      description: >-
        JSON Base64 `pdf` plus a `values` map and optional `flatten`, or
        multipart field `pdf` plus a `values` JSON object (same shape). Or
        `templateId` XOR `pdf` for a stored blank template (same store as `GET
        /v1/templates/:id`). Inspect and validate-fill accept the same XOR. Same
        `x-api-key` as render. Returns a filled PDF with written appearances.
        Streams the PDF on the response and does not keep the output. Does not
        accept `persist`. Preview and print show the values without a viewer
        repair pass. Omit `flatten` or set it false. Widgets stay interactive
        with written `/AP`. `flatten: true` stamps appearances and strips the
        form. Not the default. Password fields still do not flatten in the
        clear. Never `/NeedAppearances`. Overlay advisories (`overflow.clipped`,
        `overflow.autosized`, `font.substituted`, `widget.tiny`) ride
        `X-Fill-Warnings` (base64url JSON). Always present. Empty when every
        appearance fit. The PDF still returns. Silent clip is not a 200 with no
        note. A successful fill records one unit. Inspect and validate-fill do
        not. A caller at the hard cap receives the same 402 `spend_cap_reached`
        as `POST /v1/render`. Optional `x-idempotency-key` retries the same body
        without a second unit. Reusing the key with a different `values` object
        or `flatten` returns 409 `idempotency_conflict`. Request/response only:
        no job id and no poll. Fill-by-bytes (JSON or multipart `pdf`) uses the
        plan `bodyBytes` ceiling (oversize is 413 `payload_too_large`). A
        `templateId` fill does not re-check stored PDF bytes against
        `bodyBytes`. Produce must finish within 120 seconds; an overrun or
        aborted produce is 504 `service_unavailable`. Inspect and validate-fill
        spend no unit; they still sit on plan `ratePerMin` and `concurrency`. A
        successful fill sets `Content-Disposition` to `{PDF /Title or
        form}-filled.pdf`. Title-less templates download as `form-filled.pdf`.
        Safe ASCII `filename=`. Optional RFC 5987 `filename*` when `/Title` is
        not ASCII. Not `download`. Not a uuid. The client does not send a
        `filename` field. Inspect and validate-fill stay JSON. `values` keys are
        ISO fully qualified names (or the unique `/T` when there is only one).
        Omitted names stay unchanged. `false` is a value. Unknown names are
        `unknown_field_name` with close-match suggestions. A type mismatch is
        `type_mismatch`. A skipped import name is `skipped_field_name`. Fill
        injects the hosted appearance face. The client does not send a TTF or a
        `font` field. A value that face cannot encode is
        `appearance_unencodable` (`PdfPreserveFieldAppearanceError`). One bad
        key fails the whole request. An empty required field is not a 400. A
        template with `/NeedAppearances` is rejected as `need_appearances`
        (`PdfNeedAppearancesUnsupportedError`). Password, XFA, and signed or
        certified templates are rejected as `encrypted_pdf`
        (`PdfEncryptionUnsupportedError`), `xfa_unsupported`
        (`PdfXfaUnsupportedError`), or {SIGNED_REJECT}. Fill is not a second
        verb on `POST /v1/render`.
      operationId: fillForm
      parameters:
        - name: x-idempotency-key
          in: header
          required: false
          schema:
            type: string
          description: >-
            Optional client-supplied idempotency token. When present, usage
            metering deduplicates on (key, user_id) so retries with the same
            body do not double-count. Reusing the key with a different request
            body returns 409 `idempotency_conflict` (no PDF, no usage headers).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - values
              additionalProperties: false
              properties:
                pdf:
                  type: string
                  format: byte
                  description: >-
                    AcroForm PDF bytes, Base64-encoded. Does not store the PDF.
                    XOR with `templateId`.
                templateId:
                  type: string
                  description: >-
                    Stored template id from `POST /v1/templates`. XOR with
                    `pdf`. Same store as `GET /v1/templates/:id`. Unknown,
                    deleted, or foreign is 404.
                values:
                  type: object
                  additionalProperties: true
                  description: >-
                    Fill-by-name map. Keys are inspect names. Tx and Ch are
                    strings, checkbox is boolean, radio is string or null.
                    Omitted names stay unchanged. `false` is a value.
                flatten:
                  type: boolean
                  description: >-
                    Omit `flatten` or set it false. Widgets stay interactive
                    with written `/AP`. `flatten: true` stamps appearances and
                    strips the form. Not the default. Password fields still do
                    not flatten in the clear.
            examples:
              byBytes:
                summary: Synthetic intake by bytes
                value:
                  pdf: <Base64>
                  values:
                    givenName: Ada
                    agree: true
              byTemplateId:
                summary: Stored template id
                value:
                  templateId: <id>
                  values:
                    givenName: Ada
                    agree: true
          multipart/form-data:
            schema:
              type: object
              required:
                - values
              additionalProperties: false
              properties:
                pdf:
                  type: string
                  format: binary
                  description: >-
                    AcroForm PDF file part. Does not store the PDF. XOR with
                    `templateId`.
                templateId:
                  type: string
                  description: >-
                    Stored template id from `POST /v1/templates`. XOR with
                    `pdf`. Same store as `GET /v1/templates/:id`. Unknown,
                    deleted, or foreign is 404.
                values:
                  type: object
                  additionalProperties: true
                  description: >-
                    Fill-by-name map. Keys are inspect names. Tx and Ch are
                    strings, checkbox is boolean, radio is string or null.
                    Omitted names stay unchanged. `false` is a value.
                flatten:
                  type: boolean
                  description: >-
                    Omit `flatten` or set it false. Widgets stay interactive
                    with written `/AP`. `flatten: true` stamps appearances and
                    strips the form. Not the default. Password fields still do
                    not flatten in the clear.
      responses:
        '200':
          description: >-
            Filled PDF. Appearances are written. Preview and print show the
            values. Streams the bytes and does not keep the output. Default
            keeps `/AcroForm` and widgets. `flatten: true` stamps appearances,
            strips widgets, and still shows the values. Overlay warnings ride
            `X-Fill-Warnings` (empty when every appearance fit).
            `Content-Disposition` is `{PDF /Title or form}-filled.pdf`. Records
            one unit
          headers:
            X-Fill-Warnings:
              schema:
                type: string
              description: >-
                Base64url-encoded UTF-8 JSON array of overlay advisories
                (`code`, `fieldName`). Codes: `overflow.clipped`,
                `overflow.autosized`, `font.substituted`, `widget.tiny`. Always
                present on 200. Empty when every appearance fit. Never includes
                field values. The PDF still returns.
            X-Fill-Warnings-Summary:
              schema:
                type: string
              description: >-
                Plain-text companion to `X-Fill-Warnings`: the advisory count
                and distinct codes. Present when the list is non-empty.
            X-Fill-Warnings-Truncated:
              schema:
                type: string
                enum:
                  - 'true'
              description: >-
                Present when the overlay-advisory JSON was capped to fit header
                size limits.
            Content-Disposition:
              schema:
                type: string
              description: >-
                A successful fill sets `Content-Disposition` to `{PDF /Title or
                form}-filled.pdf`. Title-less templates download as
                `form-filled.pdf`. Safe ASCII `filename=`. Optional RFC 5987
                `filename*` when `/Title` is not ASCII. Not `download`. Not a
                uuid. The client does not send a `filename` field. Inspect and
                validate-fill stay JSON.
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        '400':
          description: >-
            Caller-value fault: `unknown_field_name`, `type_mismatch`,
            `skipped_field_name`, or `appearance_unencodable`. Or missing or
            invalid template bytes or values
        '401':
          $ref: '#/components/responses/Responses.Unauthorized'
        '402':
          $ref: '#/components/responses/Responses.SpendCapReached'
        '404':
          description: No stored template with that `templateId` for this account
        '409':
          $ref: '#/components/responses/Responses.IdempotencyConflict'
        '413':
          $ref: '#/components/responses/Responses.PayloadTooLarge'
        '422':
          description: >-
            Template rejected: `no_acroform`, `need_appearances`
            (`PdfNeedAppearancesUnsupportedError`), `encrypted_pdf`
            (`PdfEncryptionUnsupportedError`), `xfa_unsupported`
            (`PdfXfaUnsupportedError`), or `signed_pdf`
            (`PdfSignedPdfUnsupportedError`)
        '429':
          $ref: '#/components/responses/Responses.RateLimited'
        '503':
          $ref: '#/components/responses/Responses.ServiceUnavailable'
        '504':
          $ref: '#/components/responses/Responses.GatewayTimeout'
      security:
        - apiKey: []
components:
  responses:
    Responses.Unauthorized:
      description: >-
        Missing or invalid `x-api-key` (must be a valid, enabled `bp_*` key;
        documentation endpoints and health are exempt)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error.Unauthorized'
          examples:
            unauthorized:
              $ref: '#/components/examples/Error.Unauthorized'
    Responses.SpendCapReached:
      description: >-
        A plan unit allowance has been reached (`spend_cap_reached` — spend cap
        for paid; free calendar 250 units monthly). Fill and render share that
        allowance. Detail in body names the exhausted limit. Response may carry
        `X-BlinkPDF-Usage-*` headers.
      headers:
        X-BlinkPDF-Usage-PDFs-This-Period:
          schema:
            type: integer
            minimum: 0
          description: Current unit usage in the active billing period.
        X-BlinkPDF-Usage-Included:
          schema:
            type: integer
            minimum: 0
          description: The plan's included unit volume for the period.
        X-BlinkPDF-Period-Start:
          schema:
            type: string
            format: date-time
          description: ISO-8601 anchor (anniversary for paid, calendar month for free).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error.SpendCapReached'
          examples:
            spendCapReached:
              $ref: '#/components/examples/Error.SpendCapReached'
    Responses.IdempotencyConflict:
      description: >-
        The supplied idempotency key was already used with a different request
        body.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error.IdempotencyConflict'
          examples:
            idempotencyConflict:
              $ref: '#/components/examples/Error.IdempotencyConflict'
    Responses.PayloadTooLarge:
      description: >-
        Serialized JSON request body exceeds the caller's plan tier limit
        (`getTechnicalLimits`: free 128 KiB, pro 2 MiB, business 5 MiB).
        Enforcement uses the UTF-8 byte length of `JSON.stringify(body)` after
        parse, so a missing or incorrect `Content-Length` header cannot bypass
        the cap.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error.PayloadTooLarge'
          examples:
            payloadTooLarge:
              $ref: '#/components/examples/Error.PayloadTooLarge'
    Responses.RateLimited:
      description: >-
        Rate or concurrency limit exceeded (post-auth per-tier limits from
        `getTechnicalLimits`: free 10/min + 1 concurrent, pro 120/min + 10
        concurrent, business 600/min + 40 concurrent; a high pre-auth per-IP
        flood shield also exists but is sized above every plan rate and never
        binds first for plan traffic). Post-auth tier rate and concurrency
        blocks both return `error: rate_limited` but use different `detail`
        strings; audit rows distinguish `rate_limited` vs `concurrency_limited`.
        Tier-specific responses may include upgrade guidance in `detail`. The
        response carries `Retry-After` and defensive security headers.
      headers:
        Retry-After:
          schema:
            minimum: 1
            type: integer
          description: Seconds remaining until the rate-limit window resets. Always >= 1.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error.RateLimited'
          examples:
            rateLimited:
              $ref: '#/components/examples/Error.RateLimited'
    Responses.ServiceUnavailable:
      description: >-
        Transient outage: a subscription tier lookup failed
        (`service_unavailable`, fail-closed) or the font catalogue could not be
        read (`font_source_unavailable`). Retry shortly.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error.ServiceUnavailable'
          examples:
            serviceUnavailable:
              $ref: '#/components/examples/Error.ServiceUnavailable'
    Responses.GatewayTimeout:
      description: >-
        Produce exceeded the 120 second ceiling, or produce was aborted. Same
        `service_unavailable` family as a render 503. Retry-safe with
        `x-idempotency-key`. No job id and no poll.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error.ServiceUnavailable'
  schemas:
    Error.Unauthorized:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          enum:
            - unauthorized
    Error.SpendCapReached:
      type: object
      required:
        - error
      description: >-
        Returned when paid plan access is required: a plan volume limit was
        reached (`spend_cap_reached` — spend cap for paid; calendar monthly 250
        render units for free). The detail names the exhausted limit.
      properties:
        error:
          type: string
          enum:
            - spend_cap_reached
        detail:
          type: string
    Error.IdempotencyConflict:
      type: object
      required:
        - error
      description: >-
        Returned when an idempotency key is reused with a different render
        request.
      properties:
        error:
          type: string
          enum:
            - idempotency_conflict
        detail:
          type: string
    Error.PayloadTooLarge:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          enum:
            - payload_too_large
    Error.RateLimited:
      type: object
      required:
        - error
      description: >-
        Post-auth tier rate exhaustion and post-auth concurrency exhaustion both
        use `error: rate_limited`; distinguish them by `detail` (tier rate vs
        concurrency/plan copy). Render audit rows use separate `status` values
        (`rate_limited` vs `concurrency_limited`).
      properties:
        error:
          type: string
          enum:
            - rate_limited
        detail:
          type: string
    Error.ServiceUnavailable:
      type: object
      required:
        - error
      description: >-
        Transient outage shared by every 503. `font_source_unavailable` is a
        font catalogue read failure (`POST /v1/render`, `GET /v1/fonts`);
        `service_unavailable` is a subscription tier-lookup failure, fail-closed
        (`GET /v1/fonts`). Both are retryable. Each route documents which codes
        it can emit.
      properties:
        error:
          type: string
          enum:
            - service_unavailable
            - font_source_unavailable
        detail:
          type: string
  examples:
    Error.Unauthorized:
      summary: Missing or invalid x-api-key (bp_*)
      value:
        error: unauthorized
    Error.SpendCapReached:
      summary: Plan monthly spend cap reached
      value:
        error: spend_cap_reached
        detail: >-
          The monthly spend cap for this plan has been reached. Usage that
          exceeds the included volume is paused until the next billing period.
          Raise the spend cap or upgrade the plan to continue.
    Error.IdempotencyConflict:
      summary: Idempotency key reused with a different request
      value:
        error: idempotency_conflict
        detail: The idempotency key was already used with a different render request.
    Error.PayloadTooLarge:
      summary: Request body exceeds the configured cap
      value:
        error: payload_too_large
    Error.RateLimited:
      summary: >-
        Per-tier rate limit exceeded (concurrency exhaustion uses the same error
        code with a different detail string)
      value:
        error: rate_limited
        detail: >-
          Tier rate limit exceeded. Retry after the Retry-After interval or
          upgrade for higher sustained throughput.
    Error.ServiceUnavailable:
      summary: Transient tier-lookup or font-catalogue outage
      value:
        error: service_unavailable
        detail: >-
          Subscription tier lookup is temporarily unavailable. Retry the
          request.
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        API key issued from your Blink PDF account, prefixed `bp_`. Send it in
        the `x-api-key` header on every request. The documentation and health
        endpoints are exempt.

````

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