# Rendering with our powerful API

<div style="text-align: justify;">

Everything the Generate PDF page does in the browser, the API does programmatically — with more control, lower overhead, and the same rendering engine underneath. A single `POST` request renders a report, optionally logs the result, and optionally dispatches a print job, all in one call.

[![api-docs.png](https://docs.veloxfactory.kiwi-software.dev/uploads/images/gallery/2026-05/scaled-1680-/api-docs.png)](https://docs.veloxfactory.kiwi-software.dev/uploads/images/gallery/2026-05/api-docs.png)

---

<h3 id="the-endpoint" style="color: #203671; margin-top: 2.2em;">The Render Endpoint</h3>

```
POST /api/v1/report-config/{id}/render
```

The `{id}` segment accepts either the numeric ID of the `ReportConfig` or its **report name** — the name set in Jaspersoft Studio and stored in VeloxFactory. Both of these are equivalent:

```
POST /api/v1/report-config/1/render
POST /api/v1/report-config/A5_KanBan/render
```

Using the report name is convenient for integrations: it stays stable even if the database record is recreated, and it makes the request self-documenting.

---

<h3 id="request-body" style="color: #203671; margin-top: 2.2em;">Request Body</h3>

<table style="width: 100%; border-collapse: collapse;">
  <thead>
    <tr style="border-top: 1px solid #e6e8ef; border-bottom: 1px solid #e6e8ef;">
      <th style="text-align: left; padding: 6px 10px; white-space: nowrap;">Field</th>
      <th style="text-align: left; padding: 6px 10px;">Type</th>
      <th style="text-align: left; padding: 6px 10px;">Required</th>
      <th style="text-align: left; padding: 6px 10px;">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>outputType</code></td>
      <td style="padding: 6px 10px;">string</td>
      <td style="padding: 6px 10px;">✓</td>
      <td style="padding: 6px 10px;">Output format: <code>base64</code>, <code>url</code>, or <code>none</code>. See below.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>parameters</code></td>
      <td style="padding: 6px 10px;">object</td>
      <td style="padding: 6px 10px;"></td>
      <td style="padding: 6px 10px;">Key-value map of parameter names to values. Required parameters must be present or the request is rejected.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>data</code></td>
      <td style="padding: 6px 10px;">array</td>
      <td style="padding: 6px 10px;"></td>
      <td style="padding: 6px 10px;">Array of field objects — one per detail band row. Each object's keys must match the report's field names. Only needed when no SQL connection is configured.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>createHistoryRecord</code></td>
      <td style="padding: 6px 10px;">boolean</td>
      <td style="padding: 6px 10px;">✓</td>
      <td style="padding: 6px 10px;">Whether to create a <code>ReportHistoryRecord</code> for this render. Stores the full request, response, and rendered PDF.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>createPrintTask</code></td>
      <td style="padding: 6px 10px;">boolean</td>
      <td style="padding: 6px 10px;">✓</td>
      <td style="padding: 6px 10px;">Whether to dispatch the rendered PDF to the print service.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>printerName</code></td>
      <td style="padding: 6px 10px;">string</td>
      <td style="padding: 6px 10px;">if print task</td>
      <td style="padding: 6px 10px;">Target printer name. Required when <code>createPrintTask</code> is <code>true</code>.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>numberOfCopies</code></td>
      <td style="padding: 6px 10px;">integer</td>
      <td style="padding: 6px 10px;"></td>
      <td style="padding: 6px 10px;">Number of copies passed to the print service. Defaults to <code>1</code>. VeloxFactory always renders once — the print service handles duplication.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>broadcastId</code></td>
      <td style="padding: 6px 10px;">string</td>
      <td style="padding: 6px 10px;"></td>
      <td style="padding: 6px 10px;">WebSocket channel ID. If provided, VeloxFactory broadcasts a <code>ReportPrintTaskCreated</code> event when the print task is created. Omit to rely on polling.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>useExampleValues</code></td>
      <td style="padding: 6px 10px;">boolean</td>
      <td style="padding: 6px 10px;"></td>
      <td style="padding: 6px 10px;">Use the stored example values instead of supplying <code>parameters</code> and <code>data</code>. Useful for testing. API-only — not available in the frontend. See below.</td>
    </tr>
    <tr style="border-bottom: 1px solid #e6e8ef;">
      <td style="padding: 6px 10px; white-space: nowrap;"><code>laconicResponse</code></td>
      <td style="padding: 6px 10px;">boolean</td>
      <td style="padding: 6px 10px;"></td>
      <td style="padding: 6px 10px;">Return only the essential output fields instead of the full response. Reduces payload size significantly for high-frequency rendering. See below.</td>
    </tr>
    <tr>
      <td style="padding: 6px 10px; white-space: nowrap;"><code>traceId</code></td>
      <td style="padding: 6px 10px;">string</td>
      <td style="padding: 6px 10px;"></td>
      <td style="padding: 6px 10px;">Custom trace identifier for this request. Auto-generated (UUID) if not provided. Must be unique across all history records if supplied.</td>
    </tr>
  </tbody>
</table>

---

<h3 id="output-types" style="color: #203671; margin-top: 2.2em;">Output Types</h3>

The `outputType` field controls how — or whether — the rendered PDF is returned.

**`base64`** — The PDF is Base64-encoded and returned inline in `output.reportPdfBase64`. No file is written to disk. This is the most common choice for integrations that process the PDF immediately.

**`url`** — The PDF is saved to the VeloxFactory history storage and a URL pointing to that file is returned in `output.reportUrl`. Useful when the calling application needs to hand off a link rather than handle raw bytes.

**`none`** — No PDF data is returned at all. Valid only when `createPrintTask` is `true` — the PDF is rendered internally and handed to the print service without being exposed in the response. Use this when the response payload is irrelevant and you only care about getting the document to the printer.

<div style="border-left: 4px solid #203671; background: #f0f3fb; padding: 10px 16px; margin: 16px 0; border-radius: 0 4px 4px 0;">
⚠️ <strong><code>outputType: none</code> requires <code>createPrintTask: true</code>.</strong> Requesting output type <code>none</code> without a print task is rejected with a validation error — there would be nothing to do with the rendered PDF.
</div>

---

<h3 id="use-example-values" style="color: #203671; margin-top: 2.2em;">useExampleValues — API-only Testing Mode</h3>

When `useExampleValues: true` is set, VeloxFactory ignores any `parameters` and `data` in the request body and instead uses the example values stored on the `ReportConfig`. This is the same data used to generate the report preview in the frontend.

It is a convenient way to verify that a report renders correctly after configuration changes — no test data needs to be assembled:

```json
POST /api/v1/report-config/A5_KanBan/render

{
  "outputType": "base64",
  "useExampleValues": true,
  "createHistoryRecord": false,
  "createPrintTask": false
}
```

<div style="border-left: 4px solid #5fc75d; background: #f6fdf6; padding: 10px 16px; margin: 16px 0; border-radius: 0 4px 4px 0;">
ℹ️ <strong><code>useExampleValues</code> is an API-only feature.</strong> The Generate PDF page in the browser always requires parameters and data to be entered manually. For frontend testing, use the example values from the report configuration edit page.
</div>

---

<h3 id="laconic-response" style="color: #203671; margin-top: 2.2em;">laconicResponse — Minimal Output</h3>

By default, a successful render response includes the full `ReportConfig` record, the input parameters and data echoed back, and any linked `ReportHistoryRecord` and `ReportPrintTask`. For many production integrations, this detail is unnecessary — the caller only needs the PDF.

Setting `laconicResponse: true` strips the response down to the essentials: just the `traceId` and the `output` block. Everything else — `input`, `reportConfig`, `reportHistoryRecord`, `reportPrintTask` — is omitted.

The two response shapes are shown in detail in the [Response Structure](#response-structure) section below.

<div style="border-left: 4px solid #5fc75d; background: #f6fdf6; padding: 10px 16px; margin: 16px 0; border-radius: 0 4px 4px 0;">
ℹ️ <strong>The laconic mode also suppresses <code>reportMeta</code> in error responses.</strong> If a render fails in laconic mode, the error response contains only the error messages — the field and parameter metadata is not included.
</div>

---

<h3 id="a-complete-request" style="color: #203671; margin-top: 2.2em;">A Complete Request</h3>

Here is a full render request for a KanBan label — dynamic array data, a parameter, history logging enabled, print task dispatched via WebSocket:

```json
POST /api/v1/report-config/A5_KanBan/render

{
  "outputType": "base64",
  "parameters": {
    "P_ARTICLE_NUMBER": "4561287-154"
  },
  "data": [
    {
      "articleNumber": "4561287-154",
      "description":   "Packing Carton Size 1 - 200x150x50mm",
      "moq":           250,
      "deliveryTime":  "3 Days",
      "supplier":      "Ninghao Packaging",
      "barcode":       "5698532145712"
    }
  ],
  "createHistoryRecord": true,
  "createPrintTask": true,
  "printerName": "WarehousePrinter01",
  "numberOfCopies": 1,
  "broadcastId": "Standard",
  "laconicResponse": false
}
```

---

<h3 id="response-structure" style="color: #203671; margin-top: 2.2em;">Response Structure</h3>

<h4 style="color: #203671; margin-top: 1.4em;">Full Response</h4>

The full response (default, `laconicResponse: false` or omitted) includes the rendered output, the echoed input, the full `ReportConfig` snapshot, and any created `ReportHistoryRecord` and `ReportPrintTask`:

```json
{
  "success": true,
  "count": 1,
  "data": {
    "model": "ReportRendering",
    "traceId": "ec1e29de-7aca-4c59-9722-ae9edc7d24d7",
    "input": {
      "parameters": { "P_ARTICLE_NUMBER": "4561287-154" },
      "data": [
        {
          "articleNumber": "4561287-154",
          "description":   "Packing Carton Size 1 - 200x150x50mm",
          "moq":           250,
          "deliveryTime":  "3 Days",
          "supplier":      "Ninghao Packaging",
          "barcode":       "5698532145712"
        }
      ]
    },
    "output": {
      "reportPdfFileName": "a7dd0ea5-85fd-481c-998b-fa9819c2e84c.pdf",
      "reportPdfBase64":   "JVBERi0xLjQ..."
    },
    "reportConfig": {
      "model": "ReportConfig",
      "id": 1,
      "name": "A5_KanBan",
      ...
    },
    "reportHistoryRecord": {
      "model": "ReportHistoryRecord",
      "id": 4,
      "traceId": "ec1e29de-7aca-4c59-9722-ae9edc7d24d7",
      "outputType": "Base64",
      "status": "Ok"
    },
    "reportPrintTask": {
      "model": "ReportPrintTask",
      "id": 4,
      "traceId": "ec1e29de-7aca-4c59-9722-ae9edc7d24d7",
      "broadcastId": "Standard",
      "printerName": "WarehousePrinter01",
      "numberOfCopies": 1,
      "status": "Pending",
      "errorMessage": null
    }
  },
  "meta": [],
  "status": 200
}
```

<h4 style="color: #203671; margin-top: 1.4em;">Laconic Response</h4>

With `laconicResponse: true`, the response contains only what is needed to retrieve the PDF:

```json
{
  "success": true,
  "count": 1,
  "data": {
    "model": "ReportRendering",
    "traceId": "555d073b-a630-4096-acd1-643b85ed5cc9",
    "output": {
      "reportPdfFileName": "8de016b5-4cf9-423a-9575-8c3155e35410.pdf",
      "reportPdfBase64":   "JVBERi0xLjQ..."
    }
  },
  "meta": [],
  "status": 200
}
```

The `traceId` is always included — it links this render to any created history record or print task, making it useful for cross-referencing even in laconic mode.

---

<h3 id="errors" style="color: #203671; margin-top: 2.2em;">Errors</h3>

<h4 style="color: #203671; margin-top: 1.4em;">Validation Errors — HTTP 422</h4>

Missing required fields, an invalid `outputType` value, or a missing `printerName` when a print task is requested all produce a `422` response with an `errors` array describing the violations.

Required parameters that are not present in the request also return a `422` — one error message per missing parameter:

```json
{
  "success": false,
  "errors": [
    "Parameter P_DATE_FROM is required.",
    "Parameter P_DATE_TO is required."
  ],
  "meta": { "traceId": "..." },
  "status": 422
}
```

<h4 style="color: #203671; margin-top: 1.4em;">Render Errors — HTTP 400</h4>

If the request passes validation but the renderer itself fails — empty data array for a report with a detail band, a type mismatch between field values and declared Java types, a broken SQL query — the response comes back with HTTP `400` and a `success: false` payload.

In full (non-laconic) mode, a `reportMeta` block is included in the `meta` object alongside the `traceId`. This snapshot lists the report's fields, parameters, and resources at the time of the failure — useful for diagnosing mismatches between the request payload and what the report actually expects:

```json
{
  "success": false,
  "errors": [
    "No data delivered (or fetched via SQL using parameters) while data deliverance is mandatory for reports with detail bands."
  ],
  "meta": {
    "traceId": "08deac82-274d-4f56-b9d0-d9fdb6280f8f",
    "reportMeta": {
      "resourceList": [
        { "parameterName": "P_RESOURCE_LOGO", "fileName": "Logo_Dark.png" }
      ],
      "parameterList": [
        { "parameterName": "P_ARTICLE_NUMBER", "dataType": "java.lang.String" }
      ],
      "fieldList": [
        { "fieldName": "articleNumber", "dataType": "java.lang.String" },
        { "fieldName": "description",   "dataType": "java.lang.String" },
        { "fieldName": "moq",           "dataType": "java.lang.Integer" },
        { "fieldName": "deliveryTime",  "dataType": "java.lang.String" },
        { "fieldName": "supplier",      "dataType": "java.lang.String" },
        { "fieldName": "barcode",       "dataType": "java.lang.String" }
      ]
    }
  },
  "status": 400
}
```

If a `ReportHistoryRecord` was requested (`createHistoryRecord: true`), it is still created even when the render fails — the error is recorded in the history entry, which makes it possible to review failed renders from the frontend alongside successful ones.

</div>