# PDFBolt - Scalable and Privacy‑First PDF Generation API
> PDFBolt API - generate professional PDFs from HTML, URLs, and dynamic templates using REST endpoints. Supports Node.js, Python, Java, PHP, C#, Go, Rust with Direct/Sync/Async modes, AI-powered template generation, Handlebars templates, direct S3 uploads, automation platform integrations (n8n, Make, Zapier), interactive Playground, team collaboration, GDPR compliance, and enterprise-grade privacy.
This file contains all documentation content in a single document following the llmstxt.org standard.
## PDFBolt API Documentation
PDFBolt provides REST APIs to convert HTML, URLs, and templates into pixel-perfect PDFs and manage reusable templates. It uses headless Chromium for rendering and is built for developers and businesses that need production-grade PDF generation with privacy controls, async workflows, and S3 delivery.
## Key Features
- **Three conversion modes**: Direct (PDF in response), Sync (downloadable URL), and Async (signed webhook callback).
- **Dynamic templates**: Create reusable Handlebars templates in the Dashboard, generate drafts with AI, start from the gallery, or create and manage templates programmatically through the Template API.
- **Privacy & data control**: HTML and template data used for conversions are redacted from stored logs after processing, PDFs auto-delete after 24 hours, and processing runs in the EU.
- **Direct upload to your S3-compatible bucket**: AWS, Backblaze B2, MinIO, Wasabi, DigitalOcean Spaces.
- **SDKs and examples**: Official Node.js, Python, and PHP SDKs, REST examples for Java, C#, Go, Rust, cURL, plus a Postman collection.
- **Print production**: PDF/X-4, PDF/X-1a, CMYK conversion, and ICC color profiles.
- **Free plan**: 100 documents per month, no credit card required.
## Get Started
---
## Quick Start Guide
Generate your first PDF in a few minutes with the official [Node.js SDK](/docs/sdks/nodejs), [Python SDK](/docs/sdks/python), [PHP SDK](/docs/sdks/php), cURL, Postman, or REST examples for Java, C#, Go, and Rust.
## 1. Sign Up and Get Your API Key
[Sign up](https://app.pdfbolt.com/register) for an account. Once registered, find your API key on the **API Credentials** page in your Dashboard. The free plan includes **100 document conversions per month** – no credit card required.
:::tip Quick API Testing with Postman
- Import the PDFBolt Postman collection to run API requests without writing code.
- See the [Postman Quick Start](/docs/quick-start-guide/postman) for setup details.
[](https://app.getpostman.com/run-collection/40399365-9472b2d4-c8da-4338-8774-962cc6bb9347?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D40399365-9472b2d4-c8da-4338-8774-962cc6bb9347%26entityType%3Dcollection%26workspaceId%3D3a6b1d25-d352-4c2e-8a9b-0b4fcb6d6cae#?env%5BPDFBolt%5D=W3sia2V5IjoiYmFzZV91cmwiLCJ2YWx1ZSI6Imh0dHBzOi8vYXBpLnBkZmJvbHQuY29tIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQiLCJzZXNzaW9uVmFsdWUiOiJodHRwczovL2FwaS5wZGZib2x0LmNvbSIsImNvbXBsZXRlU2Vzc2lvblZhbHVlIjoiaHR0cHM6Ly9hcGkucGRmYm9sdC5jb20iLCJzZXNzaW9uSW5kZXgiOjB9LHsia2V5IjoiQVBJX0tFWSIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6InNlY3JldCIsInNlc3Npb25WYWx1ZSI6IiIsImNvbXBsZXRlU2Vzc2lvblZhbHVlIjoiIiwic2Vzc2lvbkluZGV4IjoxfSx7ImtleSI6IndlYmhvb2tfdXJsIiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlLCJ0eXBlIjoiZGVmYXVsdCIsInNlc3Npb25WYWx1ZSI6IiIsImNvbXBsZXRlU2Vzc2lvblZhbHVlIjoiIiwic2Vzc2lvbkluZGV4IjoyfSx7ImtleSI6ImN1c3RvbVMzX3VybCIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQiLCJzZXNzaW9uVmFsdWUiOiIiLCJjb21wbGV0ZVNlc3Npb25WYWx1ZSI6IiIsInNlc3Npb25JbmRleCI6M31d)
:::
## 2. Set Up Authorization
Authenticate by adding your `API-KEY` to request headers:
```bash
API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
```
:::info Firewall Configuration
If your source URLs or webhook endpoints restrict access by source IP, allowlist PDFBolt's static outbound IP addresses.
See [IP Addresses](/docs/ip-addresses) for the full list.
:::
## 3. Make Your First Request
Choose your endpoint based on response type:
- [Direct](/docs/api-endpoints/direct) – get the PDF immediately in the response (simplest, recommended for getting started).
- [Sync](/docs/api-endpoints/sync) – get a downloadable URL in a JSON response.
- [Async](/docs/api-endpoints/async) – receive a webhook callback when ready (best for high-volume).
**Choose your endpoint:**
**Choose your source:**
**Convert a webpage to PDF:**
```bash
curl 'https://api.pdfbolt.com/v1/direct' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"format": "A4",
"printBackground": true
}' \
-o webpage.pdf
```
**Convert HTML to PDF:**
```bash
curl 'https://api.pdfbolt.com/v1/direct' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"html": "PGh0bWw+PGJvZHk+PGgxPkhlbGxvITwvaDE+PHA+VGhpcyBpcyBhIHNhbXBsZSBQREYuPC9wPjwvYm9keT48L2h0bWw+",
"format": "A4",
"printBackground": true,
"margin": {
"top": "30px",
"left": "30px"
}
}' \
-o document.pdf
```
:::info Base64 Explanation
The base64 encoded HTML above represents:
```html
Hello!This is a sample PDF.
```
:::
**Convert a template with data to PDF:**
```bash
curl 'https://api.pdfbolt.com/v1/direct' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{
"description": "Web Development",
"unit_price": "$200.00"
},
{
"description": "Design Services",
"unit_price": "$99.99"
}
]
}
}' \
-o invoice.pdf
```
:::info New to templates?
- Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
- You can also [generate templates with AI](/docs/ai-pdf-template-generation) from descriptions or reference files.
:::
:::note Expected Result
The response is the raw PDF binary, saved to the file specified by your `-o` flag. Open it to view your PDF.
:::
**Choose your source:**
**Convert a webpage and get a download URL:**
```bash
curl 'https://api.pdfbolt.com/v1/sync' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"format": "A4",
"printBackground": true
}'
```
**Convert HTML and get a download URL:**
```bash
curl 'https://api.pdfbolt.com/v1/sync' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"html": "PGh0bWw+PGJvZHk+PGgxPkhlbGxvITwvaDE+PHA+VGhpcyBpcyBhIHNhbXBsZSBQREYuPC9wPjwvYm9keT48L2h0bWw+",
"format": "A4",
"printBackground": true,
"margin": {
"top": "30px",
"left": "30px"
}
}'
```
**Convert a template with data and get a download URL:**
```bash
curl 'https://api.pdfbolt.com/v1/sync' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{
"description": "Web Development",
"unit_price": "$200.00"
},
{
"description": "Design Services",
"unit_price": "$99.99"
}
]
}
}'
```
:::info New to templates?
- Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
- You can also [generate templates with AI](/docs/ai-pdf-template-generation) from descriptions or reference files.
:::
:::note Expected Result
The response is JSON with a `documentUrl` field – fetch that URL to download your PDF (valid for 24 hours).
:::
:::info Plan requirement
The `/v1/async` endpoint is available on paid plans. Free plan users can use `/v1/direct` and `/v1/sync`.
:::
**Choose your source:**
**Convert a webpage and receive a webhook callback:**
```bash
curl 'https://api.pdfbolt.com/v1/async' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"format": "A4",
"printBackground": true,
"webhook": "https://your-app.com/webhook"
}'
```
**Convert HTML and receive a webhook callback:**
```bash
curl 'https://api.pdfbolt.com/v1/async' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"html": "PGh0bWw+PGJvZHk+PGgxPkhlbGxvITwvaDE+PHA+VGhpcyBpcyBhIHNhbXBsZSBQREYuPC9wPjwvYm9keT48L2h0bWw+",
"format": "A4",
"printBackground": true,
"margin": {
"top": "30px",
"left": "30px"
},
"webhook": "https://your-app.com/webhook"
}'
```
**Convert a template with data and receive a webhook callback:**
```bash
curl 'https://api.pdfbolt.com/v1/async' \
-H 'API-KEY: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{
"description": "Web Development",
"unit_price": "$200.00"
},
{
"description": "Design Services",
"unit_price": "$99.99"
}
]
},
"webhook": "https://your-app.com/webhook"
}'
```
:::info New to templates?
- Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
- You can also [generate templates with AI](/docs/ai-pdf-template-generation) from descriptions or reference files.
:::
:::note Expected Result
The response is JSON with a `requestId`. Your webhook URL receives a POST request with the PDF once it's ready.
:::
## 4. SDKs and Integration Guides
Use an official SDK for Node.js, Python, or PHP, or follow REST quick starts for each supported language and Postman:
## Next Steps
- [API Endpoints](/docs/api-endpoints) – Direct, Sync, Async modes and Usage Monitoring.
- [Template API](/docs/api-endpoints/template-api) – create, validate, preview, compare, save, and publish reusable templates.
- [Conversion Parameters](/docs/parameters) – customize page size, headers/footers, fonts, and more.
- [Error Handling](/docs/error-handling) – HTTP status codes and recommended actions.
- [Template Guide](/docs/pdf-templates) – reusable PDF layouts with Handlebars syntax.
---
## Official SDKs
PDFBolt SDKs wrap the Conversion API with language-specific clients, helper methods, result objects, and error classes. Use an SDK when you want a higher-level integration than calling the REST API directly.
The REST API is available from any language that can make HTTPS requests. For endpoint guides, see the [API Endpoints](/docs/api-endpoints) docs. For exact schemas and examples, use the [OpenAPI Reference](/docs/api-reference). SDKs use the same Conversion API endpoints, parameters, rate limits, and error responses as the REST API.
## Available SDKs
## When to Use an SDK
Use an official SDK if you want:
- Language-specific request and response helpers.
- Helper methods for Direct, Sync, Async, and Usage endpoints.
- Automatic raw HTML to Base64 encoding in high-level helpers.
- Result helpers such as saving Direct PDF responses to disk.
- API, network, validation, and webhook signature error classes.
The official SDKs cover PDF conversion and usage monitoring. To create and manage templates programmatically, use the [Template API](/docs/api-endpoints/template-api) over REST.
Use the REST API directly if you want full control over HTTP requests or are working in a language without an official SDK. Follow the [Quick Start Guide](/docs/quick-start-guide) or generate your own client from the [OpenAPI YAML](/openapi.yaml).
---
## Node.js SDK
The official Node.js SDK is TypeScript-first, uses native `fetch`, and is intended for server-side Node.js applications. It supports PDFBolt's Direct, Sync, Async, Usage, and webhook signature workflows.
If you prefer calling the REST API directly with `fetch`, see the [Node.js API quick start](/docs/quick-start-guide/nodeJS). For the complete API parameter reference, see [Conversion Parameters](/docs/parameters) and the [OpenAPI Reference](/docs/api-reference).
## Installation
```bash
npm install @pdfbolt/node
```
Package: [@pdfbolt/node on npm](https://www.npmjs.com/package/@pdfbolt/node)
Requires Node.js 22 or newer.
## Quick Start
This example converts `https://example.com` to a PDF, saves it as `example.pdf`, and prints the SDK version and output size.
```ts
const pdfbolt = new PDFBolt({
apiKey: process.env.PDFBOLT_API_KEY!
});
const pdf = await pdfbolt.direct.fromUrl({
url: 'https://example.com',
printBackground: true
});
await pdf.save('example.pdf');
console.log(`Using PDFBolt SDK ${VERSION}`);
console.log(`Saved ${pdf.size} bytes`);
```
## Convert a URL to PDF
Use `fromUrl()` when you want PDFBolt to load an HTTPS page and render it as a PDF.
```ts
const pdf = await pdfbolt.direct.fromUrl({
url: 'https://example.com',
format: 'A4',
printBackground: true
});
await pdf.save('url.pdf');
```
## Convert HTML to PDF
Use `fromHtml()` when you have raw HTML. The SDK automatically encodes it to Base64 for the API.
```ts
const pdf = await pdfbolt.direct.fromHtml({
html: 'Hello from PDFBolt',
format: 'A4'
});
await pdf.save('hello.pdf');
```
If you already have a Base64-encoded HTML string, use `convert()` directly. It returns the same `DirectConversionResult` as `fromHtml()`.
```ts
const pdf = await pdfbolt.direct.convert({
html: 'PGgxPkhlbGxvPC9oMT4='
});
await pdf.save('hello.pdf');
```
Header and footer templates work the same way: `fromUrl()`, `fromHtml()`, and `fromTemplate()` accept raw HTML templates and automatically encode them to Base64, while `convert()` expects Base64-encoded template values.
This rule applies to all low-level `convert()` methods: `direct.convert()`, `sync.convert()`, and `asyncConversions.convert()` send HTML and header/footer template values as provided.
See the [`headerTemplate`](/docs/parameters#headertemplate) and [`footerTemplate`](/docs/parameters#footertemplate) parameter docs for supported placeholders and examples.
```ts
const pdf = await pdfbolt.direct.fromHtml({
html: 'Invoice',
displayHeaderFooter: true,
headerTemplate: 'Invoice',
footerTemplate: 'Page of ',
margin: {
top: '20mm',
bottom: '20mm'
}
});
await pdf.save('invoice.pdf');
```
## Convert a Template to PDF
Create and publish a template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api). Then pass its template ID and JSON data to `fromTemplate()`.
```ts
const pdf = await pdfbolt.direct.fromTemplate({
templateId: '00000000-0000-0000-0000-000000000000',
templateData: {
invoiceNumber: 'INV-1001',
customerName: 'Acme Inc.',
total: '$250.00'
}
});
await pdf.save('template.pdf');
```
## Direct Results
Use `pdfbolt.direct` when you want the generated PDF returned in the HTTP response. Direct conversions return a `DirectConversionResult`.
`DirectConversionResult.buffer` always contains PDF bytes. When you pass `isEncoded: true`, PDFBolt returns Base64 text and the SDK exposes it as `DirectConversionResult.base64`. `DirectConversionResult.buffer` still contains decoded PDF bytes, so `save()` works the same way.
```ts
const pdf = await pdfbolt.direct.fromUrl({
url: 'https://example.com',
filename: 'example.pdf'
});
await pdf.save('example.pdf');
console.log(pdf.buffer); // Buffer with PDF bytes
console.log(pdf.base64); // string only when isEncoded: true, otherwise null
console.log(pdf.size);
console.log(pdf.contentType);
console.log(pdf.contentDisposition);
console.log(pdf.filename);
console.log(pdf.conversionCost);
console.log(pdf.rateLimit.minute.remaining);
console.log(pdf.headers.get('x-pdfbolt-conversion-cost'));
```
Direct, Sync, Async job, and Usage results expose parsed rate-limit values through `rateLimit`. Rate-limit fields can be `null` when a response does not include the matching header. Direct results also expose raw HTTP headers via `pdf.headers`.
## Get a Temporary URL
Use `pdfbolt.sync` when you want PDFBolt to generate the document and return a temporary download URL (valid for 24 hours).
```ts
const result = await pdfbolt.sync.fromUrl({
url: 'https://example.com'
});
console.log(result.requestId);
console.log(result.status);
console.log(result.documentUrl);
console.log(result.expiresAt);
console.log(result.duration);
console.log(result.documentSizeMb);
console.log(result.rateLimit.minute.remaining);
console.log(result.conversionCost);
```
For custom S3 uploads, pass a valid presigned URL. PDFBolt uploads the generated PDF to your S3‑compatible bucket, so `documentUrl` and `expiresAt` are `null`.
```ts
const result = await pdfbolt.sync.fromHtml({
html: 'Invoice',
customS3PresignedUrl: process.env.PDFBOLT_CUSTOM_S3_PRESIGNED_URL!
});
console.log(result.isCustomS3Bucket); // true
console.log(result.documentUrl); // null
```
Presigned URLs are usually time-limited and often single-use. Generate a new one for each conversion. See [Uploading to Your S3 Bucket](/docs/s3-bucket-upload) for setup details.
## Run an Async Conversion
Use `pdfbolt.asyncConversions` when the conversion should run in the background. The request returns an accepted job with a `requestId` immediately, and PDFBolt sends the final success or failure payload to your HTTPS webhook later.
```ts
const job = await pdfbolt.asyncConversions.fromUrl({
url: 'https://example.com',
webhook: 'https://your-app.com/webhooks/pdfbolt',
retryDelays: [5, 15, 60]
});
console.log(job.requestId);
console.log(job.rateLimit.minute.remaining);
```
[`retryDelays`](/docs/api-endpoints/async#retrydelays) are in minutes and retry the conversion attempt itself, not webhook delivery.
For async custom S3 uploads, pass a valid `customS3PresignedUrl` in the async request. After a successful upload, the final webhook has `isCustomS3Bucket: true`, `documentUrl: null`, and `expiresAt: null`.
## Verify Webhook Signatures
Use the exact raw request body received from your framework. Do not parse and re-serialize JSON before verification. Supported raw body types are `string`, `Buffer`, `Uint8Array`, `ArrayBuffer`, and `ArrayBufferView`.
When using Express, configure the webhook route with a raw body parser before calling `verifyAndParse()`:
```js
express.raw({ type: 'application/json' })
```
The `secret` value is your PDFBolt webhook signature key, not your API key. You can find the webhook signature key on the [API Credentials page](/docs/dashboard/api-keys) in the Dashboard.
```ts
const event = PDFBolt.webhooks.verifyAndParse({
rawBody,
signature: req.headers['x-pdfbolt-signature'],
secret: process.env.PDFBOLT_WEBHOOK_SECRET!
});
console.log(event.requestId);
console.log(event.status);
console.log(event.errorCode);
console.log(event.documentUrl);
```
`verifyAndParse()` verifies the HMAC signature first and parses JSON only after the signature is valid. If you only need a boolean result, use `PDFBolt.webhooks.verifySignature()`.
The SDK exposes webhook helpers through both `PDFBolt.webhooks` and the top-level `webhooks` export. Use whichever import style fits your codebase.
## Error Handling
The PDFBolt API returns one common error response shape. The SDK represents API error responses with one class: `PDFBoltAPIError`. Check `statusCode` for HTTP-level handling and `errorCode` for PDFBolt-specific causes.
```ts
PDFBoltAPIError,
PDFBoltNetworkError,
PDFBoltValidationError
} from '@pdfbolt/node';
try {
await pdfbolt.direct.fromUrl({ url: 'https://example.com' });
} catch (error) {
if (error instanceof PDFBoltValidationError) {
console.log(error.message);
} else if (error instanceof PDFBoltAPIError) {
console.log(error.statusCode);
console.log(error.timestamp);
console.log(error.errorCode);
console.log(error.errorMessage);
console.log(error.rateLimit.minute.limit);
console.log(error.rateLimit.minute.remaining);
console.log(error.rawBody);
if (error.statusCode === 401) {
console.log('Check your API key.');
}
if (error.errorCode === 'TOO_MANY_REQUESTS') {
console.log(error.rateLimit.minute.remaining);
}
} else if (error instanceof PDFBoltNetworkError) {
console.log(error.message);
} else {
throw error;
}
}
```
`PDFBoltError` is the base class for all SDK errors. `PDFBoltAPIError` is thrown when the PDFBolt API returns an HTTP error response.
Exported error classes:
```ts
PDFBoltError
PDFBoltAPIError
PDFBoltNetworkError
PDFBoltWebhookSignatureError
PDFBoltValidationError
PDFBoltConfigurationError
```
See [Error Handling](/docs/error-handling) for the full API error reference. These SDK-specific classes are worth calling out:
- `PDFBoltValidationError` is thrown before a request is sent when a high-level helper is called with missing or invalid SDK-side parameters.
- `PDFBoltConfigurationError` is thrown before a request is sent, for example when the API key is missing.
- `PDFBoltNetworkError` means the SDK did not receive a usable HTTP response, for example because of a network failure, timeout, or aborted request.
- `PDFBoltWebhookSignatureError` is thrown by `verifyAndParse()` when the webhook signature is invalid.
## Advanced Client Options
```ts
const pdfbolt = new PDFBolt({
apiKey: process.env.PDFBOLT_API_KEY!,
requestTimeoutMs: 120_000
});
```
The SDK does not automatically retry failed requests. One SDK method call sends at most one HTTP request. For async conversion retries handled by PDFBolt, use the `retryDelays` conversion parameter.
`requestTimeoutMs` is the SDK HTTP timeout. The default is `120_000` ms. The conversion `timeout` option is different: it is sent to the PDFBolt API and controls the browser render timeout for the PDF conversion.
The SDK sends `User-Agent: pdfbolt-node/` on requests to the PDFBolt API. This helps identify SDK traffic for support and debugging. To set headers for the page being rendered by Chromium, use the conversion `extraHTTPHeaders` parameter.
Common conversion options such as `format`, `margin`, `printBackground`, `contentDisposition`, `filename`, and `compression` use the same names as the REST API. See [Conversion Parameters](/docs/parameters) for the full parameter reference.
## CommonJS
Use `require()` if your Node.js project uses CommonJS.
```js
const { PDFBolt } = require('@pdfbolt/node');
const pdfbolt = new PDFBolt({
apiKey: process.env.PDFBOLT_API_KEY
});
```
## Usage
Use `pdfbolt.usage.get()` to read the current account plan, remaining conversion credits, and rate-limit metadata.
```ts
const usage = await pdfbolt.usage.get();
console.log(usage.plan);
console.log(usage.recurring);
console.log(usage.oneTime);
console.log(usage.rateLimit.day.remaining);
```
## SDK Reference
Main client methods:
```ts
pdfbolt.direct.convert(...)
pdfbolt.direct.fromUrl(...)
pdfbolt.direct.fromHtml(...)
pdfbolt.direct.fromTemplate(...)
pdfbolt.sync.convert(...)
pdfbolt.sync.fromUrl(...)
pdfbolt.sync.fromHtml(...)
pdfbolt.sync.fromTemplate(...)
pdfbolt.asyncConversions.convert(...)
pdfbolt.asyncConversions.fromUrl(...)
pdfbolt.asyncConversions.fromHtml(...)
pdfbolt.asyncConversions.fromTemplate(...)
pdfbolt.usage.get(...)
```
Webhook helpers:
```ts
PDFBolt.webhooks.verifySignature(...)
PDFBolt.webhooks.verifyAndParse(...)
webhooks.verifySignature(...)
webhooks.verifyAndParse(...)
```
Common runtime exports:
```ts
PDFBolt
DirectConversionResult
VERSION
Webhooks
webhooks
PDFBoltError
PDFBoltAPIError
PDFBoltNetworkError
PDFBoltWebhookSignatureError
PDFBoltValidationError
PDFBoltConfigurationError
```
TypeScript type exports include conversion request and result types, webhook event and verification option types, rate-limit metadata, cookies, margins, dimensions, and other REST API parameter types.
---
## Python SDK
The official Python SDK is typed, uses `requests`, and is intended for server-side Python applications. It supports PDFBolt's Direct, Sync, Async, Usage, and webhook signature workflows.
If you prefer calling the REST API directly with Python, see the [Python API quick start](/docs/quick-start-guide/python). For the complete API parameter reference, see [Conversion Parameters](/docs/parameters) and the [OpenAPI Reference](/docs/api-reference).
## Installation
```bash
pip install pdfbolt
```
Package: [pdfbolt on PyPI](https://pypi.org/project/pdfbolt/)
Requires Python 3.11 or newer.
## Quick Start
This example converts `https://example.com` to a PDF, saves it as `example.pdf`, and prints the SDK version and output size.
```python
from pdfbolt import PDFBolt, VERSION
pdfbolt = PDFBolt(api_key=os.environ["PDFBOLT_API_KEY"])
pdf = pdfbolt.direct.from_url(
url="https://example.com",
print_background=True,
)
pdf.save("example.pdf")
print(f"Using PDFBolt SDK {VERSION}")
print(f"Saved {pdf.size} bytes")
```
Python SDK options use `snake_case` and are mapped to PDFBolt REST API fields:
- `print_background` -> `printBackground`
- `custom_s3_presigned_url` -> `customS3PresignedUrl`
- `extra_http_headers` -> `extraHTTPHeaders`
`template_data` keys are sent unchanged, so they continue to match your template variables exactly.
## Convert a URL to PDF
Use `from_url()` when you want PDFBolt to load an HTTPS page and render it as a PDF.
```python
pdf = pdfbolt.direct.from_url(
url="https://example.com",
format="A4",
print_background=True,
)
pdf.save("url.pdf")
```
## Convert HTML to PDF
Use `from_html()` when you have raw HTML. The SDK automatically encodes it to Base64 for the API.
```python
pdf = pdfbolt.direct.from_html(
html="Hello from PDFBolt",
format="A4",
)
pdf.save("hello.pdf")
```
If you already have a Base64-encoded HTML string, use `convert()` directly. It returns the same `DirectConversionResult` as `from_html()`.
```python
pdf = pdfbolt.direct.convert({
"html": "PGgxPkhlbGxvPC9oMT4="
})
pdf.save("hello.pdf")
```
Header and footer templates work the same way: `from_url()`, `from_html()`, and `from_template()` accept raw HTML templates and automatically encode them to Base64, while `convert()` expects Base64-encoded template values.
This rule applies to all low-level `convert()` methods: `direct.convert()`, `sync.convert()`, and `async_conversions.convert()` send HTML and header/footer template values as provided.
See the [`headerTemplate`](/docs/parameters#headertemplate) and [`footerTemplate`](/docs/parameters#footertemplate) parameter docs for supported placeholders and examples.
```python
pdf = pdfbolt.direct.from_html(
html="Invoice",
display_header_footer=True,
header_template='Invoice',
footer_template='Page of ',
margin={
"top": "20mm",
"bottom": "20mm",
},
)
pdf.save("invoice.pdf")
```
## Convert a Template to PDF
Create and publish a template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api). Then pass its template ID and JSON data to `from_template()`.
```python
pdf = pdfbolt.direct.from_template(
template_id="00000000-0000-0000-0000-000000000000",
template_data={
"invoiceNumber": "INV-1001",
"customerName": "Acme Inc.",
"total": "$250.00",
},
)
pdf.save("template.pdf")
```
`template_data` is sent as provided. The SDK does not rename keys inside your template data object.
## Direct Results
Use `pdfbolt.direct` when you want the generated PDF returned in the HTTP response. Direct conversions return a `DirectConversionResult`.
`DirectConversionResult.buffer` always contains PDF bytes. When you pass `is_encoded=True`, PDFBolt returns Base64 text and the SDK exposes it as `DirectConversionResult.base64`. `DirectConversionResult.buffer` still contains decoded PDF bytes, so `save()` works the same way.
```python
pdf = pdfbolt.direct.from_url(
url="https://example.com",
filename="example.pdf",
)
pdf.save("example.pdf")
print(pdf.buffer) # bytes with PDF content
print(pdf.base64) # string only when is_encoded=True, otherwise None
print(pdf.size)
print(pdf.content_type)
print(pdf.content_disposition)
print(pdf.filename)
print(pdf.conversion_cost)
print(pdf.rate_limit.minute.remaining)
print(pdf.headers.get("x-pdfbolt-conversion-cost"))
```
Direct, Sync, Async job, and Usage results expose parsed rate-limit values through `rate_limit`. Rate-limit fields can be `None` when a response does not include the matching header. Direct results also expose raw HTTP headers through `pdf.headers`.
## Get a Temporary URL
Use `pdfbolt.sync` when you want PDFBolt to generate the document and return a temporary download URL, valid for 24 hours.
```python
result = pdfbolt.sync.from_url(url="https://example.com")
print(result.request_id)
print(result.status)
print(result.document_url)
print(result.expires_at)
print(result.duration)
print(result.document_size_mb)
print(result.rate_limit.minute.remaining)
print(result.conversion_cost)
```
For custom S3 uploads, pass a valid presigned URL. PDFBolt uploads the generated PDF to your S3-compatible bucket, so `document_url` and `expires_at` are `None`. Custom S3 uploads are available on paid plans.
```python
result = pdfbolt.sync.from_html(
html="Invoice",
custom_s3_presigned_url=os.environ["PDFBOLT_CUSTOM_S3_PRESIGNED_URL"],
)
print(result.is_custom_s3_bucket) # True
print(result.document_url) # None
```
Presigned URLs are usually time-limited and often single-use. Generate a new one for each conversion. See [Uploading to Your S3 Bucket](/docs/s3-bucket-upload) for setup details.
## Run an Async Conversion
Use `pdfbolt.async_conversions` when the conversion should run in the background. The request returns an accepted job with a `request_id` immediately, and PDFBolt sends the final success or failure payload to your HTTPS webhook later.
```python
job = pdfbolt.async_conversions.from_url(
url="https://example.com",
webhook="https://your-app.com/webhooks/pdfbolt",
retry_delays=[5, 15, 60],
)
print(job.request_id)
print(job.rate_limit.minute.remaining)
```
[`retryDelays`](/docs/api-endpoints/async#retrydelays) are in minutes and retry the conversion attempt itself, not webhook delivery.
For async custom S3 uploads, pass a valid `custom_s3_presigned_url` in the async request. After a successful upload, the final webhook has `is_custom_s3_bucket=True`, `document_url=None`, and `expires_at=None`.
## Verify Webhook Signatures
Use the exact raw request body received from your framework. Do not parse and re-serialize JSON before verification. Supported raw body types are `str`, `bytes`, `bytearray`, and `memoryview`.
For Flask, use `request.get_data()` as the raw body. For FastAPI or Starlette, use `await request.body()`.
The `secret` value is your PDFBolt webhook signature key, not your API key. You can find the webhook signature key on the [API Credentials page](/docs/dashboard/api-keys) in the Dashboard.
```python
from pdfbolt import webhooks
event = webhooks.verify_and_parse(
raw_body=raw_body,
signature=request.headers.get("x-pdfbolt-signature"),
secret=os.environ["PDFBOLT_WEBHOOK_SECRET"],
)
print(event.request_id)
print(event.status)
print(event.error_code)
print(event.document_url)
```
`verify_and_parse()` verifies the HMAC signature first and parses JSON only after the signature is valid. If you only need a boolean result, use `webhooks.verify_signature()`.
The SDK exposes webhook helpers through both `PDFBolt.webhooks` and the top-level `webhooks` export. Use whichever import style fits your codebase.
## Error Handling
The PDFBolt API returns one common error response shape. The SDK represents API error responses with one class: `PDFBoltAPIError`. Check `status_code` for HTTP-level handling and `error_code` for PDFBolt-specific causes.
```python
from pdfbolt import (
PDFBoltAPIError,
PDFBoltError,
PDFBoltNetworkError,
PDFBoltValidationError,
)
try:
pdfbolt.direct.from_url(url="https://example.com")
except PDFBoltValidationError as error:
print(error)
except PDFBoltAPIError as error:
print(error.status_code)
print(error.timestamp)
print(error.error_code)
print(error.error_message)
print(error.rate_limit.minute.limit)
print(error.rate_limit.minute.remaining)
print(error.raw_body)
if error.status_code == 401:
print("Check your API key.")
if error.error_code == "TOO_MANY_REQUESTS":
print(error.rate_limit.minute.remaining)
except PDFBoltNetworkError as error:
print(error)
except PDFBoltError:
raise
```
`PDFBoltError` is the base class for all SDK errors. `PDFBoltAPIError` is thrown when the PDFBolt API returns an HTTP error response.
Exported error classes:
```python
PDFBoltError
PDFBoltAPIError
PDFBoltNetworkError
PDFBoltWebhookSignatureError
PDFBoltValidationError
PDFBoltConfigurationError
```
See [Error Handling](/docs/error-handling) for the full API error reference. These SDK-specific classes are worth calling out:
- `PDFBoltValidationError` is thrown before a request is sent when a high-level helper is called with missing or invalid SDK-side parameters.
- `PDFBoltConfigurationError` is thrown before a request is sent, for example when the API key is missing.
- `PDFBoltNetworkError` means the SDK did not receive a usable HTTP response, for example because of a network failure, timeout, or malformed success response.
- `PDFBoltWebhookSignatureError` is thrown by `verify_and_parse()` when the webhook signature or payload is invalid.
## Advanced Client Options
```python
from pdfbolt import PDFBolt
session = requests.Session()
pdfbolt = PDFBolt(
api_key=os.environ["PDFBOLT_API_KEY"],
base_url="https://api.pdfbolt.com",
request_timeout=120.0,
session=session,
)
```
The SDK does not automatically retry failed requests. One SDK method call sends at most one HTTP request. For async conversion retries handled by PDFBolt, use the `retry_delays` conversion parameter.
`request_timeout` is the SDK HTTP timeout in seconds. The default is `120.0`. The conversion `timeout` option is different: it is sent to the PDFBolt API in milliseconds and controls the browser render timeout for the PDF conversion, for example `timeout=30000`.
The SDK sends `User-Agent: pdfbolt-python/` on requests to the PDFBolt API. This helps identify SDK traffic for support and debugging. To set headers for the page being rendered by Chromium, use the conversion `extra_http_headers` parameter.
Common conversion options such as `format`, `margin`, `print_background`, `content_disposition`, `filename`, and `compression` use Pythonic snake_case names and are mapped to the REST API request fields. See [Conversion Parameters](/docs/parameters) for the full parameter reference.
## Usage
Use `pdfbolt.usage.get()` to read the current account plan, remaining conversion credits, and rate-limit metadata.
```python
usage = pdfbolt.usage.get()
print(usage.plan)
print(usage.recurring)
print(usage.one_time)
print(usage.rate_limit.day.remaining)
```
## SDK Reference
Main client methods:
```python
pdfbolt.direct.convert(...)
pdfbolt.direct.from_url(...)
pdfbolt.direct.from_html(...)
pdfbolt.direct.from_template(...)
pdfbolt.sync.convert(...)
pdfbolt.sync.from_url(...)
pdfbolt.sync.from_html(...)
pdfbolt.sync.from_template(...)
pdfbolt.async_conversions.convert(...)
pdfbolt.async_conversions.from_url(...)
pdfbolt.async_conversions.from_html(...)
pdfbolt.async_conversions.from_template(...)
pdfbolt.usage.get(...)
```
Webhook helpers:
```python
PDFBolt.webhooks.verify_signature(...)
PDFBolt.webhooks.verify_and_parse(...)
webhooks.verify_signature(...)
webhooks.verify_and_parse(...)
```
Common runtime exports:
```python
PDFBolt
DirectConversionResult
VERSION
Webhooks
webhooks
PDFBoltError
PDFBoltAPIError
PDFBoltNetworkError
PDFBoltWebhookSignatureError
PDFBoltValidationError
PDFBoltConfigurationError
```
Typed exports are available for request dictionaries, conversion options, webhook events, result models, rate-limit metadata, cookies, margins, dimensions, and other PDFBolt API parameter types.
---
## PHP SDK
The official PHP SDK uses Guzzle and is intended for server-side PHP applications. It supports PDFBolt's Direct, Sync, Async, Usage, and webhook signature workflows.
If you prefer calling the REST API directly with PHP, see the [PHP API quick start](/docs/quick-start-guide/php). For the complete API parameter reference, see [Conversion Parameters](/docs/parameters) and the [OpenAPI Reference](/docs/api-reference).
## Installation
```bash
composer require pdfbolt/pdfbolt
```
Package: [pdfbolt/pdfbolt on Packagist](https://packagist.org/packages/pdfbolt/pdfbolt)
Requires PHP 8.2 or newer.
## Quick Start
This example converts `https://example.com` to a PDF, saves it as `example.pdf`, and prints the SDK version and output size.
```php
direct()->fromUrl('https://example.com', [
'printBackground' => true,
]);
$pdf->save('example.pdf');
echo 'Using PDFBolt SDK ' . PDFBolt::VERSION . PHP_EOL;
echo 'Saved ' . $pdf->size() . ' bytes' . PHP_EOL;
```
PHP SDK conversion parameters use the same camelCase field names as the PDFBolt REST API:
- `printBackground`
- `customS3PresignedUrl`
- `extraHTTPHeaders`
- `additionalWebhookHeaders`
`templateData` keys are sent unchanged, so they continue to match your template variables exactly.
## Convert a URL to PDF
Use `fromUrl()` when you want PDFBolt to load an HTTPS page and render it as a PDF.
```php
$pdf = $pdfbolt->direct()->fromUrl('https://example.com', [
'format' => 'A4',
'printBackground' => true,
]);
$pdf->save('url.pdf');
```
## Convert HTML to PDF
Use `fromHtml()` when you have raw HTML. The SDK automatically encodes it to Base64 for the API.
```php
$pdf = $pdfbolt->direct()->fromHtml('Hello from PDFBolt', [
'format' => 'A4',
]);
$pdf->save('hello.pdf');
```
If you already have a Base64-encoded HTML string, use `convert()` directly. It returns the same `DirectConversionResult` as `fromHtml()`.
```php
$pdf = $pdfbolt->direct()->convert([
'html' => 'PGgxPkhlbGxvPC9oMT4=',
]);
$pdf->save('hello.pdf');
```
Header and footer templates work the same way: `fromUrl()`, `fromHtml()`, and `fromTemplate()` accept raw HTML templates and automatically encode them to Base64, while `convert()` expects Base64-encoded template values.
This rule applies to all low-level `convert()` methods: `direct()->convert()`, `sync()->convert()`, and `asyncConversions()->convert()` send `html`, `headerTemplate`, and `footerTemplate` exactly as provided.
See the [`headerTemplate`](/docs/parameters#headertemplate) and [`footerTemplate`](/docs/parameters#footertemplate) parameter docs for supported placeholders and examples.
```php
$pdf = $pdfbolt->direct()->fromHtml(
'Invoice',
[
'displayHeaderFooter' => true,
'headerTemplate' => 'Invoice',
'footerTemplate' => 'Page of ',
'margin' => [
'top' => '20mm',
'bottom' => '20mm',
],
],
);
$pdf->save('invoice.pdf');
```
## Convert a Template to PDF
Create and publish a template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api). Then pass its template ID and JSON data to `fromTemplate()`.
```php
$pdf = $pdfbolt->direct()->fromTemplate(
'00000000-0000-0000-0000-000000000000',
[
'invoiceNumber' => 'INV-1001',
'customerName' => 'Acme Inc.',
'total' => '$250.00',
],
);
$pdf->save('template.pdf');
```
Pass `templateData` as an associative array. The SDK does not rename keys inside your template data.
For nested empty JSON objects inside `templateData`, use `(object) []`. Plain `[]` is encoded by PHP as a JSON array.
## Direct Results
Use `direct()` when you want the generated PDF returned in the HTTP response. Direct conversions return a `DirectConversionResult`.
`DirectConversionResult->buffer` always contains PDF bytes. When you pass `isEncoded => true`, PDFBolt returns Base64 text and the SDK exposes it as `DirectConversionResult->base64`. `DirectConversionResult->buffer` still contains decoded PDF bytes, so `save()` works the same way.
```php
$pdf = $pdfbolt->direct()->fromUrl('https://example.com', [
'filename' => 'example.pdf',
]);
$pdf->save('example.pdf');
echo $pdf->buffer;
echo $pdf->base64; // string only when isEncoded is true, otherwise null
echo $pdf->size();
echo $pdf->contentType;
echo $pdf->contentDisposition;
echo $pdf->filename;
echo $pdf->conversionCost;
echo $pdf->rateLimit->minute->remaining;
echo $pdf->headers['x-pdfbolt-conversion-cost'][0] ?? null;
```
Direct, Sync, Async job, and Usage results expose parsed rate-limit values through `rateLimit`. Rate-limit fields can be `null` when a response does not include the matching header. Direct results also expose raw HTTP headers through `$pdf->headers`.
## Get a Temporary URL
Use `sync()` when you want PDFBolt to generate the document and return a temporary download URL, valid for 24 hours.
```php
$result = $pdfbolt->sync()->fromUrl('https://example.com');
echo $result->requestId;
echo $result->status;
echo $result->documentUrl;
echo $result->expiresAt;
echo $result->duration;
echo $result->documentSizeMb;
echo $result->rateLimit->minute->remaining;
echo $result->conversionCost;
```
For custom S3 uploads, pass a valid presigned URL. PDFBolt uploads the generated PDF to your S3-compatible bucket, so `documentUrl` and `expiresAt` are `null`. Custom S3 uploads are available on paid plans.
```php
$result = $pdfbolt->sync()->fromHtml('Invoice', [
'customS3PresignedUrl' => getenv('PDFBOLT_CUSTOM_S3_PRESIGNED_URL')
?: throw new RuntimeException('Set PDFBOLT_CUSTOM_S3_PRESIGNED_URL.'),
]);
var_dump($result->isCustomS3Bucket); // true
var_dump($result->documentUrl); // null
```
Presigned URLs are usually time-limited and often single-use. Generate a new one for each conversion. See [Uploading to Your S3 Bucket](/docs/s3-bucket-upload) for setup details.
## Run an Async Conversion
Use `asyncConversions()` when the conversion should run in the background. The request returns an accepted job with a `requestId` immediately, and PDFBolt sends the final success or failure payload to your HTTPS webhook later.
```php
$job = $pdfbolt->asyncConversions()->fromUrl(
'https://example.com',
'https://your-app.com/webhooks/pdfbolt',
[
'retryDelays' => [5, 15, 60],
],
);
echo $job->requestId;
echo $job->rateLimit->minute->remaining;
```
[`retryDelays`](/docs/api-endpoints/async#retrydelays) are in minutes and retry the conversion attempt itself, not webhook delivery.
For async custom S3 uploads, pass a valid `customS3PresignedUrl` in the async request. After a successful upload, the final webhook has `isCustomS3Bucket=true`, `documentUrl=null`, and `expiresAt=null`.
## Verify Webhook Signatures
Use the exact raw request body received from your framework. Do not parse and re-serialize JSON before verification.
For plain PHP handlers, use `file_get_contents('php://input')`. For Laravel and Symfony, use `$request->getContent()` as the raw body. For PSR-7 frameworks, read `(string) $request->getBody()` before any middleware consumes or modifies the body stream.
The `secret` value is your PDFBolt webhook signature key, not your API key. You can find the webhook signature key on the [API Credentials page](/docs/dashboard/api-keys) in the Dashboard.
```php
use PDFBolt\PDFBolt;
$event = PDFBolt::webhooks()->verifyAndParse(
rawBody: $request->getContent(),
signature: $request->headers->get('x-pdfbolt-signature'),
secret: getenv('PDFBOLT_WEBHOOK_SECRET') ?: throw new RuntimeException('Set PDFBOLT_WEBHOOK_SECRET.'),
);
echo $event->requestId;
echo $event->status;
echo $event->errorCode;
echo $event->documentUrl;
```
`verifyAndParse()` verifies the HMAC signature first and parses JSON only after the signature is valid. If you only need a boolean result, use `verifySignature()`.
## Error Handling
The PDFBolt API returns one common error response shape. The SDK represents API error responses with one class: `PDFBoltApiException`. Check `statusCode` for HTTP-level handling and `errorCode` for PDFBolt-specific causes.
```php
use PDFBolt\Exceptions\PDFBoltApiException;
use PDFBolt\Exceptions\PDFBoltException;
use PDFBolt\Exceptions\PDFBoltNetworkException;
use PDFBolt\Exceptions\PDFBoltValidationException;
try {
$pdfbolt->direct()->fromUrl('https://example.com');
} catch (PDFBoltValidationException $error) {
echo $error->getMessage();
} catch (PDFBoltApiException $error) {
echo $error->statusCode;
echo $error->timestamp;
echo $error->errorCode;
echo $error->errorMessage;
echo $error->rateLimit->minute->limit;
echo $error->rateLimit->minute->remaining;
echo $error->rawBody;
if ($error->statusCode === 401) {
echo 'Check your API key.';
}
} catch (PDFBoltNetworkException $error) {
echo $error->getMessage();
} catch (PDFBoltException $error) {
throw $error;
}
```
See [Error Handling](/docs/error-handling) for the full API error reference.
`PDFBoltException` is the base class for all SDK errors. These SDK-specific classes are worth calling out:
- `PDFBoltValidationException` is thrown before a request when SDK-side parameters are invalid.
- `PDFBoltConfigurationException` is thrown before a request when SDK configuration, such as the API key or global request timeout, is missing or invalid.
- `PDFBoltNetworkException` means the SDK did not receive a usable API response, for example because of a network failure, SDK HTTP timeout, or malformed success response.
- `PDFBoltWebhookSignatureException` is thrown by `verifyAndParse()` when the webhook signature or payload is invalid.
Available error classes:
```php
PDFBoltException
PDFBoltApiException
PDFBoltNetworkException
PDFBoltWebhookSignatureException
PDFBoltValidationException
PDFBoltConfigurationException
```
## Advanced Client Options
```php
use GuzzleHttp\Client;
use PDFBolt\PDFBolt;
$httpClient = new Client();
$pdfbolt = new PDFBolt(
apiKey: getenv('PDFBOLT_API_KEY') ?: throw new RuntimeException('Set PDFBOLT_API_KEY.'),
baseUrl: 'https://api.pdfbolt.com',
requestTimeout: 120.0,
httpClient: $httpClient,
);
```
Pass a custom Guzzle client when you need custom transport configuration such as a proxy, instrumentation, or a test handler.
The SDK does not automatically retry failed requests. One SDK method call sends at most one HTTP request. If your application retries, use idempotent inputs and generate a fresh presigned URL for each custom S3 retry. For async conversion retries handled by PDFBolt, use the `retryDelays` conversion parameter.
`requestTimeout` is the SDK HTTP timeout in seconds. The default is `120.0`. It is different from the conversion `timeout` option sent to the PDFBolt API, which is a browser render timeout in milliseconds, for example `timeout => 30000`.
Each conversion request can override the SDK HTTP timeout by passing `requestTimeout` in the options array:
```php
$pdf = $pdfbolt->direct()->fromUrl('https://example.com', [
'requestTimeout' => 180.0,
]);
```
For usage requests, pass the SDK HTTP timeout directly:
```php
$usage = $pdfbolt->usage()->get(180.0);
```
The SDK sends `User-Agent: pdfbolt-php/` on requests to the PDFBolt API. This helps identify SDK traffic for support and debugging. To set headers for the page being rendered by Chromium, use the conversion `extraHTTPHeaders` parameter.
Common conversion options such as `format`, `margin`, `printBackground`, `contentDisposition`, `filename`, and `compression` use the same names as the REST API. See [Conversion Parameters](/docs/parameters) for the full parameter reference.
## Usage
Use `usage()->get()` to read the current account plan, remaining conversion credits, and rate-limit metadata.
```php
$usage = $pdfbolt->usage()->get();
echo $usage->plan;
print_r($usage->recurring);
print_r($usage->oneTime);
echo $usage->rateLimit->day->remaining;
```
## SDK Reference
Main client methods:
```text
$pdfbolt->direct()->convert(array $params);
$pdfbolt->direct()->fromUrl(string $url, array $options = []);
$pdfbolt->direct()->fromHtml(string $html, array $options = []);
$pdfbolt->direct()->fromTemplate(string $templateId, array $templateData, array $options = []);
$pdfbolt->sync()->convert(array $params);
$pdfbolt->sync()->fromUrl(string $url, array $options = []);
$pdfbolt->sync()->fromHtml(string $html, array $options = []);
$pdfbolt->sync()->fromTemplate(string $templateId, array $templateData, array $options = []);
$pdfbolt->asyncConversions()->convert(array $params);
$pdfbolt->asyncConversions()->fromUrl(string $url, string $webhook, array $options = []);
$pdfbolt->asyncConversions()->fromHtml(string $html, string $webhook, array $options = []);
$pdfbolt->asyncConversions()->fromTemplate(string $templateId, array $templateData, string $webhook, array $options = []);
$pdfbolt->usage()->get(?float $requestTimeout = null);
```
Webhook helpers:
```text
PDFBolt::webhooks()->verifySignature(string $rawBody, string|array|null $signature, string $secret);
PDFBolt::webhooks()->verifyAndParse(string $rawBody, string|array|null $signature, string $secret);
```
Common runtime classes:
```text
PDFBolt
DirectConversionResult
SyncConversionResult
AsyncConversionJob
AsyncConversionWebhookEvent
UsageSummary
RateLimitInfo
PDFBoltException
PDFBoltApiException
PDFBoltNetworkException
PDFBoltWebhookSignatureException
PDFBoltValidationException
PDFBoltConfigurationException
```
Namespaces are omitted in the reference lists for readability; result classes live under `PDFBolt\Results`, exception classes under `PDFBolt\Exceptions`, and the client class lives under `PDFBolt`.
---
## Node.js PDF Generation: Quick Start Guide
# Quick Start for Node.js
Integrate PDFBolt's REST API in Node.js to generate PDFs from URLs, HTML, or templates. The examples below cover all three conversion modes (Direct, Sync, Async).
:::tip Official Node.js SDK
Want typed helper methods, automatic HTML encoding, and SDK error classes?
See the [Node.js SDK guide](/docs/sdks/nodejs).
:::
## 1. Get Your API Key
Find your API key on the **API Credentials** page in your Dashboard. If you don't have an account, [sign up](https://app.pdfbolt.com/register) – the free plan includes 100 document conversions per month.
## 2. Make Your First Request
Any HTTP client works – adjust the request structure to match your library. Examples use native `fetch` (Node.js 18+).
**Choose your endpoint:**
The **Direct** endpoint provides immediate PDF generation and returns the raw PDF file in the response.
**Choose your source:**
**Convert a webpage to PDF:**
```js
const fs = require('fs');
async function generatePdf() {
const response = await fetch('https://api.pdfbolt.com/v1/direct', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com',
format: 'A4',
printBackground: true
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const pdfBuffer = await response.arrayBuffer();
fs.writeFileSync('webpage.pdf', Buffer.from(pdfBuffer));
console.log('PDF generated successfully');
}
generatePdf().catch(console.error);
```
**Convert HTML to PDF** (HTML must be base64 encoded):
```js
const fs = require('fs');
async function generatePdf() {
const htmlContent = 'Hello!This is a sample PDF.';
const base64Html = Buffer.from(htmlContent).toString('base64');
const response = await fetch('https://api.pdfbolt.com/v1/direct', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: base64Html,
format: 'A4',
printBackground: true,
margin: {
top: '30px',
left: '30px'
}
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const pdfBuffer = await response.arrayBuffer();
fs.writeFileSync('document.pdf', Buffer.from(pdfBuffer));
console.log('PDF generated successfully');
}
generatePdf().catch(console.error);
```
**Convert a template with data to PDF:**
```js
const fs = require('fs');
async function generatePdf() {
const response = await fetch('https://api.pdfbolt.com/v1/direct', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
templateId: 'your-template-id',
templateData: {
client_name: 'John Doe',
invoice_number: 'INV-001',
total_amount: '$299.99',
line_items: [
{ description: 'Web Development', unit_price: '$200.00' },
{ description: 'Design Services', unit_price: '$99.99' }
]
}
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const pdfBuffer = await response.arrayBuffer();
fs.writeFileSync('invoice.pdf', Buffer.from(pdfBuffer));
console.log('PDF generated successfully');
}
generatePdf().catch(console.error);
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
The **Sync** endpoint returns a JSON response with a download URL for the PDF (valid for 24 hours).
**Choose your source:**
**Convert a webpage and get a download URL:**
```js
async function generatePdf() {
const response = await fetch('https://api.pdfbolt.com/v1/sync', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com',
format: 'A4',
printBackground: true
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const result = await response.json();
console.log('PDF URL:', result.documentUrl);
}
generatePdf().catch(console.error);
```
**Convert HTML and get a download URL** (HTML must be base64 encoded):
```js
async function generatePdf() {
const htmlContent = 'Hello!This is a sample PDF.';
const base64Html = Buffer.from(htmlContent).toString('base64');
const response = await fetch('https://api.pdfbolt.com/v1/sync', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: base64Html,
format: 'A4',
printBackground: true,
margin: {
top: '30px',
left: '30px'
}
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const result = await response.json();
console.log('PDF URL:', result.documentUrl);
}
generatePdf().catch(console.error);
```
**Convert a template with data and get a download URL:**
```js
async function generatePdf() {
const response = await fetch('https://api.pdfbolt.com/v1/sync', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
templateId: 'your-template-id',
templateData: {
client_name: 'John Doe',
invoice_number: 'INV-001',
total_amount: '$299.99',
line_items: [
{ description: 'Web Development', unit_price: '$200.00' },
{ description: 'Design Services', unit_price: '$99.99' }
]
}
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const result = await response.json();
console.log('PDF URL:', result.documentUrl);
}
generatePdf().catch(console.error);
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
The **Async** endpoint returns a `requestId` immediately and delivers the final result via webhook callback.
**Choose your source:**
**Convert a webpage and receive a webhook callback:**
```js
async function generatePdf() {
const response = await fetch('https://api.pdfbolt.com/v1/async', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com',
format: 'A4',
printBackground: true,
webhook: 'https://your-app.com/webhook'
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const result = await response.json();
console.log('Request ID:', result.requestId);
console.log('PDF will be sent to webhook when ready');
}
generatePdf().catch(console.error);
```
**Convert HTML and receive a webhook callback** (HTML must be base64 encoded):
```js
async function generatePdf() {
const htmlContent = 'Hello!This is a sample PDF.';
const base64Html = Buffer.from(htmlContent).toString('base64');
const response = await fetch('https://api.pdfbolt.com/v1/async', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: base64Html,
format: 'A4',
printBackground: true,
margin: {
top: '30px',
left: '30px'
},
webhook: 'https://your-app.com/webhook'
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const result = await response.json();
console.log('Request ID:', result.requestId);
console.log('PDF will be sent to webhook when ready');
}
generatePdf().catch(console.error);
```
**Convert a template with data and receive a webhook callback:**
```js
async function generatePdf() {
const response = await fetch('https://api.pdfbolt.com/v1/async', {
method: 'POST',
headers: {
'API-KEY': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type': 'application/json'
},
body: JSON.stringify({
templateId: 'your-template-id',
templateData: {
client_name: 'John Doe',
invoice_number: 'INV-001',
total_amount: '$299.99',
line_items: [
{ description: 'Web Development', unit_price: '$200.00' },
{ description: 'Design Services', unit_price: '$99.99' }
]
},
webhook: 'https://your-app.com/webhook'
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const result = await response.json();
console.log('Request ID:', result.requestId);
console.log('PDF will be sent to webhook when ready');
}
generatePdf().catch(console.error);
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
## Next Steps
:::tip Related reading
- [How to Convert HTML to PDF Using an API](/blog/how-to-convert-html-to-pdf-using-api) – complete Node.js tutorial with EJS templates and invoice example.
- [How to Generate Invoice PDFs with an API](/blog/generate-invoice-pdf-api) – invoice automation with a Node.js example.
:::
---
## Python PDF Generation: Quick Start Guide
# Quick Start for Python
Integrate PDFBolt's REST API in Python to generate PDFs from URLs, HTML, or templates. The examples below cover all three conversion modes (Direct, Sync, Async).
:::tip Official Python SDK
Want type-hinted helper methods, automatic HTML encoding, and SDK error classes?
See the [Python SDK guide](/docs/sdks/python).
:::
## 1. Get Your API Key
Find your API key on the **API Credentials** page in your Dashboard. If you don't have an account, [sign up](https://app.pdfbolt.com/register) – the free plan includes 100 document conversions per month.
## 2. Make Your First Request
Any HTTP client works – adjust the request structure to match your library.
Examples use the `requests` library. Install it with:
```bash
pip install requests
```
**Choose your endpoint:**
The **Direct** endpoint provides immediate PDF generation and returns the raw PDF file in the response.
**Choose your source:**
**Convert a webpage to PDF:**
```python
url = "https://api.pdfbolt.com/v1/direct"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"url": "https://example.com",
"format": "A4",
"printBackground": True
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
with open('webpage.pdf', 'wb') as f:
f.write(response.content)
print("PDF generated successfully")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
**Convert HTML to PDF** (HTML must be base64 encoded):
```python
html_content = "Hello!This is a sample PDF."
base64_html = base64.b64encode(html_content.encode()).decode()
url = "https://api.pdfbolt.com/v1/direct"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"html": base64_html,
"format": "A4",
"printBackground": True,
"margin": {
"top": "30px",
"left": "30px"
}
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
with open('document.pdf', 'wb') as f:
f.write(response.content)
print("PDF generated successfully")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
**Convert a template with data to PDF:**
```python
url = "https://api.pdfbolt.com/v1/direct"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{"description": "Web Development", "unit_price": "$200.00"},
{"description": "Design Services", "unit_price": "$99.99"}
]
}
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
with open('invoice.pdf', 'wb') as f:
f.write(response.content)
print("PDF generated successfully")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
The **Sync** endpoint returns a JSON response with a download URL for the PDF (valid for 24 hours).
**Choose your source:**
**Convert a webpage and get a download URL:**
```python
url = "https://api.pdfbolt.com/v1/sync"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"url": "https://example.com",
"format": "A4",
"printBackground": True
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
result = response.json()
print(f"PDF URL: {result['documentUrl']}")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
**Convert HTML and get a download URL** (HTML must be base64 encoded):
```python
html_content = "Hello!This is a sample PDF."
base64_html = base64.b64encode(html_content.encode()).decode()
url = "https://api.pdfbolt.com/v1/sync"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"html": base64_html,
"format": "A4",
"printBackground": True,
"margin": {
"top": "30px",
"left": "30px"
}
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
result = response.json()
print(f"PDF URL: {result['documentUrl']}")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
**Convert a template with data and get a download URL:**
```python
url = "https://api.pdfbolt.com/v1/sync"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{"description": "Web Development", "unit_price": "$200.00"},
{"description": "Design Services", "unit_price": "$99.99"}
]
}
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
result = response.json()
print(f"PDF URL: {result['documentUrl']}")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
The **Async** endpoint returns a `requestId` immediately and delivers the final result via webhook callback.
**Choose your source:**
**Convert a webpage and receive a webhook callback:**
```python
url = "https://api.pdfbolt.com/v1/async"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"url": "https://example.com",
"format": "A4",
"printBackground": True,
"webhook": "https://your-app.com/webhook"
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
result = response.json()
print(f"Request ID: {result['requestId']}")
print("PDF will be sent to webhook when ready")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
**Convert HTML and receive a webhook callback** (HTML must be base64 encoded):
```python
html_content = "Hello!This is a sample PDF."
base64_html = base64.b64encode(html_content.encode()).decode()
url = "https://api.pdfbolt.com/v1/async"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"html": base64_html,
"format": "A4",
"printBackground": True,
"margin": {
"top": "30px",
"left": "30px"
},
"webhook": "https://your-app.com/webhook"
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
result = response.json()
print(f"Request ID: {result['requestId']}")
print("PDF will be sent to webhook when ready")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
**Convert a template with data and receive a webhook callback:**
```python
url = "https://api.pdfbolt.com/v1/async"
headers = {
"API-KEY": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Content-Type": "application/json"
}
data = {
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{"description": "Web Development", "unit_price": "$200.00"},
{"description": "Design Services", "unit_price": "$99.99"}
]
},
"webhook": "https://your-app.com/webhook"
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
result = response.json()
print(f"Request ID: {result['requestId']}")
print("PDF will be sent to webhook when ready")
except requests.exceptions.HTTPError:
print(f"HTTP {response.status_code}")
print(f"Error Message: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
## Next Steps
:::tip Related reading
- [How to Generate Invoice PDFs with an API](/blog/generate-invoice-pdf-api) – invoice automation with a Python example.
- [Print-Ready PDF Generation: PDF/X-1a and PDF/X-4 via API](/blog/print-ready-pdf-generation-pdfx1a-pdfx4) – generate print-ready PDFs, includes Python example.
:::
---
## Java PDF Generation: Quick Start Guide
# Quick Start for Java
Integrate PDFBolt's REST API in Java to generate PDFs from URLs, HTML, or templates. The examples below cover all three conversion modes (Direct, Sync, Async).
## 1. Get Your API Key
Find your API key on the **API Credentials** page in your Dashboard. If you don't have an account, [sign up](https://app.pdfbolt.com/register) – the free plan includes 100 document conversions per month.
## 2. Make Your First Request
Any HTTP client works – adjust the request structure to match your library.
Examples require Java 17+ and use the built-in `java.net.http.HttpClient` and Jackson for JSON parsing. Add Jackson to your project:
```xml
com.fasterxml.jackson.core
jackson-databind
2.21.3
```
```groovy
implementation 'com.fasterxml.jackson.core:jackson-databind:2.21.3'
```
**Choose your endpoint:**
The **Direct** endpoint provides immediate PDF generation and returns the raw PDF file in the response.
**Choose your source:**
**Convert a webpage to PDF:**
```java
public class DirectUrl {
public static void main(String[] args) throws Exception {
String jsonBody = """
{
"url": "https://example.com",
"format": "A4",
"printBackground": true
}
""";
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/direct"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() == 200) {
Files.write(Paths.get("webpage.pdf"), response.body());
System.out.println("PDF generated successfully");
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + new String(response.body()));
}
}
}
```
**Convert HTML to PDF** (HTML must be base64 encoded):
```java
public class DirectHtml {
public static void main(String[] args) throws Exception {
String htmlContent = "Hello!This is a sample PDF.";
String base64Html = Base64.getEncoder().encodeToString(htmlContent.getBytes(StandardCharsets.UTF_8));
String jsonBody = """
{
"html": "%s",
"format": "A4",
"printBackground": true,
"margin": {
"top": "30px",
"left": "30px"
}
}
""".formatted(base64Html);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/direct"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() == 200) {
Files.write(Paths.get("document.pdf"), response.body());
System.out.println("PDF generated successfully");
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + new String(response.body()));
}
}
}
```
**Convert a template with data to PDF:**
```java
public class DirectTemplate {
public static void main(String[] args) throws Exception {
String jsonBody = """
{
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{"description": "Web Development", "unit_price": "$200.00"},
{"description": "Design Services", "unit_price": "$99.99"}
]
}
}
""";
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/direct"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() == 200) {
Files.write(Paths.get("invoice.pdf"), response.body());
System.out.println("PDF generated successfully");
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + new String(response.body()));
}
}
}
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
The **Sync** endpoint returns a JSON response with a download URL for the PDF (valid for 24 hours).
**Choose your source:**
**Convert a webpage and get a download URL:**
```java
public class SyncUrl {
public static void main(String[] args) throws Exception {
String jsonBody = """
{
"url": "https://example.com",
"format": "A4",
"printBackground": true
}
""";
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/sync"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonNode root = new ObjectMapper().readTree(response.body());
String documentUrl = root.get("documentUrl").asText();
System.out.println("PDF URL: " + documentUrl);
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + response.body());
}
}
}
```
**Convert HTML and get a download URL** (HTML must be base64 encoded):
```java
public class SyncHtml {
public static void main(String[] args) throws Exception {
String htmlContent = "Hello!This is a sample PDF.";
String base64Html = Base64.getEncoder().encodeToString(htmlContent.getBytes(StandardCharsets.UTF_8));
String jsonBody = """
{
"html": "%s",
"format": "A4",
"printBackground": true,
"margin": {
"top": "30px",
"left": "30px"
}
}
""".formatted(base64Html);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/sync"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonNode root = new ObjectMapper().readTree(response.body());
String documentUrl = root.get("documentUrl").asText();
System.out.println("PDF URL: " + documentUrl);
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + response.body());
}
}
}
```
**Convert a template with data and get a download URL:**
```java
public class SyncTemplate {
public static void main(String[] args) throws Exception {
String jsonBody = """
{
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{"description": "Web Development", "unit_price": "$200.00"},
{"description": "Design Services", "unit_price": "$99.99"}
]
}
}
""";
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/sync"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonNode root = new ObjectMapper().readTree(response.body());
String documentUrl = root.get("documentUrl").asText();
System.out.println("PDF URL: " + documentUrl);
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + response.body());
}
}
}
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
The **Async** endpoint returns a `requestId` immediately and delivers the final result via webhook callback.
**Choose your source:**
**Convert a webpage and receive a webhook callback:**
```java
public class AsyncUrl {
public static void main(String[] args) throws Exception {
String jsonBody = """
{
"url": "https://example.com",
"format": "A4",
"printBackground": true,
"webhook": "https://your-app.com/webhook"
}
""";
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/async"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonNode root = new ObjectMapper().readTree(response.body());
String requestId = root.get("requestId").asText();
System.out.println("Request ID: " + requestId);
System.out.println("PDF will be sent to webhook when ready");
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + response.body());
}
}
}
```
**Convert HTML and receive a webhook callback** (HTML must be base64 encoded):
```java
public class AsyncHtml {
public static void main(String[] args) throws Exception {
String htmlContent = "Hello!This is a sample PDF.";
String base64Html = Base64.getEncoder().encodeToString(htmlContent.getBytes(StandardCharsets.UTF_8));
String jsonBody = """
{
"html": "%s",
"format": "A4",
"printBackground": true,
"margin": {
"top": "30px",
"left": "30px"
},
"webhook": "https://your-app.com/webhook"
}
""".formatted(base64Html);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/async"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonNode root = new ObjectMapper().readTree(response.body());
String requestId = root.get("requestId").asText();
System.out.println("Request ID: " + requestId);
System.out.println("PDF will be sent to webhook when ready");
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + response.body());
}
}
}
```
**Convert a template with data and receive a webhook callback:**
```java
public class AsyncTemplate {
public static void main(String[] args) throws Exception {
String jsonBody = """
{
"templateId": "your-template-id",
"templateData": {
"client_name": "John Doe",
"invoice_number": "INV-001",
"total_amount": "$299.99",
"line_items": [
{"description": "Web Development", "unit_price": "$200.00"},
{"description": "Design Services", "unit_price": "$99.99"}
]
},
"webhook": "https://your-app.com/webhook"
}
""";
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.pdfbolt.com/v1/async"))
.header("API-KEY", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonNode root = new ObjectMapper().readTree(response.body());
String requestId = root.get("requestId").asText();
System.out.println("Request ID: " + requestId);
System.out.println("PDF will be sent to webhook when ready");
} else {
System.err.println("HTTP " + response.statusCode());
System.err.println("Error Message: " + response.body());
}
}
}
```
:::info New to templates?
Create and publish your first template in the [Dashboard Template Designer](/docs/dashboard/templates) or through the [Template API](/docs/api-endpoints/template-api), then use its ID in conversion requests.
See the [Template Guide](/docs/pdf-templates) for Handlebars syntax and examples.
:::
## Next Steps
:::tip Related reading
- [Optimizing HTML for Professional PDF Output](/blog/optimizing-html-for-pdf) – HTML/CSS techniques: page breaks, fonts, and image optimization.
- [How to Compress PDFs with Apache PDFBox in Java](/blog/pdfbox-compress-pdf-java) – Java PDF compression with Apache PDFBox, plus when a PDF generation API is the simpler alternative.
:::
---
## PHP PDF Generation: Quick Start Guide
# Quick Start for PHP
Integrate PDFBolt's REST API in PHP to generate PDFs from URLs, HTML, or templates. The examples below cover all three conversion modes (Direct, Sync, Async).
:::tip Official PHP SDK
Want helper methods, automatic HTML encoding, and SDK error classes?
See the [PHP SDK guide](/docs/sdks/php).
:::
## 1. Get Your API Key
Find your API key on the **API Credentials** page in your Dashboard. If you don't have an account, [sign up](https://app.pdfbolt.com/register) – the free plan includes 100 document conversions per month.
## 2. Make Your First Request
Any HTTP client works – adjust the request structure to match your library.
Examples use Guzzle. Install it with:
```bash
composer require guzzlehttp/guzzle
```
**Choose your endpoint:**
The **Direct** endpoint provides immediate PDF generation and returns the raw PDF file in the response.
**Choose your source:**
**Convert a webpage to PDF:**
```php
'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
'Content-Type' => 'application/json',
];
$body = [
'url' => 'https://example.com',
'format' => 'A4',
'printBackground' => true,
];
try {
$client = new Client();
$response = $client->post('https://api.pdfbolt.com/v1/direct', [
'headers' => $headers,
'json' => $body,
]);
file_put_contents('webpage.pdf', (string) $response->getBody());
echo "PDF generated successfully\n";
} catch (RequestException $e) {
if ($e->hasResponse()) {
echo "HTTP " . $e->getResponse()->getStatusCode() . "\n";
echo "Error Message: " . $e->getResponse()->getBody() . "\n";
} else {
echo "Error: " . $e->getMessage() . "\n";
}
}
```
**Convert HTML to PDF** (HTML must be base64 encoded):
```php
Hello!This is a sample PDF.