Conversions
Two endpoints do the whole job: one starts a conversion, one reads its
result. Upload a PDF, get back a job_id, then poll that job
until an ESX download link appears.
Start a conversion
Send the PDF as multipart/form-data. The response is immediate
— a 202 with a job_id; the actual conversion runs
in the background.
Body fields
| Field | Required | Type | Notes |
|---|---|---|---|
file | Yes | file | The estimate PDF. application/pdf content-type or a .pdf filename. |
price_list | Yes | string | Xactimate price-list code, e.g. FLTA8X_02MAY26. Must be one of the currently-loaded lists. |
output_formats | No | string[] | Repeatable form field. Default ["esx"]. Add "json" for a structured JSON artifact alongside the ESX — see JSON output. |
callback_url | No | string | Per-request webhook override. |
Headers
| Header | Required | Notes |
|---|---|---|
X-API-Key | Yes | See Authentication. |
Idempotency-Key | No | Same key + same partner within the retention window returns the existing job instead of creating a duplicate. Use it to make retries after a timeout safe. |
Limits
- Max upload size: 50 MB.
- Only PDF is accepted — anything else returns
invalid_file_type.
Example
curl -s -X POST https://est.anterotrail.com/v1/conversions \
-H "X-API-Key: at_test_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Idempotency-Key: my-job-2026-07-09-001" \
-F "file=@estimate.pdf;type=application/pdf" \
-F "price_list=FLTA8X_02MAY26" { "job_id": "b3f1...", "status": "queued" } Read a conversion
Returns the job that belongs to your partner account only.
A job ID that isn't yours — or doesn't exist — returns 404 not_found. The two cases are never distinguished, so no one can
probe for other partners' jobs.
While running
{
"job_id": "b3f1...",
"status": "processing",
"created_at": "2026-07-09T12:00:00Z"
} On success
{
"job_id": "b3f1...",
"status": "succeeded",
"created_at": "2026-07-09T12:00:00Z",
"summary": { "room_count": 14, "line_item_count": 132, "total_rcv": 48213.44, "warnings": [] },
"esx_url": "https://.../job.esx?sig=...",
"esx_expired": false,
"artifacts": [
{ "type": "esx", "url": "https://.../job.esx?sig=...", "expired": false }
]
} -
esx_urlis a time-limited signed URL, generated fresh on everyGET— valid 7 days from generation (not from job completion). Re-poll to refresh it. -
artifactslists every output the job produced, each with its own signed URL — one entry per requestedoutput_format. Jobs requesting only ESX carry the singleesxentry shown above;esx_urlremains alongside it either way. -
Once the artifact passes the 30-day retention
window,
esx_urlisnullandesx_expiredistrue.summarystays available indefinitely.
On failure
{
"job_id": "b3f1...",
"status": "failed",
"created_at": "2026-07-09T12:00:00Z",
"error": { "code": "unsupported_estimate", "message": "No line items could be read..." }
}
Poll on a reasonable interval — a few seconds. Most conversions finish in
under a minute. A job stuck in processing past 20 minutes is
force-failed with error.code: "timeout". To skip polling
entirely, use a webhook.