# Multi-Page PDFs

> Generate multi-page PDF documents from a single template — perfect for reports, catalogs, and multi-page certificates.

- **URL**: https://orshot.com/docs/pdf-generation/multi-page-pdfs

---

Multi-page templates in Orshot let you design multiple pages within a single template and generate them as one combined PDF document. This is ideal for reports, catalogs, slide decks, multi-section invoices, and any document that spans more than one page.

## How It Works

When your Studio template has multiple pages and you render as PDF, Orshot combines all pages into a single PDF file.```javascript
const response = await fetch("https://api.orshot.com/v1/studio/render", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <YOUR_API_KEY>",
  },
  body: JSON.stringify({
    templateId: "<MULTI_PAGE_TEMPLATE>",
    modifications: {
      "page1@title": "Annual Report 2026",
      "page1@subtitle": "Q1 Financial Summary",
      "page2@title": "Revenue Breakdown",
      "page2@chart_data": "https://example.com/chart.png",
      "page3@title": "Looking Ahead",
      "page3@body": "Our projections for the coming quarter...",
    },
    response: {
      format: "pdf",
      type: "url",
    },
  }),
});

const data = await response.json();
console.log(data.data.content); // Single PDF URL with all pages
```## Rendering Specific Pages

Use `response.includePages` to select which pages appear in the final PDF:```json
{
  "response": {
    "format": "pdf",
    "type": "url",
    "includePages": [1, 3, 5]
  }
}
```This generates a PDF containing only pages 1, 3, and 5 — skipping pages 2 and 4.

### Using Page Ranges

Alternatively, use `pdfOptions.rangeFrom` and `pdfOptions.rangeTo` to select a contiguous range:```json
{
  "response": {
    "format": "pdf",
    "type": "url"
  },
  "pdfOptions": {
    "rangeFrom": 2,
    "rangeTo": 4
  }
}
```This generates a PDF with pages 2, 3, and 4.

## Page-Specific Content

Use the `page@` prefix to target content on specific pages:```json
{
  "modifications": {
    "page1@heading": "Cover Page",
    "page1@canvasBackgroundColor": "#0f172a",
    "page1@heading.color": "#ffffff",

    "page2@heading": "Table of Contents",
    "page2@canvasBackgroundColor": "#ffffff",
    "page2@heading.color": "#0f172a",

    "page3@heading": "Chapter 1: Introduction",
    "page3@body": "This report covers our progress in Q1 2026..."
  }
}
```## Global Modifications

Modifications without the `page@` prefix apply to all pages:```json
{
  "modifications": {
    "footer_logo": "https://example.com/logo.png",
    "footer_text": "© 2026 Acme Corp",

    "page1@title": "Cover",
    "page2@title": "Summary",
    "page3@title": "Details"
  }
}
```Here, `footer_logo` and `footer_text` update on every page, while each `title` is page-specific.

## Example: Product Catalog

Generate a multi-page product catalog:```javascript
const products = [
  {
    name: "Wireless Headphones",
    price: "$89",
    image: "https://example.com/headphones.jpg",
  },
  {
    name: "Smart Watch",
    price: "$249",
    image: "https://example.com/watch.jpg",
  },
  {
    name: "Portable Speaker",
    price: "$59",
    image: "https://example.com/speaker.jpg",
  },
];

const modifications = {
  brand_logo: "https://example.com/brand-logo.png",
};

products.forEach((product, i) => {
  const page = i + 1;
  modifications[`page${page}@product_name`] = product.name;
  modifications[`page${page}@product_price`] = product.price;
  modifications[`page${page}@product_image`] = product.image;
  modifications[`page${page}@product_name.href`] =
    `https://shop.example.com/product/${i + 1}`;
});

const response = await fetch("https://api.orshot.com/v1/studio/render", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <YOUR_API_KEY>",
  },
  body: JSON.stringify({
    templateId: "<CATALOG_TEMPLATE>",
    modifications,
    response: {
      format: "pdf",
      type: "url",
      fileName: "product-catalog-2026",
    },
    pdfOptions: {
      dpi: 300,
      colorMode: "cmyk",
    },
  }),
});
```## Example: Multi-Page Certificate

Generate a certificate with a cover page and detailed breakdown:```javascript
await fetch("https://api.orshot.com/v1/studio/render", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <YOUR_API_KEY>",
  },
  body: JSON.stringify({
    templateId: "<CERTIFICATE_TEMPLATE>",
    modifications: {
      // Page 1: Certificate
      "page1@recipient": "Alex Johnson",
      "page1@title": "Certificate of Completion",
      "page1@course": "Full Stack Development",
      "page1@date": "March 25, 2026",

      // Page 2: Course details
      "page2@modules_completed": "12 / 12",
      "page2@total_hours": "180 hours",
      "page2@final_grade": "A+",
      "page2@verify_link": "Verify Online",
      "page2@verify_link.href": "https://example.com/verify/CERT-001",
    },
    response: {
      format: "pdf",
      type: "url",
    },
    pdfOptions: {
      dpi: 300,
    },
  }),
});
```## Flow Text (Automatic Multi-Page PDFs)

If your template uses [flowing content](https://orshot.com/docs/orshot-studio/flowing-content) (text with `textMode: "flow"`), the PDF automatically includes as many pages as needed to fit all the text. You design a single page, and the flow engine generates the rest.```json
{
  "templateId": "<FLOW_TEMPLATE>",
  "modifications": {
    "body": "Your long document text... can be any length."
  },
  "response": {
    "format": "pdf",
    "type": "url"
  }
}
```The PDF output combines all pages (source + overflow) into one document. Use `pdfOptions.rangeFrom` and `pdfOptions.rangeTo` or `response.includePages` to select specific pages from the flow output.

Flow is great for reports, articles, or invoices where the number of pages depends on the content. See the [Flowing Content guide](https://orshot.com/docs/orshot-studio/flowing-content) for setup instructions.

## Render Costs

Each page in a multi-page PDF counts towards your render usage — this includes both designed pages and flow-generated overflow pages. Using `includePages` or `rangeFrom`/`rangeTo` to render fewer pages reduces costs accordingly.