Skip to main content

Single PDF Async Generation

The POST /file/async/single endpoint generates a single PDF asynchronously from the specified template and parameters. It returns a requestId and file information immediately, so the client never has to wait for rendering.

Endpoint​

  • URL: https://api.re-port-flow.com/v1/file/async/single
  • Method: POST
  • Auth: appkey header required
  • Timeout: none (async processing)
  • Request body limit: 50MB (after Base64 encoding, roughly 37MB of binary data)

Example​

cURL​

curl -X POST https://api.re-port-flow.com/v1/file/async/single \
-H "appkey: your-application-key" \
-H "Content-Type: application/json" \
-d '{
"designId": "0eUDdgAjNXrrItA2",
"version": 1,
"content": {
"fileName": "invoice.pdf",
"shareType": "01",
"passcodeEnabled": false,
"params": {
"customerName": "John Doe",
"invoiceNumber": "INV-2024-001",
"amount": 10000
}
}
}'

Request parameters​

FieldTypeRequiredDescription
designIdstring✓Template ID (16-character alphanumeric, e.g. 0eUDdgAjNXrrItA2)
versioninteger✓Template version
webhookUrlstring-Webhook destination for this request (https, up to 2048 characters). Must match the URL of an enabled webhook endpoint registered in the workspace, otherwise 400 WEBHOOK_URL_NOT_ALLOWED. When set, only that endpoint receives this request's events (details)
content.fileNamestring✓File name (any character is allowed except `/ \ : * ? " < >
content.shareTypestring-Share type on the request side is a numeric code: "01" = workspace (default), "02" = invitee, "03" = public URL. In the response, share.shareType is returned as the human-readable name (workspace / invited / public)
content.passcodeEnabledboolean-Whether to enable passcode protection (default false)
content.passthroughobject-Arbitrary metadata that will be echoed back in files[].passthrough (e.g. { "pageId": "abc123" }). Top-level strings/numbers are also stored as report-search metadata.
content.paramsobject✓Template parameters. The expected structure is available from the template parameter API

Response​

Success (202 Accepted)​

{
"requestId": "kZ3mP9qL2xV7nR4t",
"url": "https://re-port-flow.com/{workspaceId}/templates/{designId}/outputs?requestId={requestId}",
"files": [
{
"fileName": "invoice.pdf",
"fileId": "Hn4sT8wQ1cV6bX2e",
"passthrough": { "pageId": "abc123" },
"share": {
"shareType": "workspace",
"url": "https://re-port-flow.com/file/{requestId}/{fileId}",
"passcodeEnabled": false
}
}
]
}
FieldTypeDescription
requestIdstringRequest ID (16-character alphanumeric), used by the download endpoint
urlstring (URI)URL of the app screen (output history) where the generated result can be reviewed. Not a direct file download URL — use PDF download to fetch files
filesarrayGenerated files
files[].fileNamestringFile name
files[].fileIdstringFile ID, used by the per-file download endpoint
files[].passthroughobjectThe content.passthrough value supplied on the request (only when set)
files[].share.shareTypestringShare type (workspace / invited / public)
files[].share.urlstringSharable URL
files[].share.passcodeEnabledbooleanWhether passcode protection is enabled
files[].share.passcodestringServer-generated passcode (only when passcodeEnabled=true AND immediately after generation)
When to use passthrough

ReportFlow 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 to webhook endpoints.

If you need to know which business record a PDF corresponds to, put your own DB id (or any opaque token) into passthrough on the request. The exact value comes back on the response and the webhook unchanged.

{
"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.

Top-level string/number values in passthrough are also stored as report-search metadata (both in the generated PDF's XMP metadata and in the Re:port Flow app's report-search index). See passthrough and report-search metadata for which values are indexed, the limits, and why personal data doesn't belong there.

Errors​

Errors are the same shape as the synchronous endpoint. See Single PDF Sync Generation — Errors and Error Codes. If generation fails after the request was accepted (202), the reason is available from error / failedFiles in Get Generation Status. When the generation request specified webhookUrl, the file.failed webhook is also sent to that URL.

Async flow​

1. Client → API: send generation request
↓
2. API → Client: returns requestId / url / files immediately (202 Accepted)
↓
3. API: starts background PDF generation
↓
4. API: uploads the result to S3 when done (records it as failed on failure)
↓
5. Client: check completion or failure with GET /v1/file/status/{requestId}
(or receive the file.completed webhook; file.failed is sent only when webhookUrl was specified)
↓
6. Client: download the PDF via /v1/file/download/{requestId}/{fileId}
(the `url` in the response is an app-screen link and cannot be used
to download the file)

Use cases​

Case 1: background generation​

Accept the user request immediately and let the rendering happen in the background.

app.post('/api/generate-report', async (req, res) => {
const response = await axios.post(
'https://api.re-port-flow.com/v1/file/async/single',
{
designId: '...',
version: 1,
content: { fileName: 'report.pdf', params: req.body },
},
{ headers: { appkey: process.env.APP_KEY } },
);

const { requestId, url, files } = response.data;

res.status(202).json({
message: 'PDF generation started',
requestId,
fileId: files[0].fileId,
// Link to the app screen (output history) where the result can be
// reviewed. Requires a login; it is not a direct file download URL.
outputsUrl: url,
});
});

Fetch the generated file with requestId / fileId via PDF download. Authenticate with either the appkey header or an OAuth 2.0 access token (Authorization: Bearer) — see Authentication for which to pick.

Generate and fetch with credentials for the same workspace

An appkey is issued per workspace, and an OAuth 2.0 access token is bound to the workspace chosen at consent. Credentials for a different workspace than the one that generated the file cannot retrieve its requestId / fileId.

Keeping the appkey on your server, as above, fits "automating a single workspace": both generation and retrieval stay inside that appkey's workspace.

To let external or third-party users work with their own workspace data, use OAuth 2.0 Authorization Code + PKCE, have the user authorize, and issue both the generation request and the download with that same access token (required scope: pdf:generate). A file generated with the server appkey above cannot be fetched with a token for another workspace.

Use ReportFlow's built-in webhook to be notified when generation finishes — no polling required.

See the Webhook guide for details, including HMAC-SHA256 signature verification.

FAQ​

Should I use sync or async generation?​

Use Single PDF Sync Generation when you need the PDF back immediately. Use this async endpoint when generation may take more than 60 seconds, or when you want to avoid the sync timeout (60 seconds).

How do I know when generation has finished?​

Set up a webhook and you receive completion in real time with no polling — see the Webhook guide. Without a webhook, take the requestId from the response and poll Get Generation Status (GET /v1/file/status/{requestId}) until status becomes completed or failed. While generating, the response carries a Retry-After header — use it as your polling interval. See Async Workflows.

Next steps​