Overview
The SupaPDF API lets you build PDF workflows programmatically. Create jobs with chained tasks - import a file, transform it, and export the result - all in a single request.
Every operation follows the same pipeline: import → process → export. Tasks reference each other by name, and the API executes them in dependency order automatically.
Base URL
Request format
All request bodies must be JSON. Set Content-Type: application/json on every POST request.
Versioning
Current version: v1. Breaking changes ship under a new version prefix. The previous version remains available for 12 months after a new version is released.
# All requests follow this pattern
curl -X POST https://api.supapdf.com/v1/jobs \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"tasks": {
"import-1": { "operation": "import/url", "url": "..." },
"compress-1": { "operation": "compress", "input": "import-1" },
"export-1": { "operation": "export/url", "input": "compress-1" }
}
}'Authentication
All API requests require bearer token authentication. Include your API key in theAuthorization header of every request.
Key prefixes
sk_live_...Live key - counts against your plan quotask_test_...Test key - free, outputs are watermarkedNever expose API keys in client-side code or public repositories. Use environment variables and keep keys server-side only.
Revoking keys
Revoke any key from Dashboard → API Keys. Revoked keys return 401 immediately.
curl https://api.supapdf.com/v1/jobs \
-H "Authorization: Bearer sk_live_abc123..."
-H "Content-Type: application/json"{
"code": "unauthorized",
"message": "Invalid or missing API key.",
"doc_url": "https://supapdf.com/docs#authentication"
}Quickstart
Compress a PDF from a public URL and get a download link - the most common SupaPDF workflow in a single request.
Import
Define an import/url task pointing to your file.
Process
Add a compress task that takes the import as input.
Export
Add an export/url task to get a download link.
Poll or webhook
Poll GET /jobs/{id} until status is finished, or receive a webhook callback.
curl -X POST https://api.supapdf.com/v1/jobs \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"tag": "compress-example",
"tasks": {
"import-1": {
"operation": "import/url",
"url": "https://example.com/report.pdf"
},
"compress-1": {
"operation": "compress",
"input": "import-1",
"quality": "medium"
},
"export-1": {
"operation": "export/url",
"input": "compress-1"
}
}
}'// Job created
{
"id": "job_01hx4k9m2p",
"status": "processing",
"tag": "compress-example",
"created_at": "2026-05-01T10:23:00Z"
}
// After polling GET /v1/jobs/job_01hx4k9m2p
{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"result": {
"files": [{
"filename": "report.pdf",
"url": "https://cdn.supapdf.com/dl/...",
"size": 148201,
"expires_at": "2026-05-02T10:23:00Z"
}]
}
}
}
}Jobs
A job is a container for one or more tasks. Tasks can reference each other's output by task name. The API resolves the dependency graph and executes tasks in the correct order automatically.
Job lifecycle
Create a job
| Param | Type | Description |
|---|---|---|
| tasksreq | object | Named task definitions. Each key is a task name used as input by other tasks. |
| tag | string | Optional label for filtering in list endpoints. |
| webhook_url | string | URL to POST when the job finishes. Overrides account webhook settings. |
List jobs
| Param | Type | Description |
|---|---|---|
| status | string | Filter: created | processing | finished | failed |
| tag | string | Filter by tag. |
| limit | integer | Results per page. Default: 25, max: 100. |
| after | string | Pagination cursor - last ID from previous page. |
Get a job
curl "https://api.supapdf.com/v1/jobs?limit=10&status=finished" \
-H "Authorization: Bearer sk_live_..."{
"data": [
{
"id": "job_01hx4k9m2p",
"status": "finished",
"tag": "compress-example",
"created_at": "2026-05-01T10:23:00Z",
"finished_at": "2026-05-01T10:23:04Z"
}
],
"has_more": false,
"total": 1
}
// GET /v1/jobs/{id} - includes task results
{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"import-1": { "status": "finished" },
"compress-1": { "status": "finished" },
"export-1": {
"status": "finished",
"result": {
"files": [{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/...",
"size": 148201,
"expires_at": "2026-05-02T10:23:00Z"
}]
}
}
}
}Tasks
Tasks are the individual steps within a job. Each task has an operation field plus operation-specific parameters. The input field accepts a single task name or an array of names (for operations like merge).
Task lifecycle
List tasks
{
"id": "task_9xkq2v",
"job_id": "job_01hx4k9m2p",
"operation": "compress",
"status": "finished",
"created_at": "2026-05-01T10:23:00Z",
"finished_at": "2026-05-01T10:23:03Z",
"result": {
"files": [
{
"filename": "compressed.pdf",
"size": 148201,
"url": "https://cdn.supapdf.com/..."
}
]
}
}import/url
Import a file from any publicly accessible URL. The file is fetched by SupaPDF servers at job execution time.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "import/url". |
| urlreq | string | Publicly accessible URL of the file. |
| filename | string | Override the filename. Defaults to the URL filename. |
| headers | object | Custom HTTP headers when fetching (e.g. Authorization for private CDNs). |
{
"tasks": {
"import-1": {
"operation": "import/url",
"url": "https://example.com/invoice.pdf",
"filename": "invoice.pdf"
}
}
}import/upload
Get a presigned upload URL for direct file uploads from a browser or server. Create the job first, then PUT the file to the returned upload URL before the job starts.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "import/upload". |
| filenamereq | string | Name of the file to upload. |
| file_size | integer | File size in bytes. Recommended for server-side validation. |
The presigned URL expires in 30 minutes. Upload the file before the window closes.
{
"tasks": {
"import-1": {
"operation": "import/upload",
"filename": "contract.pdf"
},
"compress-1": { "operation": "compress", "input": "import-1" },
"export-1": { "operation": "export/url", "input": "compress-1" }
}
}
// Response includes an upload URL
{
"id": "job_01hx4k9m2p",
"status": "waiting_for_upload",
"tasks": {
"import-1": {
"result": {
"upload_url": "https://upload.supapdf.com/...",
"upload_method": "PUT",
"upload_expires_at": "2026-05-01T10:53:00Z"
}
}
}
}# Upload the actual file
curl -X PUT "https://upload.supapdf.com/..." \
-H "Content-Type: application/pdf" \
--data-binary @contract.pdfimport/base64
Embed a file directly in the request body as base64. Suitable for files up to 1.5 MB.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "import/base64". |
| filereq | string | Base64-encoded file content. |
| filenamereq | string | Filename including extension. |
For files larger than 1.5 MB use import/upload or import/url instead.
{
"tasks": {
"import-1": {
"operation": "import/base64",
"filename": "form.pdf",
"file": "JVBERi0xLjQKJeLjz9MKNCAwIG9iago..."
}
}
}import/s3
Import a file directly from an AWS S3 bucket. The bucket must grant SupaPDF read access via IAM or bucket policy.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "import/s3". |
| bucketreq | string | S3 bucket name. |
| keyreq | string | Object key (path) within the bucket. |
| regionreq | string | AWS region, e.g. us-east-1. |
| access_key_id | string | AWS access key ID. Can be saved in your dashboard instead. |
| secret_access_key | string | AWS secret access key. Can be saved in your dashboard instead. |
{
"tasks": {
"import-1": {
"operation": "import/s3",
"bucket": "my-documents",
"key": "contracts/2026/q1.pdf",
"region": "us-east-1",
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
"secret_access_key": "wJalrXUtnFEMI/K7MDENG..."
}
}
}compress
Reduce PDF file size by adjusting image DPI and applying compression algorithms while preserving visual fidelity at the selected quality level.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "compress". |
| inputreq | string | Task name of the import task. |
| quality | string | "low" | "medium" | "high". Default: "medium". |
highMinimal size reduction, maximum fidelitymediumBalanced - recommended for most use caseslowMaximum compression, some visible quality lossconst res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/report.pdf" },
"compress-1": { operation: "compress", input: "import-1", quality: "medium" },
"export-1": { operation: "export/url", input: "compress-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 148201,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}merge
Combine two or more PDF files into a single document. Pages are concatenated in the order the input task names are listed.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "merge". |
| inputreq | string[] | Array of import task names. Files are merged in the order listed. |
All input files must be valid PDFs. Mixed formats are not supported in a single merge.
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/cover.pdf" },
"import-2": { operation: "import/url", url: "https://example.com/appendix.pdf" },
"merge-1": { operation: "merge", input: ["import-1", "import-2"] },
"export-1": { operation: "export/url", input: "merge-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 243780,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}split
Split a PDF into multiple files by page ranges. Each range produces a separate output file.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "split". |
| inputreq | string | Import task name. |
| pages | string[] | Page range strings e.g. ["1-3","4","5-end"]. Omit to split every page individually. |
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/report.pdf" },
"split-1": { operation: "split", input: "import-1", pages: ["1-5", "6-10", "11-end"] },
"export-1": { operation: "export/url", input: "split-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output-1.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output-1.pdf",
"size": 84512,
"expires_at": "2026-05-24T10:23:00Z"
},
{
"filename": "output-2.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output-2.pdf",
"size": 63689,
"expires_at": "2026-05-24T10:23:00Z"
},
{
"filename": "output-3.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output-3.pdf",
"size": 51204,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}convert
Convert PDFs to Office formats (and vice versa). Supports Word, Excel, PowerPoint, and image formats.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "convert". |
| inputreq | string | Import task name. |
| output_formatreq | string | Target format (see supported formats below). |
Supported formats
PDF → Other
Other → PDF
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/report.pdf" },
"convert-1": { operation: "convert", input: "import-1", output_format: "docx" },
"export-1": { operation: "export/url", input: "convert-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.docx",
"url": "https://cdn.supapdf.com/dl/abc123/output.docx",
"size": 92840,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}ocr
Add a searchable text layer to a scanned PDF. The original image is preserved while text becomes selectable and searchable.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "ocr". |
| inputreq | string | Import task name. |
| language | string | Primary language using ISO 639-1 code. Default: en. |
| output_format | string | "pdf" (searchable PDF, default) or "txt" (plain text). |
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/scanned.pdf" },
"ocr-1": { operation: "ocr", input: "import-1", language: "en", output_format: "pdf" },
"export-1": { operation: "export/url", input: "ocr-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 312450,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}protect
Password-protect a PDF with an open password (encryption) and/or an owner password (permissions control).
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "protect". |
| inputreq | string | Import task name. |
| user_password | string | Password required to open the document. |
| owner_password | string | Password that controls permission restrictions. |
| allow_print | boolean | Permit printing. Default: true. |
| allow_copy | boolean | Permit text copying. Default: true. |
| allow_modify | boolean | Permit editing. Default: false. |
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/contract.pdf" },
"protect-1": { operation: "protect", input: "import-1", user_password: "open-secret", allow_print: true, allow_copy: false, allow_modify: false },
"export-1": { operation: "export/url", input: "protect-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 198340,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}unlock
Remove password protection from a PDF. You must supply the current owner or user password.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "unlock". |
| inputreq | string | Import task name. |
| passwordreq | string | Current document password. |
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/protected.pdf" },
"unlock-1": { operation: "unlock", input: "import-1", password: "open-secret" },
"export-1": { operation: "export/url", input: "unlock-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 176820,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}watermark
Add a text watermark to every page of a PDF.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "watermark". |
| inputreq | string | Import task name. |
| textreq | string | Watermark text content. |
| opacity | number | 0.0 to 1.0. Default: 0.3. |
| rotation | integer | Degrees. Default: 45. |
| font_size | integer | Points. Default: 48. |
| color | string | Hex color. Default: "#000000". |
| pages | string | "all", "1-5", "1,3,5". Default: "all". |
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/draft.pdf" },
"watermark-1": { operation: "watermark", input: "import-1", text: "CONFIDENTIAL", opacity: 0.25, rotation: 45, font_size: 52, color: "#cc0000" },
"export-1": { operation: "export/url", input: "watermark-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 204930,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}sign
Place a signature image at specific coordinates on a PDF page. Useful for programmatically applying pre-approved signature images.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "sign". |
| inputreq | string | Import task name. |
| signaturereq | string | Base64-encoded PNG of the signature. |
| page | integer | Page number (1-indexed). Default: last page. |
| x | number | X position as % of page width (0–100). |
| y | number | Y position as % of page height (0–100). |
| width | number | Signature width as % of page width. |
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/agreement.pdf" },
"sign-1": { operation: "sign", input: "import-1", signature: "iVBORw0KGgoAAAANSUhEUgAA...", page: 3, x: 60, y: 85, width: 25 },
"export-1": { operation: "export/url", input: "sign-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 187650,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}redact
Permanently remove sensitive content from a PDF. True redaction removes the underlying data from the file - it cannot be recovered, unlike covering content with a shape.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "redact". |
| inputreq | string | Import task name. |
| regionsreq | object[] | Array of { page, x, y, width, height } - all values as % of page dimensions. |
| fill_color | string | Redaction fill color. Default: "#000000". |
Redaction is permanent and irreversible. Always verify regions on a test file before processing production documents.
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/report.pdf" },
"redact-1": { operation: "redact", input: "import-1", fill_color: "#000000",
regions: [
{ page: 1, x: 10, y: 20, width: 30, height: 5 },
{ page: 2, x: 40, y: 60, width: 40, height: 4 },
]},
"export-1": { operation: "export/url", input: "redact-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 162140,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}rotate
Rotate pages in a PDF by 90, 180, or 270 degrees.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "rotate". |
| inputreq | string | Import task name. |
| anglereq | integer | Rotation angle: 90, 180, or 270. |
| pages | string | "all", "1,3", "2-4". Default: "all". |
const res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/scan.pdf" },
"rotate-1": { operation: "rotate", input: "import-1", angle: 90, pages: "1,3" },
"export-1": { operation: "export/url", input: "rotate-1" },
},
}),
});
const job = await res.json();
console.log(job.id);{
"id": "job_01hx4k9m2p",
"status": "finished",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [
{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/dl/abc123/output.pdf",
"size": 155320,
"expires_at": "2026-05-24T10:23:00Z"
}
]
}
}
}
}export/url
Generate a temporary public download URL for the processed file. Links expire after 24 hours by default.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "export/url". |
| inputreq | string | Processing task name to export. |
| filename | string | Override the output filename. |
| expires_in | integer | Link expiry in seconds. Default: 86400 (24h). Max: 604800 (7d). Premium only. |
// Task definition
{
"export-1": {
"operation": "export/url",
"input": "compress-1",
"filename": "compressed_report.pdf",
"expires_in": 3600
}
}
// Result in finished job
{
"export-1": {
"status": "finished",
"result": {
"files": [{
"filename": "compressed_report.pdf",
"size": 148201,
"url": "https://cdn.supapdf.com/dl/abc123/compressed_report.pdf",
"expires_at": "2026-05-01T11:23:00Z"
}]
}
}
}export/s3
Save the processed file directly to an AWS S3 bucket.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "export/s3". |
| inputreq | string | Processing task name to export. |
| bucketreq | string | Target S3 bucket name. |
| keyreq | string | Object key (path) to write. |
| regionreq | string | AWS region. |
| access_key_id | string | AWS access key ID. |
| secret_access_key | string | AWS secret access key. |
| acl | string | "private" | "public-read". Default: "private". |
{
"tasks": {
"export-1": {
"operation": "export/s3",
"input": "compress-1",
"bucket": "my-output-bucket",
"key": "processed/report-compressed.pdf",
"region": "us-east-1",
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
"secret_access_key": "wJalrXUtnFEMI...",
"acl": "private"
}
}
}export/base64
Return the processed file as a base64-encoded string inline in the job result. Best for small files that need to be consumed directly without a download step.
| Param | Type | Description |
|---|---|---|
| operationreq | string | Must be "export/base64". |
| inputreq | string | Processing task name to export. |
Avoid export/base64 for files larger than 1.5 MB - use export/url instead to avoid large response payloads.
{
"export-1": {
"status": "finished",
"result": {
"files": [{
"filename": "output.pdf",
"content": "JVBERi0xLjQKJeLjz9MK...",
"size": 48201,
"mime_type": "application/pdf"
}]
}
}
}Webhooks
Webhooks deliver HTTP notifications when jobs and tasks change state - eliminating polling. Register an endpoint and select the events you care about.
Events
job.createdA new job was acceptedjob.finishedAll tasks in the job completedjob.failedOne or more tasks failedtask.createdA task was queuedtask.finishedA single task completedtask.failedA single task failedSignature verification
Every delivery includes an X-SupaPDF-Signature header - an HMAC-SHA256 of the raw request body signed with your webhook secret. Always verify this before processing the payload.
// Event: job.finished
{
"event": "job.finished",
"created_at": "2026-05-01T10:23:04Z",
"data": {
"id": "job_01hx4k9m2p",
"status": "finished",
"tag": "compress-example",
"tasks": {
"export-1": {
"status": "finished",
"result": {
"files": [{
"filename": "output.pdf",
"url": "https://cdn.supapdf.com/...",
"size": 148201,
"expires_at": "2026-05-02T10:23:00Z"
}]
}
}
}
}
}Create Webhook
| Param | Type | Description |
|---|---|---|
| endpoint_urlreq | string | HTTPS URL that will receive POST requests. |
| eventsreq | string[] | Array of event types to subscribe to. |
| secret | string | Secret for payload signing. Auto-generated if omitted. |
curl -X POST https://api.supapdf.com/v1/webhooks \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"endpoint_url": "https://myapp.com/webhooks/supapdf",
"events": ["job.finished", "job.failed"]
}'{
"id": "wh_01hx4k9m2p",
"endpoint_url": "https://myapp.com/webhooks/supapdf",
"events": ["job.finished", "job.failed"],
"secret": "whsec_abc123...",
"created_at": "2026-05-01T10:00:00Z"
}List Webhooks
Returns all configured webhooks for your account.
{
"data": [
{
"id": "wh_01hx4k9m2p",
"endpoint_url": "https://myapp.com/webhooks/supapdf",
"events": ["job.finished", "job.failed"],
"created_at": "2026-05-01T10:00:00Z"
}
],
"total": 1
}Delete Webhook
Permanently removes a webhook. No further events will be delivered to the endpoint.
curl -X DELETE \
https://api.supapdf.com/v1/webhooks/wh_01hx4k9m2p \
-H "Authorization: Bearer sk_live_..."
# 204 No Content on successErrors
All error responses include a JSON body with a machine-readable code and a human-readable message.
HTTP status codes
200OKRequest succeeded201CreatedResource created204No ContentSuccessful deletion400Bad RequestInvalid body or params401UnauthorizedMissing or invalid API key402Payment RequiredPlan limit reached403ForbiddenInsufficient permissions404Not FoundResource does not exist429Too Many RequestsRate limit exceeded500Server ErrorRetry with exponential backoffApplication error codes
unauthorizedMissing or invalid API keyinsufficient_creditsAccount has no remaining creditsfile_too_largeFile exceeds plan limitunsupported_formatInput format is not supportedprocessing_failedFile could not be processedupload_timeoutFile upload was not completed in timerate_limit_exceededToo many requests - slow downinvalid_passwordIncorrect password for a protected PDF// Standard error
{
"code": "insufficient_credits",
"message": "Your account has no remaining credits.
Upgrade your plan or purchase additional credits.",
"doc_url": "https://supapdf.com/docs#errors"
}
// Validation error (400)
{
"code": "invalid_request",
"message": "Validation failed",
"errors": [
{
"field": "tasks.compress-1.quality",
"message": "Must be one of: low, medium, high"
}
]
}Rate Limits
Rate limits are enforced per API key. Exceeding a limit returns 429 Too Many Requests. Response headers tell you when the window resets.
Limits by plan
Rate limit headers
X-RateLimit-LimitMax requests allowed in the windowX-RateLimit-RemainingRequests remaining in current windowX-RateLimit-ResetUnix timestamp when window resetsRetry-AfterSeconds to wait before retrying (on 429)# Headers on every response
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1746358980
# 429 response
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json
{
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Retry after 12s.",
"retry_after": 12
}SDKs & Libraries
Official SDKs are coming soon. In the meantime, the REST API works with any HTTP client in any language.
Node.js / TypeScript
Use native fetch or any HTTP library (axios, got, ky).
Python
Use requests or httpx.
Community libraries
Community-maintained SDKs will be listed here as they become available. Building one? Let us know.
Get your API key
API access is available on Premium plans. Test keys (watermarked output) are free on all plans.
Open Dashboardconst res = await fetch("https://api.supapdf.com/v1/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUPAPDF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": {
operation: "import/url",
url: "https://example.com/report.pdf",
},
"compress-1": {
operation: "compress",
input: "import-1",
quality: "medium",
},
"export-1": {
operation: "export/url",
input: "compress-1",
},
},
}),
});
const job = await res.json();
console.log(job.id); // job_01hx4k9m2pimport os, requests
resp = requests.post(
"https://api.supapdf.com/v1/jobs",
headers={
"Authorization": f"Bearer {os.environ['SUPAPDF_API_KEY']}",
"Content-Type": "application/json",
},
json={
"tasks": {
"import-1": {
"operation": "import/url",
"url": "https://example.com/report.pdf",
},
"compress-1": {
"operation": "compress",
"input": "import-1",
"quality": "medium",
},
"export-1": {
"operation": "export/url",
"input": "compress-1",
},
}
},
)
job = resp.json()
print(job["id"]) # job_01hx4k9m2p