Skip to main content
Not yet available — planned. The entire URL-first surface on this page — POST /v1/discover, POST /v1/extractions (single and batch), every GET /v1/extractions/… read, …/refresh, and GET /v1/receipts/{id} — is specced but not yet served: these routes answer 501 not_implemented. Nothing on this page can be called today. This page is the contract the surface ships against; the changelog announces when it goes live. Sessions (quickstart) are the live path.
Many integrators don’t have a question — they have a link: a specific catalog URL whose rows they want, on demand and on a schedule. /v1/extractions is that path. No sentence to phrase, no merchant resolution to pay for, no fan-out: one known URL goes straight to the extraction agent and comes back as a catalog under a signed receipt. The URL-first ladder is discover → extract → refresh → monitor, and it never touches a session.

Step 0 (optional): discover — $0

Have a site but not the exact catalog link? POST /v1/discover runs deterministic candidate discovery — free:
Candidates come back best-first. Like every customer-supplied URL on this API, discover targets must resolve to public hosts — private, loopback, and link-local ranges are refused with invalid_param.

Create an extraction

The response is 201 with the extraction object — or the live SSE stream if you send Accept: text/event-stream, exactly as with sessions. Then the same read verbs:

Terminal statuses — the claim is stated

delivered | abstained | error | stopped (open enum). On delivered, the object carries the receipt’s claim:
  • "complete" — the agent covered the catalog and says so.
  • "partial" — it delivered what it could and says which part — never dressed up as complete.
An abstained extraction means the page isn’t an extractable catalog, or the meaningful data is gated — stated, and $0 is billed beyond what discovery measurably spent. An honest “no” instead of an empty “yes”.

Batches — up to 50 URLs

Same entity and guidance across a list of URLs, one extraction per URL:
Budget honesty: max_spend_usd reserves per URL — the batch’s worst case is N × the cap, and the batch response states it as total_reserved_usd before anything runs. Validation is all-or-nothing: one invalid URL fails the whole POST with invalid_param naming it; there is no partial batch creation.

What extractions deliberately are not

  • They never fan out. One URL, one pass. If you want merchant discovery from a question, that’s a session.
  • The request cannot carry instructions to the agent. Customers state intent (entity, guidance); the actual agent request is composed through a fail-closed chain — off-enum values collapse to absence, and identity fields are never filled.

The second ask is cheaper than the first

POST /v1/extractions/{id}/refresh re-runs the same URL at marginal cost, serves from the record at $0 when your max_age_s is satisfied, and diffs against the previous delivery. A monitor is that refresh on a cadence with a webhook. Both are covered in Refresh and monitors.