API reference
REST endpoints for programmatic access. Generate a key in Settings → API keys and pass it as Authorization: Bearer <key>.
Authentication
Authorization: Bearer ipx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys carry the extract scope by default. Treat them like passwords — they can be revoked from the dashboard at any time.
POST /api/v1/extract
Queue a PDF for extraction. Provide a public URL to the file (HTTPS, ≤ 25 MB). Returns immediately with a document ID.
curl -X POST https://insurancepdftoexcel.com/api/v1/extract \
-H "Authorization: Bearer $IPX_KEY" \
-H "Content-Type: application/json" \
-d '{
"file_url": "https://example.com/my-acord-25.pdf",
"filename": "my-acord-25.pdf",
"form_type_hint": "acord_25",
"webhook_url": "https://hooks.example.com/insurance"
}'Response (202):
{
"document_id": "5b3a…",
"status": "queued",
"status_url": "/api/v1/documents/5b3a…"
}GET /api/v1/documents/{id}
Poll the status of an extraction. Returns the full row once the worker finishes (status = done or failed).
{
"id": "5b3a…",
"filename": "my-acord-25.pdf",
"status": "done",
"form_type": "acord_25",
"form_version": "2016/03",
"confidence_score": 0.94,
"extracted_data": { /* form-specific JSON */ },
"processing_time_ms": 8214,
"webhook_status": "delivered"
}Webhooks
Pass webhook_url on the extract call and we'll POST the result there once extraction completes. One attempt, 5-second timeout — make your handler idempotent and return any 2xx status.
POST your-webhook-url
Content-Type: application/json
X-IPX-Signature: t=1745318400,v1=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b...
{
"document_id": "5b3a…",
"status": "done",
"form_type": "acord_25",
"form_version": "2016/03",
"overall_confidence": 0.94,
"extracted_data": { /* form-specific JSON */ },
"error": null
}Verifying the signature
Generate a secret in Settings → Webhooks. Once you have one, every delivery includes X-IPX-Signature: t=<unix>,v1=<hex>. The signature is HMAC-SHA256 over `${t}.${rawBody}`. Reject events whose t is more than five minutes old to defeat replay. Without a secret, deliveries still go out — just unsigned.
// Node.js example
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, header, secret) {
const [t, v1] = header.split(",").map((p) => p.split("=")[1]);
const mac = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
return timingSafeEqual(Buffer.from(mac), Buffer.from(v1));
}GET /api/v1/documents
List documents owned by your key. Cursor-paginated by document ID — pass the previous response's next_after to walk older pages.
curl -G "https://insurancepdftoexcel.com/api/v1/documents" \ --data-urlencode "limit=25" \ --data-urlencode "status=done" \ -H "Authorization: Bearer $IPX_KEY"
POST /api/v1/documents/{id}/webhook/retry
Re-fire the webhook for a finished document — handy when your endpoint was down on the original delivery. Returns whether the retry succeeded and updates webhook_status on the document.
curl -X POST "https://insurancepdftoexcel.com/api/v1/documents/$DOC/webhook/retry" \
-H "Authorization: Bearer $IPX_KEY" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://hooks.example.com/insurance"}' # optional overrideOpenAPI spec
Machine-readable spec at /api/v1/openapi.json. Drop it into Postman, Insomnia, or your codegen of choice.
Supported form types
acord_25— Certificate of Liability Insuranceacord_125— Commercial Insurance Applicationacord_130— Workers Compensation Applicationloss_run— Carrier loss run reportscoi_generic— Non-ACORD certificates of insurance
Export formats
Once an extraction is done, fetch the result as xlsx, csv, json, or acord_xml from the dashboard or by calling GET /api/documents/{id}/export?format=xlsx.
Rate limits
Per-key, per-minute. Counted on every /api/v1 request that passes auth (extract, list, get, webhook/retry). Public endpoints like /forms/supported aren't counted.
- Free / Starter — 10 req/min
- Pro — 30 req/min
- Agency — 120 req/min
- Enterprise — 600 req/min (custom on contract)
When you exceed the limit we return 429 Too Many Requests with a Retry-After header (seconds). Wait that long, then resume.
Errors & status codes
400— body validation failed (seeerrorfor details)401— missing or invalidAuthorizationheader402— monthly extraction limit reached; upgrade required403— key lacks theextractscope413— file exceeds 25 MB429— rate limit exceeded; waitRetry-Afterseconds502— extraction worker unreachable; retry safely