Page Extract API
Give a document and a JSON Schema; get back JSON that fits the schema, with the page each row is on. Jobs run in the background: create one, then get it until it is done. Base URL https://api.extract.pageindex.ai/v1.
Before you start
Page Extract uses your Page Search API key and credit, and reads documents you uploaded with Page Search. Upload a PDF as in the quick start and keep its doc_… id. Send the key as a bearer token.
Create a job
POST /extract starts a job and answers it at once, PENDING. Get it until its status isCOMPLETED, FAILED or CANCELLED; most documents take a minute or less, the longest several minutes.
import time, httpx
API = "https://api.extract.pageindex.ai/v1"
headers = {"Authorization": f"Bearer {api_key}"}
job = httpx.post(f"{API}/extract", headers=headers, json={
"document": "doc_60a07bcef3094b68806070f2", # uploaded with Page Search
"configuration": {"data_schema": schema, "tier": "standard", "cite_sources": True},
}).raise_for_status().json()
while job["status"] in ("PENDING", "RUNNING"):
time.sleep(5)
job = httpx.get(f"{API}/extract/{job['id']}", headers=headers).raise_for_status().json()
print(job["status"], job.get("extract_result"), job.get("error_message"))| Field | What it is |
|---|---|
document | The id of one of your documents, ready to read. |
configuration.data_schema | The JSON Schema of the result, an object at the top. Give each field a description: what it is, where it is printed, and the form you want. |
configuration.tier | standard ($0.03 a page, the default) or pro ($0.05 a page), a stronger model for the hardest layouts. |
configuration.cite_sources | Also give the page each list item is on, inextract_metadata.field_metadata, keyed by the item's path (a JSON Pointer). |
configuration.target_pages | Only these pages: one, such as 5, or a range, such as 3-12. All of them when left out. |
configuration.system_prompt | Anything else to know, such as "Amounts are in thousands". Up to 4,000 characters. |
Get a job
GET /extract/{id} answers the job; once it is COMPLETED, with its result.
{
"id": "ext_7b56d419dd0a4d7eafa68e4c",
"status": "COMPLETED",
"document": "doc_60a07bcef3094b68806070f2",
"configuration": {"data_schema": {…}, "tier": "standard", "cite_sources": true},
"extract_result": {"company": "…", "segments": [{"name": "…", "revenue_usd_millions": …}, …]},
"extract_metadata": {"field_metadata": {"/segments/0": {"page": 34}, "/segments/1": {"page": 34}, …}},
"usage": {"pages": 93, "credits": 2.79},
"created_at": "2026-11-08T12:07:53Z",
"updated_at": "2026-11-08T12:08:12Z"
}| Field | What it is |
|---|---|
status | PENDING (waiting to start), RUNNING,COMPLETED, FAILED or CANCELLED. |
extract_result | The data, fitting your schema. A value the document does not give isnull. |
extract_metadata | With cite_sources: the page of each list item. |
usage | The pages paid for and what they cost, in dollars of credit. |
error_message | Why a job failed. |
List, cancel and delete
GET /extract lists your jobs, newest first, without their results. POST /extract/{id}/cancel stops a job that has not finished; DELETE /extract/{id} deletes a job (and stops it first).
curl "https://api.extract.pageindex.ai/v1/extract?limit=20" -H "Authorization: Bearer $PAGEINDEX_SEARCH_API_KEY"
# {"jobs": [{"id": "ext_…", "status": "COMPLETED", …}, …], "next": "ext_…"} pass next as ?after= for morePricing
A job is paid when it completes, by its pages: $0.03 a page at standard, $0.05 at pro, from the same credit as Page Search. A cancelled or failed job costs nothing. Creating a job needs the credit it will take.
Writing a schema
- Describe each field: what it means, where it is printed, the form to give ("as printed, with the currency sign", "in millions"). The descriptions are the instructions.
- Put rows in arrays of objects: every printed row becomes an item, in the order printed, however many there are.
- Let values be missing:
{"type": ["string", "null"]}for a field a row may not have. - Up to 1 MB of schema;
$refand$defsare fine.
Errors
Errors answer {"error": {"code": "…", "message": "…"}}.
| Status | Code | When |
|---|---|---|
| 400 | invalid_schema, schema_too_large, invalid_target_pages | The request needs fixing. |
| 401 | unauthorized | No API key, or one that is not valid. |
| 402 | insufficient_credit | Not enough credit for the job's pages; add some in the console. |
| 404 | document_not_found, job_not_found | No such document or job of yours. |
| 409 | document_not_ready, job_finished | The document is still being made, or the job is already done. |