Docs

API Reference

Complete reference for every PDFPipe endpoint, including request parameters, response schemas, authentication, and error handling.

Base URL

All API requests are made to:

https://api.pdfpipe.dev/v1

HTTPS is required for all requests. HTTP connections are rejected.

Authentication

Authenticate by including your API key in the Authorization header:

Authorization: Bearer pk_live_...

API keys are created in the Dashboard. Each key can optionally be restricted to specific IP addresses. Keys start with pk_live_ and are shown only once at creation.

Convert a PDF

POST/v1/convert

Convert a PDF from a URL into your chosen output format. Files under 10 MB are processed synchronously (200). Larger files, requests with async: true, or jobs that exceed your timeout window return a poll URL (202). Use returnMethod: "inline" to embed the converted payload in JSON when the response is synchronous (or on status when using ?returnMethod=inline).

Request body

ParameterTypeDescription
urlrequiredstringThe HTTP or HTTPS URL of the PDF. Max 2048 characters.
formatstringOutput format. One of: json, text, markdown, xml, csv, base64, binary, png, jpg, webp. Default: json.
typestringForce PDF type detection. "inline" or "attachment". Omit to auto-detect.
asyncbooleanForce asynchronous processing. Default: false.
returnMethodstringHow the result is delivered when complete: "file" (presigned resultUrl) or "inline" (content + contentType in the JSON body). Default: file.
timeoutintegerOptional. Max seconds (1–60) to attempt synchronous processing before the job is queued. Omit for default behaviour.
webhookobjectOptional. After async completion, POSTs the result to an HTTPS URL. Shape: { url: string, secret?: string }. If secret is omitted, one is generated and returned on the async response. Payloads are signed with HMAC-SHA256 (see Webhooks).

Example request

Request body
{
  "url": "https://example.com/report.pdf",
  "format": "json",
  "type": "inline",
  "async": false,
  "returnMethod": "file",
  "timeout": 30,
  "webhook": { "url": "https://example.com/hooks/pdfpipe" }
}

Responses

With returnMethod: "inline", synchronous 200 responses include content, contentType, and for binary formats (png, jpg, webp, binary, base64) contentEncoding: "base64". If inline delivery exceeds size limits, the API may return a presigned URL instead and set returnMethodFallback: true with returnMethodFallbackReason.

200 - Synchronous (returnMethod: file, default)
{
  "requestId": "req_01J9X7K2M...",
  "status": "complete",
  "format": "json",
  "pagesProcessed": 3,
  "creditsUsed": 1,
  "resultUrl": "https://pdfpipe-results.s3...",
  "expiresAt": "2026-02-23T12:00:00.000Z"
}
200 - Synchronous (returnMethod: inline)
{
  "requestId": "req_01J9X7K2M...",
  "status": "complete",
  "format": "json",
  "pagesProcessed": 3,
  "creditsUsed": 1,
  "returnMethod": "inline",
  "contentType": "application/json",
  "content": { "pages": [ { "page": 1, "text": "..." } ] },
  "returnMethodFallback": false
}
202 - Asynchronous (queued)
{
  "requestId": "req_01J9X7K2M...",
  "status": "pending",
  "pollUrl": "/v1/status/req_01J9X7K2M..."
}
202 - With webhook / timeout-to-async message (fields optional)
{
  "requestId": "req_01J9X7K2M...",
  "status": "pending",
  "pollUrl": "/v1/status/req_01J9X7K2M...",
  "webhook": {
    "url": "https://example.com/hooks/pdfpipe",
    "secret": "whsec_generated_or_provided"
  },
  "message": "Example: job queued after synchronous processing exceeded your timeout (1–60s)."
}

Webhooks

When you include webhook on a convert request that ends up asynchronous, PDFPipe POSTs to your HTTPS URL when processing finishes. The async 202 response includes webhook.url and webhook.secret (generated if you did not supply secret). Verify deliveries with HMAC-SHA256 over the raw request body using that secret; the request includes X-PDFPipe-Signature: sha256=<hex> (plus X-PDFPipe-Request-Id and X-PDFPipe-Event).

Batch Convert

POST/v1/convert/batch

Submit multiple PDF URLs for conversion in a single request. All jobs are processed asynchronously. The maximum batch size depends on your tier.

Request body

ParameterTypeDescription
urlsrequiredarrayArray of URL objects. Each must have a url field. Optional per-item: format, type, pages, metadata, returnMethod, timeout, webhook.
defaultsobjectDefault values applied to all URLs. Supports format, type, returnMethod, timeout, and webhook.

Example

Request body
{
  "urls": [
    { "url": "https://example.com/invoice-1.pdf" },
    { "url": "https://example.com/invoice-2.pdf", "format": "text" },
    {
      "url": "https://example.com/invoice-3.pdf",
      "type": "attachment",
      "returnMethod": "file",
      "webhook": { "url": "https://example.com/hooks/invoice-3" }
    }
  ],
  "defaults": {
    "format": "json",
    "returnMethod": "inline",
    "webhook": { "url": "https://example.com/hooks/batch-default" }
  }
}
202 - Response
{
  "batchId": "batch_a1b2c3d4e5f6...",
  "requests": [
    { "requestId": "req_...", "url": "https://example.com/invoice-1.pdf", "status": "queued" },
    { "requestId": "req_...", "url": "https://example.com/invoice-2.pdf", "status": "queued" },
    { "requestId": "req_...", "url": "https://example.com/invoice-3.pdf", "status": "queued" }
  ],
  "pollUrl": "/v1/batch/batch_a1b2c3d4e5f6..."
}

Poll Request Status

GET/v1/status/:requestId

Poll the status of an asynchronous conversion request. Returns the current status and, when complete, a presigned result URL or inline content depending on query parameters.

Query parameters

ParameterTypeDescription
returnMethodstringWhen complete, return embedded content and contentType (same semantics as convert). Use inline. Default behaviour matches file.

Response

Status values: pending, processing, complete, failed.

200 - Complete (default / file delivery)
{
  "requestId": "req_01J9X7K2M...",
  "status": "complete",
  "format": "json",
  "type": "inline",
  "detectedType": "inline",
  "pagesProcessed": 3,
  "creditsUsed": 1,
  "resultUrl": "https://pdfpipe-results.s3...",
  "expiresAt": "2026-02-23T12:00:00.000Z",
  "processingDurationMs": 4230,
  "createdAt": "2026-02-22T11:00:00.000Z",
  "updatedAt": "2026-02-22T11:00:04.230Z"
}
200 - Complete (?returnMethod=inline)
{
  "requestId": "req_01J9X7K2M...",
  "status": "complete",
  "format": "json",
  "type": "inline",
  "pagesProcessed": 3,
  "creditsUsed": 1,
  "returnMethod": "inline",
  "contentType": "application/json",
  "content": { "pages": [ { "page": 1, "text": "..." } ] },
  "returnMethodFallback": false,
  "processingDurationMs": 4230,
  "createdAt": "2026-02-22T11:00:00.000Z",
  "updatedAt": "2026-02-22T11:00:04.230Z"
}

Batch Status

GET/v1/batch/:batchId

Check the overall status of a batch job and get individual request results.

200 - Response
{
  "batchId": "batch_a1b2c3d4e5f6...",
  "total": 3,
  "completed": 2,
  "failed": 0,
  "pending": 1,
  "requests": [
    { "requestId": "req_...", "status": "complete", "resultUrl": "https://..." },
    { "requestId": "req_...", "status": "complete", "resultUrl": "https://..." },
    { "requestId": "req_...", "status": "processing" }
  ]
}

Usage

GET/v1/usage

Returns your current month's usage statistics.

200 - Response
{
  "month": "2026-02",
  "requestCount": 47,
  "tier": "starter"
}

API Keys

GET/v1/keys

List all API keys for your account.

200 - Response
{
  "keys": [
    {
      "keyId": "a1b2c3d4e5f6",
      "name": "Production key",
      "prefix": "pk_live_",
      "allowedIps": ["203.0.113.10"],
      "createdAt": "2026-01-15T10:00:00.000Z",
      "revokedAt": null
    }
  ]
}
POST/v1/keys

Create a new API key. The full key value is returned only in this response.

Request body
{
  "name": "Production key",
  "allowedIps": ["203.0.113.10"]
}
201 - Response
{
  "keyId": "a1b2c3d4e5f6",
  "name": "Production key",
  "prefix": "pk_live_",
  "key": "pk_live_abc123...full_key_here"
}
PATCH/v1/keys/:keyId

Update the IP allowlist on an existing API key. Pass an array of IP addresses to restrict the key, or an empty array / omit the field to allow all IPs. Cannot be used on revoked keys.

Request body
{
  "allowedIps": ["203.0.113.10", "198.51.100.0"]
}
200 - Response
{
  "keyId": "a1b2c3d4e5f6",
  "name": "Production key",
  "prefix": "pk_live_",
  "allowedIps": ["203.0.113.10", "198.51.100.0"],
  "createdAt": "2026-01-15T10:00:00.000Z"
}
DELETE/v1/keys/:keyId

Revoke an API key. Returns 204 No Content on success.

Error Codes

Errors return a JSON body with a code and human-readable message:

Error response format
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "url: URL must use http or https protocol"
  }
}
CodeHTTPDescription
UNAUTHORIZED401Invalid or missing API key.
VALIDATION_ERROR400Request body failed validation. Check the message for specifics.
NOT_FOUND404The requested resource does not exist.
FORBIDDEN403Insufficient permissions for this action.
ACCOUNT_SUSPENDED403Account is suspended. Contact support.
FILE_TOO_LARGE413PDF exceeds your tier's file size limit.
RATE_LIMIT_EXCEEDED429Monthly request limit exceeded.
SSRF_BLOCKED403URL points to a blocked private address.
ATTACHMENT_LIMIT_REACHED403Monthly attachment request limit reached (Free/Starter only).
FORMAT_NOT_ALLOWED403Output format not available on your tier.
PROCESSING_ERROR500Internal processing failure. Retry or contact support.
API_KEY_LIMIT_REACHED409Maximum number of API keys reached for this user.
MEMBER_LIMIT_REACHED409Account team member limit reached.
CHAT_NOT_AVAILABLE403Dashboard AI Help is available on Starter, Pro, and Business only.
CHAT_RATE_LIMIT_EXCEEDED429Dashboard AI Help daily limit reached (50 questions per user per day).

Rate Limits

Rate limits are applied per account on a monthly billing cycle. When you exceed your limit, requests return a 429 status. Business tier accounts can configure overage billing instead.

Dashboard AI Help is separate from PDF conversion quotas: paid plans (Starter+) include an in-dashboard assistant (Claude) at /dashboard/chat with documentation-grounded answers. Free tier does not include AI Help. Limit: 50 questions per user per calendar day (UTC). See also Getting Started.

TierRequests/moMax FileFormatsBatch SizeAPI KeysURL ExpiryAI Help
Free102 MBjson, text521 hourNo
Starter25010 MBAll 1025524 hoursYes (50/day)
Pro1,00025 MBAll 1050107 daysYes (50/day)
Business5,00050 MBAll 101002530 daysYes (50/day)