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

# Document Options: Page Size, Margins & Metadata

> Configure page size, orientation, margins, optional full-sheet background, and PDF metadata for every document you render with Blink PDF — all through a single JSON request.

Every PDF you render with Blink PDF is controlled entirely through the JSON body of a `POST /v1/render` request. There is no CSS to write and no HTML to maintain — you describe the document you want and the API handles the rest. This page covers the core document-level options: the required `markdown` field, the `title` alias, the `metadata` object for PDF properties, the `page` object that controls page size, orientation, margins, and optional sheet background, and the `viewer` object for language and viewer hints.

<Note>
  The fields below are validated against the live API schema. The **API Reference → Render** endpoint is generated directly from the server's OpenAPI contract and is always the authoritative source for every field and constraint.
</Note>

## The `markdown` Field

The `markdown` field is the only required field in every request. It contains the full Markdown source for your document. Blink PDF renders it into a professional PDF in approximately 100 ms.

<ParamField body="markdown" type="string" required>
  The Markdown source of the document to render. Supports standard CommonMark syntax including headings, lists, tables, code blocks, and inline formatting. This is the only required field in the request body.
</ParamField>

## The `title` Field

`title` is a top-level convenience alias for [`metadata.title`](#the-metadata-object). When you set only the document title, `title` is shorter than nesting it under `metadata`.

<ParamField body="title" type="string">
  Convenience alias for `metadata.title`. When both `title` and `metadata.title` are present, `metadata.title` wins. When neither is set, the title defaults to the first Markdown heading.
</ParamField>

## The `theme` Field

<ParamField body="theme" type="string" default="report-clean">
  A curated design preset — one of 15 slugs — resolved to a bundle of typography, page, furniture, numbering, and rules, then merged **under** your own settings (your values win per field). Omitting the field applies `report-clean` (the plain engine default). See [Themes](/configuration/themes) for the full catalog.
</ParamField>

## The `metadata` Object

The `metadata` object sets the document properties that are embedded inside the PDF file itself. These properties appear in PDF viewers under "Document Properties" and are indexed by search engines and document management systems. They also form the basis of Blink PDF's PDF/UA-1 accessible output.

<ParamField body="metadata" type="object">
  An optional object containing PDF document metadata. None of the nested fields are individually required.

  <Expandable title="metadata fields">
    <ParamField body="metadata.title" type="string">
      The document title embedded in the PDF. Appears in the title bar of most PDF viewers and is used by screen readers as the document's accessible name.
    </ParamField>

    <ParamField body="metadata.author" type="string">
      The name of the document's author or the organization that produced it.
    </ParamField>

    <ParamField body="metadata.subject" type="string">
      A short description of the document's subject. Equivalent to the "Subject" field in standard PDF metadata.
    </ParamField>

    <ParamField body="metadata.keywords" type="string[]">
      An array of keyword strings describing the document. Used by document management systems and PDF indexers — for example `["finance", "Q3", "revenue"]`.
    </ParamField>

    <ParamField body="metadata.creator" type="string">
      The name of the application that created the document.
    </ParamField>

    <ParamField body="metadata.creationDate" type="string">
      Document creation date and time, in ISO 8601 format with a timezone offset or `Z` (for example `2026-06-01T09:00:00Z`).
    </ParamField>

    <ParamField body="metadata.modificationDate" type="string">
      Document modification date and time, in ISO 8601 format with a timezone offset or `Z`.
    </ParamField>

    <ParamField body="metadata.trapped" type="string">
      Trapping state embedded in the PDF. One of `true`, `false`, or `unknown`.
    </ParamField>
  </Expandable>
</ParamField>

<Warning>
  `metadata` fields are embedded in the PDF and visible to anyone who opens the file. Never include PHI, secrets, or other sensitive data in them.
</Warning>

## The `page` Object

The `page` object controls how the page itself is sized, oriented, padded, and optionally tinted. These settings apply to every page in the rendered document.

<ParamField body="page" type="object">
  An optional object containing page geometry and appearance settings.

  <Expandable title="page fields">
    <ParamField body="page.size" type="string | number[]" default="A4">
      The page dimensions. Either a named preset or an explicit `[width, height]` pair **in points** (1–14400 per axis).

      Named presets: `A3`, `A4` (default), `A5`, `B4`, `B5`, `Letter`, `Legal`, `Tabloid`, `HalfLetter`.

      Example explicit size: `[612, 792]` (US Letter in points).
    </ParamField>

    <ParamField body="page.orientation" type="string" default="portrait">
      Page orientation. Accepted values are `portrait` and `landscape`.
    </ParamField>

    <ParamField body="page.margin" type="number | object">
      Page margins **in points** (1 inch = 72 points; 0–2880). Pass a single number for a uniform margin on all four sides, or an object with all four sides specified.

      <Expandable title="margin object fields">
        <ParamField body="page.margin.top" type="number" required>
          Top margin in points.
        </ParamField>

        <ParamField body="page.margin.right" type="number" required>
          Right margin in points.
        </ParamField>

        <ParamField body="page.margin.bottom" type="number" required>
          Bottom margin in points.
        </ParamField>

        <ParamField body="page.margin.left" type="number" required>
          Left margin in points.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="page.background" type="object | null">
      Full-sheet background painted on the media box before body content on every page. Pass `{ "color": "#RRGGBB" }` with optional `opacity` (0–1). Omit the field for the default white viewer appearance, or pass `null` to suppress an explicit fill.

      <Expandable title="background fields">
        <ParamField body="page.background.color" type="string" required>
          Fill color as `#RGB` or `#RRGGBB`.
        </ParamField>

        <ParamField body="page.background.opacity" type="number">
          Fill opacity from 0 to 1.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<Tip>
  Margins are measured in points: 72 points = 1 inch ≈ 25.4 mm. Use wider left and right margins (e.g., `85` points ≈ 30 mm) for documents that will be printed and bound.
</Tip>

## The `viewer` Object

The `viewer` object sets PDF viewer hints — the document language plus how a viewer should open and present the file. These are stored in the PDF and honored by conforming readers.

<ParamField body="viewer" type="object">
  Optional PDF viewer hints.

  <Expandable title="viewer fields">
    <ParamField body="viewer.language" type="string">
      Document language as a well-formed BCP 47 tag (e.g. `en`, `en-US`, `zh-Hans-CN`). Sets the PDF `/Lang` so screen readers apply the correct pronunciation rules; a malformed tag is rejected. See [Accessibility](/concepts/accessibility).
    </ParamField>

    <ParamField body="viewer.pageLayout" type="string">
      Initial page layout: `single`, `one-column`, `two-column-left`, `two-column-right`, `two-page-left`, or `two-page-right`.
    </ParamField>

    <ParamField body="viewer.pageMode" type="string">
      What the viewer shows alongside the page on open: `none`, `outlines` (bookmarks panel), `thumbs`, `fullscreen`, or `attachments`.
    </ParamField>

    <ParamField body="viewer.preferences" type="object">
      Viewer preference flags: `hideToolbar`, `hideMenubar`, `hideWindowUI`, `fitWindow`, `centerWindow`, `displayDocTitle` (booleans), plus `direction` (`ltr`/`rtl`), `duplex` (`simplex`/`duplex-short-edge`/`duplex-long-edge`), and `printScaling` (`none`/`app-default`).
    </ParamField>
  </Expandable>
</ParamField>

## The `imageSequence` Field

Lay out a set of [staged assets](/concepts/markdown-rendering#images-remote-inline-and-staged) as pages — one image per page or a contact-sheet grid — without hand-writing Markdown. The sequence renders after the Markdown body; with an empty `markdown`, the document is the sequence alone. Ideal for scanned documents and photo batches.

<ParamField body="imageSequence" type="object">
  <Expandable title="imageSequence fields">
    <ParamField body="imageSequence.items" type="object[]" required>
      1–256 items, each `{ "asset": "blink://asset/<sha256>", "alt": "…" }`. `alt` (1–1024 chars) is recommended for PDF/UA-1 — an item without it is tagged as a decorative artifact.
    </ParamField>

    <ParamField body="imageSequence.layout" type="string" required>
      `one_per_page` (one image per page, e.g. a scan replica) or `grid` (contact-sheet tiling).
    </ParamField>

    <ParamField body="imageSequence.fit" type="string">
      `contain` or `cover`. Defaults to `contain` for `one_per_page` and `cover` for `grid`.
    </ParamField>

    <ParamField body="imageSequence.orientation" type="string" default="auto">
      `one_per_page` only. `auto` matches each page to its image; also `portrait` / `landscape`.
    </ParamField>

    <ParamField body="imageSequence.grid" type="object">
      Required for — and only for — `layout: "grid"`. `{ "columns": 2–6, "rows"?: 1–12, "gap"?: points (default 8) }`.
    </ParamField>

    <ParamField body="imageSequence.size" type="string | number[]" default="A4">
      Page size for the sequence pages (same presets as `page.size`).
    </ParamField>

    <ParamField body="imageSequence.padding" type="number | object" default="0">
      Inner padding around the sequence content (default 0, full-bleed).
    </ParamField>

    <ParamField body="imageSequence.furniture" type="boolean" default="false">
      Keep headers/footers on sequence pages. The free-tier watermark always applies regardless.
    </ParamField>
  </Expandable>
</ParamField>

## The `imageOverrides` Field

Target specific images with presentation overrides, without a `rules` selector.

<ParamField body="imageOverrides" type="object[]">
  An array of `{ "match", "style" }` entries. `match` is either `{ "index": 0 }` (0-based; block images first, then inline) or `{ "url": "…" }` (the exact Markdown image URL). `style` merges over `styles.image` for matching images only — `sizePct` ⊕ `sizePt`, `align`, `border`, `borderRadius`, `shadow`, `opacity`, `verticalAlign`, `inlineSize`, `height`, `fit`, `mask`, `pin`, `bleed`, `wrap`. See [Styling Rules](/configuration/styling-rules) for the image style vocabulary.
</ParamField>

## The `pinRemoteImages` Field

Make repeat renders of the same request deterministic. By default every remote `http(s)://` image is fetched fresh on each render, so a document can change if the origin changes.

<ParamField body="pinRemoteImages" type="boolean" default="false">
  When `true`, each remote image is fetched once and its bytes are reused on later renders of the same request — repeated renders produce a byte-identical PDF even if the origin changes, and skip the re-fetch. Reuse lasts up to 24 hours per image, after which it is fetched again. Pinned bytes are scoped to your API key, content-addressed, and hash-verified. Applies to `POST /v1/render` only — the [validate](/api-reference/overview) path never pins. See [Zero-retention](/concepts/zero-retention) for how this interacts with data handling.
</ParamField>

## The `glyphFallback` Field

<ParamField body="glyphFallback" type="string">
  A document-level, last-resort font family applied per glyph: only codepoints your primary fonts miss route to it. Replaces the automatic `inter` fallback, and the chosen family is reported in the `X-Render-Font-Fallback` response header. See [Fonts & Typography](/configuration/fonts-layouts).
</ParamField>

## Example: Tinted page background

The following request paints a light gray sheet behind every page. Body text and margins behave as usual; only the media-box fill changes.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.blinkpdf.io/v1/render \
    --request POST \
    --header 'Accept: application/pdf' \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: bp_xxxxxxxxxxxxxxxxxxxx' \
    --data '{
      "markdown": "# Report\n\nBody text on a tinted sheet.",
      "metadata": { "title": "Tinted report" },
      "page": {
        "size": "A4",
        "background": { "color": "#f8fafc" }
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.blinkpdf.io/v1/render", {
    method: "POST",
    headers: {
      "x-api-key": "bp_xxxxxxxxxxxxxxxxxxxx",
      "Accept": "application/pdf",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      markdown: "# Report\n\nBody text on a tinted sheet.",
      metadata: { title: "Tinted report" },
      page: {
        size: "A4",
        background: { color: "#f8fafc" },
      },
    }),
  });

  const pdf = await response.arrayBuffer();
  ```

  ```python Python theme={null}
  import httpx

  response = httpx.post(
      "https://api.blinkpdf.io/v1/render",
      headers={
          "x-api-key": "bp_xxxxxxxxxxxxxxxxxxxx",
          "Accept": "application/pdf",
          "Content-Type": "application/json",
      },
      json={
          "markdown": "# Report\n\nBody text on a tinted sheet.",
          "metadata": {"title": "Tinted report"},
          "page": {
              "size": "A4",
              "background": {"color": "#f8fafc"},
          },
      },
  )

  with open("report-tinted.pdf", "wb") as f:
      f.write(response.content)
  ```
</CodeGroup>

## Complete request example

The following example renders a two-section report with full metadata and a custom Letter-size landscape layout with generous margins.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.blinkpdf.io/v1/render \
    --request POST \
    --header 'Accept: application/pdf' \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: bp_xxxxxxxxxxxxxxxxxxxx' \
    --data '{
      "markdown": "# Q3 Financial Report\n\nThis report summarizes performance across all regions.\n\n## Revenue\n\nTotal revenue reached **$4.2M**, up 18% year-over-year.\n\n## Expenses\n\nOperating expenses remained flat at $1.9M.",
      "metadata": {
        "title": "Q3 Financial Report",
        "author": "Acme Finance Team",
        "subject": "Quarterly financial performance summary",
        "keywords": ["finance", "Q3", "revenue", "expenses", "annual"]
      },
      "page": {
        "size": "Letter",
        "orientation": "landscape",
        "margin": { "top": 72, "right": 57, "bottom": 72, "left": 85 }
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.blinkpdf.io/v1/render", {
    method: "POST",
    headers: {
      "x-api-key": "bp_xxxxxxxxxxxxxxxxxxxx",
      "Accept": "application/pdf",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      markdown: `# Q3 Financial Report

  This report summarizes performance across all regions.

  ## Revenue

  Total revenue reached **$4.2M**, up 18% year-over-year.

  ## Expenses

  Operating expenses remained flat at $1.9M.`,
      metadata: {
        title: "Q3 Financial Report",
        author: "Acme Finance Team",
        subject: "Quarterly financial performance summary",
        keywords: ["finance", "Q3", "revenue", "expenses", "annual"],
      },
      page: {
        size: "Letter",
        orientation: "landscape",
        margin: { top: 72, right: 57, bottom: 72, left: 85 },
      },
    }),
  });

  const pdf = await response.arrayBuffer();
  ```

  ```python Python theme={null}
  import httpx

  response = httpx.post(
      "https://api.blinkpdf.io/v1/render",
      headers={
          "x-api-key": "bp_xxxxxxxxxxxxxxxxxxxx",
          "Accept": "application/pdf",
          "Content-Type": "application/json",
      },
      json={
          "markdown": (
              "# Q3 Financial Report\n\n"
              "This report summarizes performance across all regions.\n\n"
              "## Revenue\n\nTotal revenue reached **$4.2M**, up 18% year-over-year.\n\n"
              "## Expenses\n\nOperating expenses remained flat at $1.9M."
          ),
          "metadata": {
              "title": "Q3 Financial Report",
              "author": "Acme Finance Team",
              "subject": "Quarterly financial performance summary",
              "keywords": ["finance", "Q3", "revenue", "expenses", "annual"],
          },
          "page": {
              "size": "Letter",
              "orientation": "landscape",
              "margin": {"top": 72, "right": 57, "bottom": 72, "left": 85},
          },
      },
  )

  with open("report.pdf", "wb") as f:
      f.write(response.content)
  ```
</CodeGroup>

<Info>
  The API returns the rendered PDF as a binary stream with `Content-Type: application/pdf`. Write the response body directly to a `.pdf` file — do not attempt to parse it as JSON.
</Info>
