---
source: https://carbone.io/documentation/developer/http-api/generate-reports.html
title: "Generate reports"
description: "HTTP API to merge the data in your template"
generated_at: "2026-07-13"
---

# Generate reports

HTTP API to merge the data in your template

## Generate a report

POST /render/{templateId-or-versionId}

Renders a document by merging a template with the JSON data you provide: reference it by [Template ID](/documentation/developer/http-api/introduction.md#template-id) to always render the latest deployed version, by [Version ID](/documentation/developer/http-api/introduction.md#version-id) to pin an exact one, or skip uploading entirely and [provide the template inline as base64](/documentation/developer/http-api/generate-reports.md#providing-a-template) in the request body. By default the response is a JSON object with a `renderId`; add `?download=true` to [get the rendered file directly](/documentation/developer/http-api/generate-reports.md#direct-download) in this same call.

```bash
curl  --location --request POST 'https://api.carbone.io/render/{templateId-or-versionId}' \
      --header 'carbone-version: 5' \
      --header 'Content-Type: application/json' \
      --header 'Authorization: Bearer API_TOKEN' \
      --data-raw '{ "data": { "firstname": "John", "lastname": "Wick" }, "convertTo": "pdf" }'
```

### Request header

```json
{
  // REQUIRED - Pass your API token here (string)
  "authorization"       : "Bearer API_TOKEN",

  // REQUIRED - Content type (string)
  "content-type"        : "application/json",

  // REQUIRED - Pin the Carbone API major version to avoid breaking changes (string)
  "carbone-version"     : "5",

  // OPTIONAL - Webhook for asynchronous rendering, called by Carbone when the report is generated. More info (string)
  "carbone-webhook-url" : "https://your-url",

  // OPTIONAL - Webhook custom headers, where X is any header name. Ex: carbone-webhook-header-authorization, carbone-webhook-header-x-api-key. More info (string)
  "carbone-webhook-header-X" : "headers value",

  // OPTIONAL (v5.9.0+) - Custom authorization header for egress traffic. More info (string, max 512 chars)
  "carbone-egress-header-authorization" : "my-secret"
}
```

### Request body

```jsonc
{
  // OPTIONAL - Data merged into the template with tags {d.}. Omit "data" to skip templating and only convert the file (tags left unchanged). Pass {} to run templating with an empty data-set (tags resolve to empty) (array|object)
  "data"         : {},

  // OPTIONAL - Output file format. More info (string|object)
  "convertTo"    : "pdf",

  // OPTIONAL - PDF converter engine, only relevant when "convertTo" is "pdf". "L" = LibreOffice (default), the best balance between performance and document compatibility. "O" = OnlyOffice, ideal for office documents (DOCX, XLSX, PPTX). "C" = Chromium, high-fidelity HTML-to-PDF conversion, perfect for web-based templates. More info (string)
  "converter": "L",

  // OPTIONAL - Render without a pre-uploaded template ID by providing the template here as a base64 string. When used, put the keyword "template" in the URL instead of the ID (POST /render/template). More info (string)
  "template": "BASE64_ENCODED_TEMPLATE_CONTENT",

  // OPTIONAL - Convert document dates to a timezone. More info (string)
  "timezone"     : "Europe/Paris",

  // OPTIONAL - Locale of the generated document. More info (string)
  "lang"         : "en-us",

  // OPTIONAL - Extra data object that can be merged into the template with tags {c.} (object)
  "complement"   : {},

  // OPTIONAL - Predefined alias (string)
  "variableStr"  : "{#def = d.id}",

  // OPTIONAL - Static or dynamic file name returned in the `content-disposition` header (the output extension is appended automatically). More info (string)
  "reportName"   : "{d.date}",

  // OPTIONAL - List of enumerations to use with the convEnum formatter (object)
  "enum"         : {
    "ORDER_STATUS" : ["open", "close"],
    "SPEED" : {
      "10" : "slow",
      "20" : "fast"
    }
  },

  // OPTIONAL - Localization dictionary to use with Carbone tags {t( )}. More info (object)
  "translations" : {
    "fr-ca" : {"one":"un" },
    "es"    : {"one":"uno"}
  },

  // OPTIONAL - Currency source coming from your JSON data. More info (string)
  "currencySource" : "EUR",

  // OPTIONAL - Target currency for the generated document. More info (string)
  "currencyTarget" : "USD",

  // OPTIONAL - Exchange rates used for currency conversion. More info (object)
  "currencyRates"  : {
    "EUR" : 1,
    "USD" : 1.1403
  },

  // OPTIONAL - Force the report to recompute pagination and table of contents. Requires "convertTo" to be defined (boolean)
  "hardRefresh": false,

  // OPTIONAL - Generate multiple reports with one template and multiple JSON objects. More info (string)
  "batchSplitBy" : "d.items",

  // OPTIONAL - From v5+, the output format for batch processing. More info (string)
  "batchOutput" : "zip"
}
```

### Request Query Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `download` | Boolean | No | `true`: returns the generated document directly as a file stream (the `Content-Type` reflects the output format). The file is not stored on Carbone servers and no `renderId` is issued, so there is no need to call `GET /render/{renderId}` ([more info](/documentation/developer/http-api/generate-reports.md#direct-download)).   `false`: returns a JSON object with a `renderId`; use `GET /render/{renderId}` to download the file in a second call ([see Download Reports](/documentation/developer/http-api/download-reports.md)). |

### Response

On success, by default a JSON response with content-type `application/json` containing the `renderId` is returned, which is a unique identifier for the generated document. If the query parameter **download=true** is used, the response body will be the file itself, and the content type will reflect the type of the generated document.

|   | Status Code | Body |
| --- | --- | --- |
| 🟢 | 200 | `{ "success" : true, "data": { "renderId": "" } }`   **or** File Stream, if the query parameter `download=true` is used. |
| 🔴 | 400 | `{ "success" : false, "error" : ""Content-Type" header is not "application/json""}` |
| 🔴 | 400 | `{ "success" : false, "error" : "Invalid templateId"}` |
| 🔴 | 401 | `{ "success" : false, "error" : "Unauthorized, please provide a correct API key on the "Authorization" header"}` |
| 🔴 | 404 | `{ "success" : false, "error" : "Template not found"}` |
| 🔴 | 413 | `{ "success" : false, "error" : "Content too large, the JSON size limit is X MB"}` |
| 🔴 | 422 | `{ "success" : false, "error" : "Missing "data" property in body"}`   **Note:** From `carbone-version: 5`, `data` is optional: omitting it converts the file without templating (tags left unchanged). This error applies to `carbone-version: 4` only. |
| 🔴 | 500 | `{ "success" : false, "error" : "Error while rendering template"}` |
| 🔴 | 500 | `{ "success" : false, "error" : "Error while setting up the webhook"}` |

## Providing a template

Every render call needs a template. There are two ways to provide one:

**Upload it first (template ID)**: Upload your template once with `POST /template`, which returns a `templateId` (and a `versionId` per version). Reference that ID in the render URL: `POST /render/{templateId-or-versionId}`. Best when the same template is reused across many renders. See [Upload a template](/documentation/developer/http-api/manage-templates.md#upload-a-template).

**Provide it inline (base64)**: Skip the upload and send the template directly in the request body as a base64-encoded string in the `template` field, using the keyword `template` in the URL instead of an ID: `POST /render/template`. The template is not stored on Carbone's servers, so a single API call is enough. Best for one-off or dynamically generated templates.

## Direct download

The `POST /render/{templateId-or-versionId}` endpoint accepts a `?download=true` query parameter to download the rendered report directly.

When this option is used, the file is not stored on our servers. A single API call is enough to download the file. There is no need to call `GET /render/{renderId}`.

When `download=true`, the response shape depends on the outcome:

-   **`200 OK`**: the body is the binary file, returned with the headers below (`Content-Type` matches the output format).
-   **Any error (`4xx`/`5xx`)**: the response falls back to JSON (`application/json`) with the usual `{ "success": false, "error": "..." }` body.

```text
  Content-Disposition: 'attachment; filename="report.pdf"'
  Content-Type: 'application/pdf'
```

## Output filename

With Carbone, even the generated report filename is a template!

Define the `reportName` option in the request body to set a custom filename. It accepts a static string or Carbone tags for dynamic filenames, for example:

```json
{
  "data": { "company": "Acme", "date": "2026-06-29" },
  "reportName": "{d.company}-{d.date}"
}
```

Carbone appends the output file extension automatically (based on the generated format), so do not include it in `reportName`. The resulting filename is returned in the `content-disposition` header when the report is downloaded, for example `Acme-2026-06-29.pdf`.

## Output file type

By default, if `convertTo` is undefined, the output file type is the same as the input template file type.

The table below lists all accepted `convertTo` values according to the input template file type.

And some output file types can have additional options. See the dedicated documentation

-   for [pdf](#pdf-options)
-   for [jpg/png](#jpg-png-options)
-   for [csv](#csv-options)

| Template Type | `convertTo` |
| --- | --- |
| document | pdf, docx, odt, bib, doc, doc6, doc95, docbook, docx7, fodt, html, latex, ooxml, ott, psw, rtf, stw, sxw, text, txt, uot, xhtml, jpg, jpeg, png, epub, md, svg, webp, pages |
| spreadsheet | pdf, xlsx, ods, csv, dbf, dif, fods, html, ooxml, ots, pxl, slk, stc, sxc, uos, xhtml, xls, xls5, xls95, xlt, xlt5, xlt95, numbers, parquet |
| presentation | pdf, pptx, odp, bmp, emf, eps, fodp, gif, html, jpg, met, odg, pbm, pct, pgm, png, ppm, pwp, ras, sti, svg, svm, swf, sxi, tiff, uop, wmf, xhtml, otp, potm, pot, pps, ppt, webp |
| web | pdf, etext, html10, html, txt, text10, text |
| graphics | bmp, emf, eps, fodg, gif, html, jpg, met, odd, otg, pbm, pct, pdf, pgm, png, ppm, ras, std, svg, svm, swf, sxd, tiff, wmf, xhtml, webp, pub, cdr |

Notes:

-   Export to `xhtml` to embed images in html

## Multi-timezone

Some date formatters like `formatD` or `formatI` adapt the inserted date in the template according to the timezone.

List of accepted timezone (Column TZ identifier) : [https://en.wikipedia.org/wiki/List\_of\_tz\_database\_time\_zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)

## Multi-language

Many text, date, and number formatters like `formatN`, `formatD`, `formatI` adapt their output in the template according to the locale.

Also, the `lang` parameter is used to select the corresponding `translations` when the Carbone tag `{t()}` is used for multi-lingual reports.

List of supported locales: [https://github.com/carboneio/carbone/blob/master/formatters/\_locale.js](https://github.com/carboneio/carbone/blob/master/formatters/_locale.js)

You can support multiple languages in your report by using [translations formatters](/documentation/design/advanced-features/translations-i18n.md).

## Multi-currency

You can create templates that adapt their currency depending on the locale.

The `formatC` formatter converts amounts from a source currency to a target currency using the exchange rates you provide:

-   `currencySource`: the currency your amounts are expressed in within your JSON data.
-   `currencyTarget`: the currency to convert those amounts to in the generated document.
-   `currencyRates`: the exchange rates used to convert from `currencySource` to `currencyTarget`.

[Learn more](/documentation/design/formatters/currency.md)

## Converters

Document conversion (for example DOCX to PDF) is handled by a dedicated converter engine. From v5, the `converter` option in the request body selects which engine Carbone uses.

-   It is only relevant when `convertTo` is set to `"pdf"`; for any other output format it is ignored.
-   If omitted, LibreOffice (`L`) is used by default.
-   All engines run from Carbone's own pre-built, optimized binaries (`bin.carbone.io`) for ARM and x64.

### Choosing a converter

| `converter` | Engine | Recommended for | Notes |
| --- | --- | --- | --- |
| `L` | LibreOffice (default) | DOCX/XLSX/PPTX, ODT/ODS/ODP/ODG and MD to PDF | Best balance between performance and document compatibility. Supports all [PDF options](#pdf-options). |
| `O` | OnlyOffice | DOCX/XLSX/PPTX to PDF | Alternative for office documents. Only [`Security`](#pdf-options) and [`Watermark`](#watermark-options) options are supported (see [limitations](#converters-onlyoffice-limitations)). |
| `C` | Chromium | HTML to PDF/JPG/PNG/WEBP | High-fidelity HTML-to-PDF conversion, perfect for web-based templates. Only [`Security`](#pdf-options) and [`Watermark`](#watermark-options) options are supported. |

For the most advanced PDF controls, use LibreOffice.

### OnlyOffice limitations

-   No custom PDF export options (such as PDF/UA, compression quality, forms, etc.).
-   Table of Contents in DOCX files is not updated when generating documents.
-   SVG support is very limited.
-   Hidden characters are not supported.
-   Repeated headers on page breaks are not supported.
-   High memory usage (RAM).
-   Slower performance with small documents (< 50 pages).

## PDF options

Options can be passed for PDF conversion. In this case, `convertTo` has to be an object with `formatName` set to `pdf` and `formatOptions` with options.

```jsonc
{
  "convertTo" : {
    "formatName"    : "pdf",
    "formatOptions" : {
      "EncryptFile"          : true,
      "DocumentOpenPassword" : "QWERTY1234",
      "Watermark"            : "Watermark Carbone.io"
    }
  }
}
```

The following options can be passed to `formatOptions`:

| Option name | Type | Default | Description |
| --- | --- | --- | --- |
| **General** |   |   |   |
| SelectPdfVersion | integer | 0 | Specifies the PDF version to emit.   **0** : PDF 1.6 Standard.   **1** : PDF/A-1 (ISO 19005-1:2005).   **2** : PDF/A-2 (ISO 19005-2:2011).   **3** : PDF/A-3 (ISO 19005-3:2012).   **4** : PDF/A-4 (ISO 19005-4).   **15** : PDF 1.5 Standard.   **16** : PDF 1.6 Standard.   **17** : PDF 1.7 Standard.   **20** : PDF 2.0 Standard. |
| ConvertOOoTargetToPDFTarget | boolean | false | Renames .od\[tpgs\] links to .pdf in exported PDF, leaving source untouched. |
| ExportFormFields | boolean | true | Specifies whether form fields are exported as widgets or only as fixed print representation. |
| ExportLinksRelativeFsys | boolean | false | Exports file system hyperlinks as relative to source document. |
| ExportNotes | boolean | true | Specifies if notes are exported to PDF. |
| ExportNotesPages | boolean | false | Specifies if notes pages are exported to PDF (Impress only). |
| FormsType | integer | 0 | Format for PDF form submission:   **0**: FDF   **1**: PDF   **2**: HTML   **3**: XML |
| IsAddStream | boolean | false | Adds stream containing original document for archiving (PDF Import only). |
| IsSkipEmptyPages | boolean | false | Suppresses auto-inserted empty pages (Writer only). |
| UseTransitionEffects | boolean | true | Exports slide transitions to PDF (Impress only). |
| **Security** |   |   |   |
| DocumentOpenPassword | string |   | Password to open PDF file (with "EncryptFile" enabled). |
| EncryptFile | boolean | false | Encrypts PDF file; password required to open. |
| PermissionPassword | string |   | Password for restricted permissions if `"RestrictPermissions"` enabled. |
| RestrictPermissions | boolean | false | Enables restricted permissions in the PDF document. Must be used with `"PermissionPassword"`. |
| Changes | integer | 4 | What changes are allowed in the PDF.   **0**: None   **1**: Insert/delete/rotate pages   **2**: Fill forms   **3**: Comment/fill forms   **4**: Any except page extraction.   Requires `"RestrictPermissions": true` and `"PermissionPassword"`. |
| EnableCopyingOfContent | boolean | true | Allows copying content to other documents.   Requires `"RestrictPermissions": true` and `"PermissionPassword"`. |
| EnableTextAccessForAccessibilityTools | boolean | true | Allows extraction for accessibility tools.   Requires `"RestrictPermissions": true` and `"PermissionPassword"`. |
| Printing | integer | 2 | Allowed printing:   **0**: None   **1**: Low resolution (150 DPI)   **2**: Max resolution.   Requires `"RestrictPermissions": true` and `"PermissionPassword"`. |
| **Compression & Quality** |   |   |   |
| MaxImageResolution | integer | 300 | Reduce images to this DPI if "ReduceImageResolution" is true. Possible: 75, 150, 300, 600, 1200 |
| Quality | integer | 90 | JPG export quality (1-100). Lower = higher compression/larger file; higher = better quality/smaller file. |
| ReduceImageResolution | boolean | false | Reduces image resolution to "MaxImageResolution". |
| UseLosslessCompression | boolean | true | Use PNG (lossless) or JPEG for graphics. |
| **Watermark** |   |   |   |
| Watermark | string |   | Draws text watermark on every page. |
| Watermarks | array |   | Array of up to 5 watermark objects (see [Watermark options](#watermark-options)). |
| **Accessibility** |   |   |   |
| UseTaggedPDF | boolean | false | Creates PDF with special tags (Tagged PDF). |
| PDFUACompliance | boolean | false | Enables PDF/UA Universal Accessibility standard (ISO 14289). |
| AllowDuplicateFieldNames | boolean | false | Allows export of multiple form fields with same name (OOo 3.3+). |
| **View/Appearance** |   |   |   |
| CenterWindow | boolean | false | Opens PDF centered on screen. |
| DisplayPDFDocumentTitle | boolean | true | Shows document title in viewer window. |
| ExportBookmarks | boolean | true | Exports bookmarks to PDF. |
| ExportBookmarksToPDFDestination | boolean | false | Exports bookmarks as named destinations. |
| FirstPageOnLeft | boolean | false | Used with "PageLayout": odd first page appears left. |
| HideViewerMenubar | boolean | false | Hides PDF viewer menubar. |
| HideViewerToolbar | boolean | false | Hides PDF viewer toolbar. |
| HideViewerWindowControls | boolean | false | Hides PDF viewer window controls. |
| InitialPage | integer | 1 | Page number on which PDF opens. |
| InitialView | integer | 0 | Display mode on open:   **0**: none   **1**: outline pane   **2**: thumbnail pane. |
| Magnification | integer | 0 | Open action:   **0**: default   **1**: fit page   **2**: fit width   **3**: fit width of bounding box   **4**: Zoom set by "Zoom". |
| OpenBookmarkLevels | integer | \-1 | Number of bookmark levels opened on startup (-1 = all). |
| OpenInFullScreenMode | boolean | false | Opens PDF in full screen. |
| PageLayout | integer | 0 | Page layout:   **0**: reader default   **1**: single   **2**: one column   **3**: two columns (see "FirstPageOnLeft"). |
| PageRange | string |   | Range of pages to include. Example : "1-5" |
| PDFViewSelection | integer | 0 | PDF viewing:   **0**: all links as URI   **1**: PDF reader only (not for PDF/A-1)   **2**: Internet browser with plugin (see "ExportBookmarksToPDFDestination"). |
| ResizeWindowToInitialPage | boolean | false | Resizes viewer to first page at open. |
| Zoom | integer | 100 | Zoom percent if "Magnification" is 4. |

> ⚠️ **Warning:** The availability of PDF export options varies by converter.

| Option Category | LibreOffice | Chrome | OnlyOffice |
| --- | --- | --- | --- |
| All PDF Options | ✓ | ✗ | ✗ |
| Security Options | ✓ | ✓ | ✓ |
| Watermark Option | ✓ | ✓ | ✓ |

-   **All PDF Options**: All the options listed above (General, Compression, Quality, View, etc.) can be used.
-   **Security Options**: Options such as password protection and file encryption.
-   **Watermark Option**: Option to add a watermark to each page.

For the most advanced PDF controls, use the LibreOffice converter.  
If you are using Chrome or OnlyOffice, only "Security" and "Watermark" options are supported.

## JPG/PNG options

It is possible to export **jpg** or **png** images with options (list below).

| Export Types | Option name | Type | Default | Description |
| --- | --- | --- | --- | --- |
| **jpg** / **png** | PixelWidth | Number | Document width | Image width as pixels |
| **jpg** / **png** | PixelHeight | Number | Document height | Image height as pixels |
| **jpg** / **png** | ColorMode | Number | 0 | 0 Colors, 1 Greyscale |
| **jpg** | Quality | Number | 100 | From 1 (low quality, high compression, low size) to 100 (high quality, low compression, high size) |
| **png** | Compression | Number | 0 | From 0 (compression disabled) to 9 (high compression, low size) |
| **png** | Interlaced | Number | 0 | 0 not interlaced, 1 interlaced (higher size) |
| **png** | Translucent | Number | 0 | 0 no transparent background, 1 transparent background |

Here is an example of exporting a JPG image with options:

```json
{
  "convertTo": {
    "formatName" : "jpg",
    "formatOptions": {
      "Quality"   : 50,
      "ColorMode" : 1
    }
  }
}
```

## CSV options

During CSV conversion, the following elements can be changed: separator, delimiter and the character set. `convertTo` has to be an object with `formatName` set to `csv` and `formatOptions` with options. `characterSet` can be one of these options : [https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Filter\_Options](https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Filter_Options)

```javascript
{
  convertTo : {
    formatName    : 'csv',
    formatOptions : {
      fieldSeparator : '+',
      textDelimiter  : '"',
      characterSet   : '76' // utf-8
    }
  }
}
```

## Watermark options

Carbone supports adding one or multiple text watermarks to every page of a generated PDF. Watermarks are defined inside the `formatOptions` object when `convertTo` is set to `pdf`.

Two fields are available:

-   **`Watermark`** _(string)_: Legacy field, still supported. Renders a single centered watermark at 45° with default styling. Use this for simple use cases or backward compatibility.
-   **`Watermarks`** _(array)_: New field introduced in v5.3.0. Accepts up to 5 watermark objects, each fully configurable. Both fields can be used simultaneously.

```jsonc
{
  "convertTo": {
    "formatName": "pdf",
    "formatOptions": {
      // Legacy: single centered watermark (backward compatible)
      "Watermark": "CONFIDENTIAL",
      // New in v5.3.0: array of watermark objects
      "Watermarks": [
        {
          "text": "Confidential - Page {#PAGE_NUMBER} / {#PAGE_TOTAL}",
          "anchor": "topLeft",
          "offsetX": 10,
          "offsetY": 10,
          "rotation": -45,
          "color": "#000000",
          "size": 64,
          "opacity": 0.21,
          "font": "Helvetica",
          "fromPage": 1,
          "toPage": 10
        }
      ]
    }
  }
}
```

**Watermark object properties**

The following properties apply to each watermark object defined inside the `Watermarks` array. They are not available on the legacy `Watermark` string field.

All properties except `text` are optional.

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `text` | string |   | **Required.** The watermark label. Between 1 and 2000 characters. Supports `{#PAGE_NUMBER}` and `{#PAGE_TOTAL}` variables for dynamic page numbering. |
| `anchor` | string | `center` | Position on the page. Accepted values: `topLeft`, `top`, `topRight`, `left`, `center`, `right`, `bottomLeft`, `bottom`, `bottomRight`. |
| `offsetX` | number | `0` | Horizontal offset in points (pt) from the anchor. In PDFs, the origin is bottom-left, so positive values move right. |
| `offsetY` | number | `0` | Vertical offset in points (pt) from the anchor. Positive values move up. |
| `rotation` | number | `45` for `center`, `0` for others | Rotation angle in degrees, between `-360` and `360`. For non-center anchors, only `0`, `90`, or `-90` are allowed. |
| `color` | string | `#000000` | Watermark text color in `#RGB` or `#RRGGBB` format (e.g. `#ff0000`, `#f00`). |
| `size` | number | Auto for `center`, `12` for others | Font size in points (pt), between `1` and `2000`. |
| `opacity` | number | `0.1` for `center`, `1` for others | Opacity between `0` (invisible) and `1` (fully opaque). |
| `font` | string | `Helvetica` | Font family. Accepted values: `Courier`, `Courier-Bold`, `Courier-Oblique`, `Courier-BoldOblique`, `Helvetica`, `Helvetica-Bold`, `Helvetica-Oblique`, `Helvetica-BoldOblique`, `Times-Roman`, `Times-Bold`, `Times-Italic`, `Times-BoldItalic`. |
| `fromPage` | integer | `1` | First page (1-based) on which the watermark is applied. |
| `toPage` | integer | Last page | Last page (1-based) on which the watermark is applied. Defaults to all remaining pages. |

**Dynamic page numbering**

Use `{#PAGE_NUMBER}` and `{#PAGE_TOTAL}` in the `text` field to insert the current page number and total page count into the watermark.

```jsonc
{
  "text": "Draft - Page {#PAGE_NUMBER} of {#PAGE_TOTAL}"
}
```

## Asynchronous jobs

For large reports or long-running renders, we recommend using the asynchronous rendering system. This method offers a longer rendering timeout of 5 minutes, surpassing the 60-second limit of the synchronous API.

Carbone will notify your application/service at a custom URL as soon as the document is generated.

How to use this system?

1.  Prepare your server to accept POST requests at a webhook endpoint. For experimentation, [https://webhook.site/](https://webhook.site/) is a convenient option.
2.  Send a request to `POST /render/{templateId-or-versionId}` with the HTTP header `carbone-webhook-url: https://my-custom-webhook/my-custom-url`
3.  (From version 4.23.0) If your webhook url needs authentication or a specific header, you can configure it by adding the header `carbone-webhook-header-X`. Ex : `carbone-webhook-header-authorization: my-secret`
4.  Upon report completion, Carbone will invoke your webhook endpoint, sending a JSON object that includes the `renderId`. The response object is the same as the response from the synchronous method.

Carbone automatically retries (one retry) to call your webhook for the following errors:

-   Status Code Errors: 408, 429, 502, 503, 504, 521, 522, 524
-   Socket Errors: ETIMEDOUT, ECONNRESET, EADDRINUSE, ECONNREFUSED, EPIPE, ENOTFOUND, ENETUNREACH, EAI\_AGAIN
-   Request Timeout (16 seconds max)

## Egress authentication

(From version 5.9.0) When Carbone makes outbound calls during a render, to your webhook, to a dynamic image URL, or to a file fetched by `appendFile`, you can set the `authorization` header on all of them with the `carbone-egress-header-authorization` request header.

For example, sending `carbone-egress-header-authorization: my-secret` makes Carbone add `authorization: my-secret` to every egress request (webhook, dynamic image, `appendFile`, and so on).

-   Only the `authorization` header can be customized this way, and its value must not exceed 512 characters.
-   For webhook calls, `carbone-webhook-header-authorization` (see [Asynchronous jobs](#asynchronous-jobs)) takes precedence and overrides `carbone-egress-header-authorization`, but only for the webhook. Dynamic images and `appendFile` requests still use the egress header.

## Batch processing

Since version 4.20.0, Carbone can generate multiple reports in one go using a single HTTP request, with the same template. This feature streamlines the creation of reports, especially when dealing with bulk data, by returning a compressed ZIP (or PDF) file that contains all generated reports.

Batch processing is particularly useful for generating personalized documents, such as letters or invoices, for multiple recipients simultaneously.

Batch processing is enabled if all of the following conditions are met

-   Include the `batchSplitBy` attribute in the `POST /render/{templateId-or-versionId}` request (see below).
-   Utilize asynchronous job processing by setting the `carbone-webhook-url` HTTP header in your request (see above).
-   Only for Cloud: Ensure the data payload contains a non-empty array with up to 100 objects (= 100 reports)
-   Only for On-Premise: The global configuration parameter `nbReportMaxPerBatch` is greater than 0.

**API Request Example**

To initiate batch processing, send a JSON object structured as follows:

```jsonc
{
  "data"         : {
    "letters" : [
      { "id" : 1, "name" : "John"   },
      { "id" : 2, "name" : "David"  },
      { "id" : 3, "name" : "Steeve" }
    ]
  },
  // The result will be a ZIP file of multiple PDFs
  "convertTo"    : "pdf",
  // Batch processing option.
  "batchSplitBy" : "d.letters",
  // From v5+, can be "zip" (default), or "pdf"
  "batchOutput" : "zip"
}
```

`batchSplitBy` determines how the batch is split. Accepted values:

-   "d" if `data` is an array of objects, resulting in one report per object.
-   "d.myCustomField" to select a direct child array of "data", resulting in one report per object in that array.

`batchOutput` determines the output file type. Accepted values:

-   `zip` to get an archive of all generated reports.
-   `pdf` to get a concatenation of generated PDFs (only possible if `convertTo = "pdf"`).

**Template Writing Methods**

When writing templates for batch processing, you can employ two approaches. Carbone automatically detects the method used.

1.  Direct child access: Write the template directly at the `d.letters[]` level, using placeholders for each data field.
    
    ```text
     {d.id} {d.name}
    ```
    
2.  Array access: Write the template at the root level `d`. For each report, Carbone generates an array containing a single object, thereby producing one report for every object within `d.letters`.
    
    ```text
     {d.letters[i].id}    {d.letters[i].name}
     {d.letters[i+1].id}
    ```

## Related topics

- [Upload and manage templates](/documentation/developer/http-api/manage-templates.md)
- [Introduction](/documentation/developer/http-api/introduction.md)
- [Download Generated Reports](/documentation/developer/http-api/download-reports.md)
- [Convert Documents](/documentation/developer/http-api/convert-reports.md)
