> ## 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.

# Update a stored template

> Changes `title` and/or replaces `pdf` bytes on the same id. The cached inspect list refreshes when bytes change. Delete-then-store is not the update path. Rejects replacement bytes with no `/AcroForm`, `/NeedAppearances`, a password, XFA, or a document signature (`no_acroform`, `need_appearances` (`PdfNeedAppearancesUnsupportedError`), `encrypted_pdf` (`PdfEncryptionUnsupportedError`), `xfa_unsupported` (`PdfXfaUnsupportedError`), or `signed_pdf` (`PdfSignedPdfUnsupportedError`)). Replacement size is `maxTemplateBytes`, not render `bodyBytes`. Oversize replace is 413 `payload_too_large` naming `maxTemplateBytes`.



## OpenAPI

````yaml /openapi.json patch /v1/templates/{id}
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/templates/{id}:
    patch:
      tags:
        - Templates
      summary: Update a stored template
      description: >-
        Changes `title` and/or replaces `pdf` bytes on the same id. The cached
        inspect list refreshes when bytes change. Delete-then-store is not the
        update path. Rejects replacement bytes with no `/AcroForm`,
        `/NeedAppearances`, a password, XFA, or a document signature
        (`no_acroform`, `need_appearances`
        (`PdfNeedAppearancesUnsupportedError`), `encrypted_pdf`
        (`PdfEncryptionUnsupportedError`), `xfa_unsupported`
        (`PdfXfaUnsupportedError`), or `signed_pdf`
        (`PdfSignedPdfUnsupportedError`)). Replacement size is
        `maxTemplateBytes`, not render `bodyBytes`. Oversize replace is 413
        `payload_too_large` naming `maxTemplateBytes`.
      operationId: updateTemplate
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: Stored template id returned by store
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                pdf:
                  type: string
                  format: byte
                  description: >-
                    Replacement AcroForm PDF bytes, Base64-encoded. Refreshes
                    the cached inspect list.
                title:
                  type: string
                  description: Replacement title. Omit to keep the stored title.
          multipart/form-data:
            schema:
              type: object
              additionalProperties: false
              properties:
                pdf:
                  type: string
                  format: binary
                  description: >-
                    Replacement AcroForm PDF file part. Refreshes the cached
                    inspect list.
                title:
                  type: string
                  description: Replacement title. Omit to keep the stored title.
      responses:
        '200':
          description: Updated template on the same id
        '400':
          description: Empty patch, or invalid title or bytes
        '401':
          $ref: '#/components/responses/Responses.Unauthorized'
        '404':
          description: No template with that id for this account
        '413':
          $ref: '#/components/responses/Responses.PayloadTooLarge'
        '422':
          description: >-
            Replacement bytes rejected: `no_acroform`, `need_appearances`
            (`PdfNeedAppearancesUnsupportedError`), `encrypted_pdf`
            (`PdfEncryptionUnsupportedError`), `xfa_unsupported`
            (`PdfXfaUnsupportedError`), or `signed_pdf`
            (`PdfSignedPdfUnsupportedError`)
        '429':
          $ref: '#/components/responses/Responses.RateLimited'
        '503':
          description: Template store is temporarily unavailable. Retry shortly.
      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.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'
  schemas:
    Error.Unauthorized:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          enum:
            - unauthorized
    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
  examples:
    Error.Unauthorized:
      summary: Missing or invalid x-api-key (bp_*)
      value:
        error: unauthorized
    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.
  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.