Async enrich jobs
Use POST /api/v1/enrich/jobs for deferred billing after long-running enrich work.
Poll GET /api/v1/enrich/jobs/{job_id} with the poll_bearer from the 202 body (free).
When to use
- Lead-session or websearch runs that may exceed HTTP timeouts (lead-session sync: 30–180 s).
- Headless workers that prefer fire-and-poll over holding a connection.
- CDP x402 upto — anonymous buyers settle on-chain after the job completes.
Sync routes (POST /api/v1/enrich/websearch, POST /api/v1/enrich/lead-session) remain
unchanged for one-shot calls.
Supported routes
Full sessions
enrich/websearchenrich/lead-session
Partial lead-session ops (same payloads as sync POST /api/v1/enrich/lead-session/… routes; hosted demo submits these via jobs only):
route |
Default precharge (omit bill_up_to_usd) |
|---|---|
enrich/lead-session/slot-rerun |
$0.35 |
enrich/lead-session/slot-person |
$0.35 |
enrich/lead-session/slots-rerun |
N × $0.35 (N = payload.model_ids count) |
enrich/lead-session/synthesize-patch |
$0.08 |
enrich/lead-session/finding-rerun |
catalog price |
enrich/lead-session/sic-rerun |
catalog price |
Partial routes use bill-on-match: no usable enrichment → $0 settle and full virtual precharge refund. Recipe for batch hunts: lead_session_followups.
Spending ceiling (bill_up_to_usd)
| Value | |
|---|---|
| Default (omit field) | Route catalog price — $1.50 for websearch / lead-session; $0.35 per slot-rerun or slot-person; N × $0.35 for slots-rerun |
| Client override | $0.05 – $50.00 (ENRICH_JOB_BILL_UP_TO_MAX_USD) |
| Charged | Actual vendor cost ≤ ceiling; unused precharge refunded |
| No-match | $0 on upto path; full refund on virtual precharge |
For async lead-session jobs, in-payload budget_usd is capped to the job’s
bill_up_to_usd (sync lead-session alone still caps budget_usd at $20 per call; session header budget up to $50).
Two billing paths
A — Virtual balance (wallet / xpay agents)
For agents with a bearer (411_… or 411k_…) and prepaid virtual_balance_usd:
POST /api/v1/enrich/jobswithAuthorization: Bearer <token>(noPAYMENT-SIGNATURE).- Server pre-charges
bill_up_to_usdfrom virtual balance (default $1.50). - Receive 202 with
job_id,poll_bearer,billing_mode: "virtual_balance". - Poll
GET /api/v1/enrich/jobs/{job_id}withAuthorization: Bearer <poll_bearer>. - On complete, server refunds unused precharge to virtual balance (full refund on no-match).
B — CDP x402 upto (anonymous or balance-exhausted)
When no bearer is sent (or balance cannot cover bill_up_to_usd):
POSTwithout payment → 402 withscheme: "upto"(CDP only),maxTimeoutSeconds: 1200.- Sign Permit2 upto and retry with
PAYMENT-SIGNATURE. - Receive 202 with
billing_mode: "x402_upto". - Poll with
poll_bearer. - Server settles on-chain after the job completes (actual ≤ max; $0 on no-match).
xpay does not advertise upto — do not expect xpay entries in accepts[].
Example — websearch job
{
"route": "enrich/websearch",
"payload": {
"business_name": "Acme Corp",
"city": "Tampa",
"state": "FL"
},
"bill_up_to_usd": 1.5,
"callback_url": "https://example.com/hooks/enrich"
}
Example — lead-session job
{
"route": "enrich/lead-session",
"payload": {
"lead": {
"contact_id": 81555753,
"company": "Haney Furniture Co",
"street": "30 N Beaver St",
"city": "New Castle",
"state": "PA",
"zip": "16101",
"number1": "7246547732"
},
"budget_usd": 2.0,
"max_rounds": 5,
"mode": "auto"
},
"bill_up_to_usd": 5.0
}
Example — batch slot rerun
{
"route": "enrich/lead-session/slots-rerun",
"payload": {
"lead": { "contact_id": 1737992709, "company": "Hoops & Gears and Clark" },
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"model_ids": ["data411-hunt-ground", "data411-crimson-span"],
"prior_backfill": { "...": "current backfill" }
},
"bill_up_to_usd": 0.70
}
See lead_session_followups for batch slot eligibility
(pending / error in trace; skip done; allow never-ran catalog slots), person hunt
per contact (slot-person, hosted Hunt controls), and hunt-board vs trace notes.
Example — slot-person (one contact)
{
"route": "enrich/lead-session/slot-person",
"payload": {
"lead": { "contact_id": 1737992709, "company": "Hoops & Gears and Clark" },
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"target_contact_id": "c_owner_1",
"target_name": "Jane Doe",
"prior_backfill": { "...": "current backfill" },
"include_person_hunt": true
},
"bill_up_to_usd": 0.35
}
Intermediate search runs data411-hunt-person; when include_person_hunt is true and
person hunt has not already run for that contact, the worker chains whitepages_person_hunt
before returning. Hosted UI Intermediate search uses this route only — contact-name
clicks use full enrich/lead-session follow-up when hunt is still pending.
Batch eligibility (slots-rerun)
When payload.model_ids is set, the worker filters each id against prior_backfill.tool_trace:
- Runs: trace status
pendingorerror, or id absent from trace (first run). - Skips: trace status
done,cancelled,repetition, orrunning(does not abort sibling ids). - Refuses job (no runnable hunts): zero ids after filter →
SLOTS_RERUN_REFUSED/no_eligible_slots.
Omit model_ids to run all trace-eligible pending/error slots. Default precharge N × $0.35 uses len(payload.model_ids) at submit time (minimum one slot price when the field is omitted).
202 response fields
| Field | Meaning |
|---|---|
job_id |
ej_… — pass to poll URL |
poll_bearer |
411j_… — scoped poll token |
poll_interval_sec |
Suggested poll interval (default 2) |
billing_mode |
virtual_balance or x402_upto |
bill_up_to_usd |
Ceiling pre-charged / authorized |
max_timeout_seconds |
Upto timeout (default 1200) |
Poll response
Poll until status is completed or failed.
status |
Meaning |
|---|---|
queued |
Accepted, not started |
running |
Worker executing |
completing |
Finishing billing / persist |
completed |
Done — see result |
failed |
Error — see error |
billing_status |
Meaning |
|---|---|
settled_virtual |
Virtual precharge true-up complete |
settled |
On-chain upto settle complete |
settling |
Settlement in progress |
settle_failed |
Billing failed after run |
result mirrors the sync route JSON when complete.
Optional fields
callback_url— HTTPS webhook; firesenrich.job_completed(see event_callbacks).idempotency_key— dedupe key for the submit request.
MCP
submit_enrich_job and get_enrich_job wrap the same paths. Anonymous CDP upto is
REST only (MCP requires bearer for submit).
Smoke scripts
python3 scripts/smoke_enrich_upto_jobs.py --anon
BASE_URL=https://411data.io python3 scripts/smoke_enrich_upto_jobs.py --balance --route websearch
BASE_URL=https://411data.io python3 scripts/smoke_enrich_upto_jobs.py --upto --route websearch
Discovery
Listed at GET /discovery/resources and /.well-known/x402 as a separate upto
resource (not in sync PAID_ROUTES). Bazaar search: try “async”, “queue”, “jobs”.