GET /v1/jobs/:id reads the current state of a job. There are two kinds of id, and they return two different shapes.
id
string
required
A job id. Parent ids have no dots (job_8t2q). Child ids are dotted, with three segments (job_8t2q.chatgpt.us).

Parent vs. child ids

When you submit a search, you get back a parent job and one child per surface × region.
  • A parent id (job_8t2q) returns a rollup: the parent’s status plus a list of its children. Use it to track fan-out progress.
  • A child id (job_8t2q.chatgpt.us) returns the canonical Envelope, the answer and its provenance for exactly one surface in one region.
Child ids follow the form job_<id>.<surface>.<regionKey> — the region key is the lowercased country[:city][:language] (or GLOBAL when untargeted). You get them from the children array on the submit response (202) or from a parent read.

Parent response

Parent
job
object
children
object[]
One entry per surface × region.

Child response (the Envelope)

Fetch a child id to get the full result for one surface.
Envelope
The Envelope has four sections: job, provenance, answer, and evidence (plus optional html and credits). See The Envelope for a full field-by-field reference.
If a surface returns nothing, the child still finishes as completed with provenance.surfacePresent: false, a surface_absent warning, and an empty answer. An empty capture costs no credits.

Status values

A job is always in exactly one status.
Active statuses
queued | running | processing
The job is still running. Keep polling, or wait for a webhook. A child that is claimed but not yet persisted returns { "job": { "id": ..., "status": "running" }, "children": [] }.
Terminal statuses
completed | partial | failed | canceled | expired
The job is done. Stop polling on any of these.
For a parent, the rollup is derived from its children: completed when all children completed, failed when all failed, and partial on a mix.
A poll loop must stop on any terminal state — not just completed. Treating partial, failed, canceled, or expired as “keep waiting” will loop forever.

Polling loop

Poll the parent until it reaches a terminal state, then read each child.
Poll a parent until terminal
For fan-out across many surfaces or regions, prefer webhooks over polling. You get a signed POST the moment each child reaches a terminal state — no loop, no wasted requests, and each child’s Envelope is delivered inline.

Errors

404
JOB_NOT_FOUND
No job exists for the given id, or it has expired. Check the id — remember that parent ids have no dots and child ids do.
404
See the full error reference for every code and the shared error shape.

Submit a search

Start a job with POST /v1/search.

The Envelope

Every field in a child result.