Sync Multiple PDF Generation (ZIP)
The POST /file/sync/multiple endpoint generates multiple PDF files synchronously from the specified design and multiple parameters, and returns them as a ZIP file.
Endpoint Information
- URL:
https://api.re-port-flow.com/v1/file/sync/multiple - Method:
POST - Authentication:
appkeyheader required - Timeout: 120 seconds (depends on file count)
- Request Size Limit: 50MB (Base64-encoded; ~37MB raw equivalent)
Usage Examples
cURL
curl -X POST https://api.re-port-flow.com/v1/file/sync/multiple \
-H "appkey: your-application-key" \
-H "Content-Type: application/json" \
-d '{
"designId": "550e8400-e29b-41d4-a716-446655440000",
"version": 1,
"contents": [
{
"fileName": "invoice_001.pdf",
"shareType": "01",
"passcodeEnabled": false,
"params": {
"customerName": "John Doe",
"invoiceNumber": "INV-001"
}
},
{
"fileName": "invoice_002.pdf",
"shareType": "02",
"passcodeEnabled": false,
"params": {
"customerName": "Jane Smith",
"invoiceNumber": "INV-002"
}
}
]
}' \
--output invoices.zip
JavaScript
const axios = require('axios');
const fs = require('fs');
async function generateMultiplePDFs(designId, contents) {
const response = await axios.post(
`https://api.re-port-flow.com/v1/file/sync/multiple`,
{
designId,
version: 1,
contents
},
{
headers: {
'appkey': process.env.APP_KEY
},
responseType: 'arraybuffer'
}
);
// Get file mapping from X-File-Mapping header
// X-File-Mapping is URL-encoded JSON; decode with decodeURIComponent → JSON.parse.
const fileMapping = JSON.parse(decodeURIComponent(response.headers['x-file-mapping']));
console.log('Generated files:', fileMapping);
return response.data; // ZIP binary
}
// Usage example
const contents = [
{
fileName: 'invoice_001.pdf',
params: { customerName: 'John Doe', invoiceNumber: 'INV-001' }
},
{
fileName: 'invoice_002.pdf',
params: { customerName: 'Jane Smith', invoiceNumber: 'INV-002' }
}
];
const zipData = await generateMultiplePDFs('550e8400-...', contents);
fs.writeFileSync('invoices.zip', zipData);
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
designId | string (UUID) | ✓ | Design ID |
version | integer | ✓ | Version number |
contents | array | ✓ | Array of ContentDto (minimum 1 item) |
contents[].fileName | string | ✓ | File name (anything except / \ : * ? " < > | and control characters is allowed; must be unique within the array, case-insensitive) |
contents[].shareType | string | - | Share type (request side uses numeric codes). "01" = workspace share (default) / "02" = invited-only / "03" = public URL share. The response share.shareType returns the human-readable name. |
contents[].passcodeEnabled | boolean | - | Enable passcode protection (default: false). |
contents[].passthrough | object | - | Per-file string KV echoed back in the response X-File-Mapping[].passthrough. |
contents[].params | object | ✓ | Parameters (check structure via Design Parameters API) |
Response
Success (200 OK)
Response Body: ZIP file (binary)
Response Headers:
| Header | Description | Example |
|---|---|---|
Content-Type | Content type | application/zip |
Content-Length | File size in bytes | 307200 |
Content-Disposition | File name | attachment; filename="files.zip" |
File-URL | ZIP download URL | https://api.re-port-flow.com/v1/file/download/{requestId} |
Request-Id | Request ID | 550e8400-e29b-41d4-a716-446655440000 |
X-File-Mapping | File metadata and share info (JSON array). URL-encoded, so clients must call decodeURIComponent before JSON.parse. | See below |
Structure of X-File-Mapping:
[
{
"fileId": "aaa111",
"fileName": "invoice_001.pdf",
"passthrough": { "pageId": "abc123" },
"share": {
"shareType": "workspace",
"url": "https://app.re-port-flow.com/file/{requestId}/aaa111",
"passcodeEnabled": false
}
},
{
"fileId": "bbb222",
"fileName": "invoice_002.pdf",
"share": {
"shareType": "invited",
"url": "https://app.re-port-flow.com/file/{requestId}/bbb222",
"passcodeEnabled": false
}
}
]
The passthrough field is included only on entries where contents[].passthrough was set on the request.
passthroughReportFlow does not echo back params (the data used to render the
PDF) on responses or webhooks, both for payload size and to avoid
leaking business data.
If you need to know which business record each PDF corresponds to, put
your own DB id (or any opaque token) into passthrough on the request.
The exact value comes back unchanged on responses and webhooks.
{
"fileName": "invoice.pdf",
"passthrough": { "invoiceId": "INV-001", "tenantId": "acme" },
"params": { "customerName": "John Doe", "amount": 10000 }
}
When the webhook arrives, look up your DB by invoiceId to find the
record to update. params (the customer name, amount, etc.) is never
sent off-server.
Errors
In addition to the same error responses as Single PDF Sync Generation — Errors, the following error may be returned:
400 Bad Request (duplicate fileName)
{
"statusCode": 400,
"message": [
"Duplicate fileName in contents (case-insensitive). Each file must have a unique name."
],
"error": "Bad Request"
}
Cause: two or more entries in contents share the same fileName (case-insensitive).
Use Cases
Bulk Monthly Invoice Generation
async function generateMonthlyInvoices(month) {
// Get invoice data for the month
const invoices = await getInvoicesByMonth(month);
// Create ContentDto array
const contents = invoices.map(invoice => ({
fileName: `invoice_${invoice.number}.pdf`,
params: invoice
}));
// Bulk generation
const zipData = await generateMultiplePDFs('invoice-template-id', contents);
// Save ZIP file
fs.writeFileSync(`invoices_${month}.zip`, zipData);
}
Next Steps
- Async Multiple PDF Generation - To avoid timeout
- File Download - How to download generated ZIP files