Quickstart
Integrate PolDex in four steps. No dashboard. No account portal. The API is the control surface.
Step 1 — Get an API Key
Initialize API access at /initialize. Your key is shown exactly once. Store it securely in a secrets manager or environment variable.
Step 2 — Submit a document
curl -X POST https://api.poldex.io/v1/extract \
-H "x-api-key: pd_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ik_unique_per_request" \
-d '{
"document_url": "https://your.host/policy.pdf",
"schema": "commercial_gl",
"webhook_url": "https://your.app/webhook"
}'Step 3 — Receive 202 Accepted
{
"job_id": "job_01hx4mz9p3kqa8",
"status": "queued",
"idempotency_key": "ik_unique_per_request",
"created_at": "2026-04-21T10:00:00Z",
"estimated_seconds": 45,
"credits_held": 12,
"poll_url": "https://api.poldex.io/v1/jobs/job_01hx4mz9p3kqa8"
}Step 4 — Receive Result
Results arrive at your webhook_url, or poll GET /v1/jobs/{job_id}.
{
"job_id": "job_01hx4mz9p3kqa8",
"status": "complete",
"schema_id": "commercial_gl",
"schema_version": "1.0.0",
"created_at": "2026-04-21T10:00:00Z",
"updated_at": "2026-04-21T10:00:52Z",
"completed_at": "2026-04-21T10:00:52Z",
"delete_status": "none",
"credits_held": 12,
"credits_captured": 12,
"result_available": true,
"result": { "policies": [], "coverages": [], "facts": [] }
}Live Metrics
Check live platform throughput — no API key required:
curl https://api.poldex.io/v1/metrics/live
Authentication
Pass your API key in the x-api-key header, or as a Bearer token.
x-api-key: pd_live_YOUR_API_KEY # or Authorization: Bearer pd_live_YOUR_API_KEY
API keys are prefixed with pd_live_ for production and pd_test_ for test mode. Keys are shown once at issuance and are not recoverable. Rotation creates a new key via POST /v1/keys/rotate.
API Key Properties
| Property | Value |
|---|---|
| prefix | pd_live_ (production), pd_test_ (test) |
| storage | PolDex stores only a hashed version |
| recovery | Not possible — rotation creates a new key |
| rotation | POST /v1/keys/rotate — self-serve, no support contact required |
Playground
The public playground accepts one input source at a time: HTTPS URL, file upload (.pdf/.txt/.md), or pasted text. It returns the same JSON shape as GET /v1/jobs/{job_id} after completion.
No API key is required. Abuse controls are enforced server-side (size limits and per-IP rate limits).
Open playground →Live Proof Run
Want to see PolDex extract a real commercial P&C document before writing any code? The live proof page runs a real extraction against an open-source PDF and returns the actual backend response.
No API purchase and no API key are required for this proof flow.
Run live extraction →Idempotency
Include an Idempotency-Key header on all POST /v1/extract requests. This makes requests safe to retry on network failure.
Idempotency-Key: ik_2026_unique_string_per_request
If the same key is submitted twice with the same payload, PolDex returns the original accepted response without creating a new job or holding additional credits. If the same key is submitted with a different payload, the request returns 409 idempotency_conflict.
Rate Limits
Rate limits are enforced per API key. Exceeding the limit returns 429 rate_limit_exceeded. Back off and retry using exponential backoff.
Initialize
POST /v1/initialize — Create a customer record and begin the funding lifecycle. No authentication required.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| org_name | string | Yes | Organisation name |
| contact_email | string | Yes | Work email address |
| intended_use | string | Yes | Description of intended use |
| path | string | Yes | self_serve or enterprise_preload |
| prepaid_credits | integer | No | Default: 1000 |
| amount_minor | integer | No | Amount in minor currency units. Default: 25000 |
| currency | string | No | Default: usd |
| metadata | object | No | Optional string key-value pairs |
Response
{
"customer_id": "cust_01hx...",
"status": "funded",
"key_delivery": "in_page_once",
"message": "Account funded. API key issued once.",
"api_key": "pd_live_...",
"payment_status": "succeeded"
}{
"customer_id": "cust_01hx...",
"status": "pending_enterprise",
"key_delivery": "email",
"message": "Enterprise request received. We will be in contact shortly.",
"api_key": null,
"payment_status": "not_applicable"
}Status values
| Status | Meaning |
|---|---|
| funded | Payment succeeded, API key issued |
| pending_payment | Payment initiated, awaiting confirmation |
| pending_enterprise | Enterprise request submitted, awaiting follow-up |
curl example
curl -X POST https://api.poldex.io/v1/initialize \
-H "Content-Type: application/json" \
-d '{
"org_name": "Acme Risk",
"contact_email": "you@acme.com",
"intended_use": "policy extraction",
"path": "self_serve"
}'Extract API
POST /v1/extract — Submit a document for async extraction.
Required header
Idempotency-Key: <unique string per request>
Request Body
| Field | Type | Description |
|---|---|---|
| document_url | string (uri) | HTTPS URL or S3 URI to the document. Mutually exclusive with upload_ref. |
| upload_ref | string | Pre-upload reference ID. Mutually exclusive with document_url. |
| schema | string | Extraction schema ID. Default: commercial_gl |
| webhook_url | string (uri) | HTTPS endpoint to receive the signed result payload |
| client_ref | string | Optional caller-supplied reference echoed in job status |
| correlation | object | Optional string key-value pairs for caller correlation |
Response (202)
{
"job_id": "job_01hx4mz9p3kqa8",
"status": "queued",
"idempotency_key": "ik_unique_per_request",
"created_at": "2026-04-21T10:00:00Z",
"estimated_seconds": 45,
"credits_held": 12,
"poll_url": "https://api.poldex.io/v1/jobs/job_01hx4mz9p3kqa8"
}curl example
curl -X POST https://api.poldex.io/v1/extract \
-H "x-api-key: pd_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ik_$(date +%s)" \
-d '{
"document_url": "https://your.host/policy.pdf",
"schema": "commercial_gl",
"webhook_url": "https://your.app/webhook"
}'Job Status API
GET /v1/jobs/{job_id} — Retrieve job status and result.
Job Status Values
| Status | Meaning |
|---|---|
| pending | Created, not yet queued |
| queued | Accepted, awaiting worker pickup |
| processing | Worker is currently extracting |
| complete | Extraction complete, result available |
| failed | Non-billable internal failure — credits released |
| dlq | Exhausted retries, moved to dead-letter queue |
| cancelled | Cancelled before processing |
Response fields
| Field | Type | Description |
|---|---|---|
| job_id | string | Job identifier |
| status | string | Lifecycle status (see above) |
| schema_id | string | Extraction schema used |
| schema_version | string | Schema version at submission time |
| client_ref | string | null | Caller-supplied reference |
| delete_status | string | Deletion lifecycle state (none, delete_requested, delete_processing, delete_completed, delete_blocked_legal_hold) |
| credits_held | integer | Credits held at submission |
| credits_captured | integer | Credits captured on completion (0 if not complete) |
| result_available | boolean | Whether result object is populated |
| result | object | null | Structured extraction output when complete |
curl example
curl https://api.poldex.io/v1/jobs/JOB_ID \ -H "x-api-key: pd_live_YOUR_KEY"
Credits API
GET /v1/credits — Retrieve current balance and recent ledger events.
{
"balance": {
"total_credits": 1000,
"held_credits": 12,
"available_credits": 988,
"currency": "credits",
"as_of": "2026-04-21T10:00:00Z"
},
"recent_events": [
{
"event_id": "evt_01hx...",
"event_type": "capture",
"amount": -12,
"description": "Extraction job_01hx...",
"job_id": "job_01hx...",
"purchase_id": null,
"created_at": "2026-04-21T10:00:52Z"
}
]
}GET /v1/credits/history — Paginated ledger event history.
| Parameter | Type | Default | Description |
|---|---|---|---|
| offset | integer | 0 | Pagination offset |
| limit | integer | 100 | Max 500 per page |
API Key Rotation
POST /v1/keys/rotate — Revoke all active keys and issue a new one. The new key is shown once in the response.
POST /v1/keys/rotate
x-api-key: pd_live_OLD_KEY
HTTP 200 OK
{
"new_key": "pd_live_NEW_KEY_SHOWN_ONCE",
"revoked_key_prefixes": ["pd_live_OLD..."],
"message": "New key issued. Old keys are immediately invalidated."
}Webhooks
PolDex delivers signed HMAC-SHA256 webhook payloads to your webhook_url on job completion. Verify the signature before processing.
Delivery headers
| Header | Description |
|---|---|
| X-PolDex-Signature | t={timestamp},v1={HMAC-SHA256 of "timestamp.rawbody"} |
| X-PolDex-Job-Id | The job ID |
| X-PolDex-Delivery-Id | Unique delivery attempt ID |
Retry schedule
Failed deliveries are retried at 5, 15, 60, 300, and 900 second intervals. After exhaustion the job moves to dlq state.
Test webhook delivery
Use POST /v1/webhook-test/send to send a test payload to any HTTPS URL and inspect the delivery result.
curl -X POST https://api.poldex.io/v1/webhook-test/send \
-H "x-api-key: pd_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your.app/webhook",
"event_type": "job.completed",
"timeout_seconds": 10
}'Deletion / Retention
Structured output is retained 90 days by default. Request early deletion via:
POST /v1/jobs/{job_id}/delete
x-api-key: pd_live_...
HTTP 200 OK
{
"deletion_request_id": "del_01hx...",
"status": "requested",
"job_id": "job_01hx...",
"delete_status": "delete_requested"
}Deletion status values
| Status | Meaning |
|---|---|
| requested | Deletion request accepted |
| blocked_legal_hold | A legal hold is active — deletion cannot proceed |
| processing | Deletion in progress |
| completed | Artifacts deleted |
| failed | Deletion failed — contact support |
See Data Requests for full details on deletion scope and timelines.
Error Reference
All errors return a JSON body with an error object containing code, message, and optionally request_id and job_id.
{
"error": {
"code": "insufficient_credits",
"message": "Available credits (10) are less than the estimated cost (12).",
"request_id": "req_01hx..."
}
}| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Key missing, malformed, revoked, or expired |
| 402 | insufficient_credits | Available balance too low for this request |
| 403 | forbidden | Account suspended or action not permitted |
| 404 | not_found / job_not_found | Resource does not exist or does not belong to this key |
| 409 | idempotency_conflict | Same Idempotency-Key submitted with a different payload |
| 409 | legal_hold_active | Deletion blocked by an active legal hold |
| 503 | service_unavailable | Queue or payment provider temporarily unavailable |
| 500 | internal_error | Unexpected internal failure — credits not charged |
Schema Reference
Pass a schema ID in POST /v1/extract to specify the extraction target. Available schemas:
| Schema ID | Document Type |
|---|---|
| commercial_gl | Commercial General Liability |
| commercial_auto | Commercial Auto |
| commercial_property | Commercial Property |
| workers_comp | Workers Compensation |
| umbrella | Umbrella / Excess |
| professional | Professional Lines (E&O, D&O, Cyber) |
Full schema definitions including required fields and example outputs are available to authenticated callers via GET /v1/schemas and GET /v1/schemas/{schema_id}.
Health & Readiness
GET /health — Liveness check. Returns 200 { "status": "ok" } if the API process is running. No authentication required.
GET /ready — Readiness check. Returns 200 { "status": "ok" } when the database and all dependencies are reachable. Returns 503 if the database is not ready. No authentication required.
Use /health as your Kubernetes livenessProbe and /ready as your readinessProbe.
See also: GET /v1/metrics/live — public endpoint returning live platform throughput metrics.