Generate a PDF

Send your data to the API and get a PDF back in the format you need.

Overview

To generate a PDF, send a POST request to the generate endpoint with the ID of the template you want to use and a JSON body containing the data to inject into the template. The API renders the published version of the template. Each PDF costs one credit.

Endpointbash
POST /api/v1/templates/{template_id}/generate

Request parameters

The body must be a JSON object with a data object holding your values; the other parameters are optional. An empty body is refused with a 422 (The request body is empty. Send a JSON object with a data field, for example {"data": {}}.), and so is a data that is not an object (The data field must be an object.).

ParameterTypeDefaultDescription
dataobject{}Key-value pairs to inject into the template variables.
outputstring"base64"Output format: base64, url, or binary.
filenamestring"document.pdf"Filename for the generated PDF. Letters, numbers, dashes, underscores and dots only.
url_expiryinteger60Expiry time in minutes for the temporary URL, from 1 to 1440. Only used when output is "url". A value outside this range is refused with a 422.
metadataobjectNoneDocument properties to write into the PDF: title, author, subject, keywords, creator. Each overrides the template's own value and may use {{ variables }}. Basic plan and above
signbooleanfalseReserved for an upcoming release. Currently ignored on every plan.

Output formats

Base64 (default)

Returns the PDF content as a base64-encoded string in a JSON response. Suitable for most integrations. The usage object counts the PDF you just generated.

Requestbash
curl -X POST https://pdfstork.com/api/v1/templates/1/generate \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": { "name": "Jane Doe" },
    "output": "base64"
  }'
Responsejson
{
  "success": true,
  "pdf": "JVBERi0xLjQKJeLj...",
  "filename": "document.pdf",
  "size": 12345,
  "usage": {
    "current": 42,
    "limit": 5000,
    "percentage": 0.8,
    "pack_credits": 0
  }
}

Temporary URL

Returns a signed URL that allows downloading the PDF without authentication. The URL expires after the specified url_expiry (default: 60 minutes, maximum: 1440 minutes, that is 24 hours).

Requestbash
curl -X POST https://pdfstork.com/api/v1/templates/1/generate \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": { "name": "Jane Doe" },
    "output": "url",
    "url_expiry": 120
  }'
Responsejson
{
  "success": true,
  "url": "https://de-s3.storage.bunnycdn.com/pdfapi-pdfs/pdfs/abc123.pdf?X-Amz-Signature=...",
  "filename": "document.pdf",
  "expires_at": "2026-03-30T12:00:00Z",
  "size": 12345,
  "usage": {
    "current": 42,
    "limit": 5000,
    "percentage": 0.8,
    "pack_credits": 0
  }
}

Binary

Returns the raw PDF bytes directly. Use this if you want to pipe the response to a file or stream it to the user. Set "output": "binary" in the body: sending Accept: application/pdf alone does not change the output, you would still get base64 JSON.

Requestbash
curl -X POST https://pdfstork.com/api/v1/templates/1/generate \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -o invoice.pdf \
  -d '{
    "data": { "name": "Jane Doe" },
    "output": "binary"
  }'

The response includes these headers:

  • Content-Type: application/pdf
  • Content-Disposition: attachment; filename="document.pdf"
  • Content-Length: 12345

Code examples

JavaScript (fetch)

Generate and download a PDFjavascript
const response = await fetch(
  'https://pdfstork.com/api/v1/templates/1/generate',
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_TOKEN',
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    },
    body: JSON.stringify({
      data: { name: 'Jane Doe', amount: '€1,200.00' },
      output: 'url',
    }),
  }
);

const { url } = await response.json();
console.log('Download your PDF:', url);

PHP (cURL)

Generate a PDF in PHPphp
$ch = curl_init('https://pdfstork.com/api/v1/templates/1/generate');

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer YOUR_TOKEN',
        'Content-Type: application/json',
        'Accept: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'data' => ['name' => 'Jane Doe', 'amount' => '€1,200.00'],
        'output' => 'base64',
    ]),
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

file_put_contents('invoice.pdf', base64_decode($response['pdf']));

Usage tracking

Every successful response includes a usage object showing your current monthly consumption. You can also check your usage at any time via the dedicated endpoint:

Check usagebash
curl https://pdfstork.com/api/v1/usage \
  -H "Authorization: Bearer YOUR_TOKEN"

See Rate Limits & Quotas for details on quotas per plan.

Error handling

Common error responses:

  • 401: Missing or invalid API token
  • 402: Monthly quota and prepaid credits both used up
  • 403: The template belongs to another account, your email address is not verified, or the template uses a feature your plan does not include (the body gives required_plan)
  • 404: Template not found ({"message": "Template 999 not found."})
  • 422: Validation error (check the errors object in the response), or a Twig error in an HTML template. No credit is consumed
  • 429: Rate limit exceeded (60 requests per minute per team)
Validation error examplejson
{
  "message": "The output must be one of: base64, url, binary.",
  "errors": {
    "output": [
      "The output must be one of: base64, url, binary."
    ]
  }
}
Twig error example (422)json
{
  "message": "Twig error in the template, line 2: missing endif (the if opened here is never closed)",
  "part": "template",
  "line": 2,
  "errors": {
    "template": [
      "Twig error in the template, line 2: missing endif (the if opened here is never closed)"
    ]
  }
}