Upload PDFs and run AI extraction against your templates programmatically. Every response is JSON.
Generate a key from Settings → API Keys. Send it as a bearer token on every request:
Authorization: Bearer pd_...Keys are shown once at creation and only their hash is stored afterward — if you lose one, revoke it and create a new one. There is no separate test/live mode; a key works against your account's real templates, documents, and credit balance.
60 requests per rolling 60-second window, per key. Requests beyond that return 429 with a message telling you the limit.
Errors are a JSON object with an error string and one of these status codes:
400 Bad request (missing/invalid field)
401 Missing, invalid, or revoked API key
402 Not enough page-credits for this document -- upgrade your plan
404 Document or template not found (or not yours)
429 Rate limit exceeded
500 Something failed on our endUpload a PDF or image (JPEG, PNG, GIF, WebP — Claude reads images natively, no separate OCR step) and run extraction against a template in one call:
curl https://<your-domain>/api/v1/documents \
-H "Authorization: Bearer pd_..." \
-F "file=@invoice.pdf" \
-F "template_id=<template_id>"Omit template_id to just upload the file, then trigger extraction later with a separate call to POST /api/v1/documents/{id}/extract.
/api/v1/templatesList your templates, so you know which template_id to pass when uploading or extracting.
curl https://<your-domain>/api/v1/templates \
-H "Authorization: Bearer pd_..."
{
"templates": [
{ "id": "...", "name": "Invoice", "description": null, "fields": [...], "created_at": "..." }
]
}/api/v1/documentsUpload a file as multipart/form-data. Accepts application/pdf (max 20MB) or an image — image/jpeg, image/png, image/gif, or image/webp (max 10MB). Pass template_id to also run extraction in the same request.
curl https://<your-domain>/api/v1/documents \
-H "Authorization: Bearer pd_..." \
-F "file=@invoice.pdf" \
-F "template_id=<template_id>"
# 201 Created
{
"document": { "id": "...", "filename": "invoice.pdf", "status": "completed", ... },
"extraction": { "id": "...", "status": "success", "extracted_data": { ... }, ... }
}If extraction fails after a successful upload, you still get 201 with an extraction_error field alongside the uploaded document instead of an extraction field.
/api/v1/documentsList your documents, newest first. Supports limit (default 20, max 100) and offset query params.
curl "https://<your-domain>/api/v1/documents?limit=10" \
-H "Authorization: Bearer pd_..."
{ "documents": [ { "id": "...", "filename": "...", "status": "completed", ... } ], "limit": 10, "offset": 0 }/api/v1/documents/{id}Document status plus its latest extraction result, if any.
curl https://<your-domain>/api/v1/documents/<document_id> \
-H "Authorization: Bearer pd_..."
{
"document": { "id": "...", "status": "completed", ... },
"extraction": { "status": "success", "extracted_data": { ... }, ... }
}/api/v1/documents/{id}/extractRun (or re-run) extraction against an already-uploaded document.
curl -X POST https://<your-domain>/api/v1/documents/<document_id>/extract \
-H "Authorization: Bearer pd_..." \
-H "Content-Type: application/json" \
-d '{"template_id": "<template_id>"}'
{ "extraction": { "status": "success", "extracted_data": { ... }, ... } }