Batch enrichment — parallel API, not a batch upload
Use when the user asks for a batch API, bulk enrichment, CSV upload, or enriching hundreds of leads overnight.
What exists today
Yes — there is a full REST + MCP API at https://411data.io/api/v1/*
(see api_integrations, /developers,
/openapi.json).
CSV upload — yes: managed batch at POST /api/v1/batch/enrich/upload and
/batch. Recipe: batch_csv_enrich.
Headless parallel REST — yes: no file required; queue rows in your app (below).
Yes — there is an async job queue for long-running enrich work:
| Endpoint | Role |
|---|---|
POST /api/v1/enrich/jobs |
Submit enrich/websearch, enrich/lead-session, or partial hunt ops (slot-rerun, slot-person, slots-rerun, …); returns 202 + poll_bearer |
GET /api/v1/enrich/jobs/{job_id} |
Poll status/result (free) |
Recipe: async_enrich_jobs. Default spending ceiling is route-specific ($1.50 full sessions; N × $0.35 batch slot reruns);
override bill_up_to_usd up to $50.
Sync enrich routes (phone, person, websearch, lead-session) return full JSON on one HTTP connection. Lead-session sync calls often run 30–180 s — use the queue when you do not want to hold the connection open.
| Route | Shape | Typical latency |
|---|---|---|
POST /api/v1/enrich/lead-session (sync) |
One CRM lead object | 30–180 s |
POST /api/v1/enrich/jobs (async) |
Same payloads, fire-and-poll | worker-bound |
POST /api/v1/enrich/phone / /person |
One phone or person query | ~1–3 s |
POST /api/v1/enrich/websearch (sync) |
One business-name hunt | ~5–30 s |
Recommended batch pattern
- CSV file — use batch_csv_enrich (
/batchor enrich-agent paperclip). - Queue in your app — read rows from your CRM export; parallel sync or async jobs (below).
- Long rows — submit via
POST /api/v1/enrich/jobs+ poll (orcallback_url+enrich.job_completed). - Short rows — worker pool of sync calls (start with 5–10 concurrent; back off on 429).
- Balance check —
GET /api/v1/agents/balancebefore large runs; prepay_deposits if headless. - Idempotency — dedupe your queue by company + address (or CRM
contact_id/ email / phone when present); the server reuses agent-scoped warm-seed onchat_title, exact input, prior matched batch rows, then company/geo/phone (AGENT_LEAD_CACHE_TTL_HOURS, default 168h) — not per-session synthetic ids assigned whencontact_idwas omitted. - Push on completion — subscribe to event_callbacks (
enrich.job_completed,lead.session_completed,enrich.completed) so workers advance the queue from webhooks instead of blocking on poll. - Usage keys — issue scoped
411k_keys for automation at /connect?action=usagekeys.
Building a list (not enriching yet)
Use leads_search with tight filters + limit ≤ 25 on the first probe, then
paginate with cursor. See leads_search_filters.
What to tell the user
- The API is real and scriptable — point at
/developers,/skill.md,/playground. - Bulk = your orchestration + our per-record endpoints or the async job queue.
- For “notify me when each row finishes” → event callbacks or async job
callback_url. - For “upload 1,000 leads and wait for one webhook” as a single managed job → not shipped; use parallel jobs + callbacks.
Related
- async_enrich_jobs — submit, poll, billing paths
- filter_discipline_meta — narrowest tool per row
- bill_on_match — refunds on no-match
- event_callbacks — webhook delivery