Prospects Contact Information Job
curl --request POST \
--url https://api.explorium.ai/v2/prospects/contact_information/job \
--header 'Content-Type: application/json' \
--header 'api_key: <api-key>' \
--data '
{
"list_id": "<string>",
"notifications": {
"email": {
"enabled": true,
"on": []
}
},
"parameters": {
"contact_types": []
}
}
'import requests
url = "https://api.explorium.ai/v2/prospects/contact_information/job"
payload = {
"list_id": "<string>",
"notifications": { "email": {
"enabled": True,
"on": []
} },
"parameters": { "contact_types": [] }
}
headers = {
"api_key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_key: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
list_id: '<string>',
notifications: {email: {enabled: true, on: []}},
parameters: {contact_types: []}
})
};
fetch('https://api.explorium.ai/v2/prospects/contact_information/job', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.explorium.ai/v2/prospects/contact_information/job",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'list_id' => '<string>',
'notifications' => [
'email' => [
'enabled' => true,
'on' => [
]
]
],
'parameters' => [
'contact_types' => [
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"api_key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.explorium.ai/v2/prospects/contact_information/job"
payload := strings.NewReader("{\n \"list_id\": \"<string>\",\n \"notifications\": {\n \"email\": {\n \"enabled\": true,\n \"on\": []\n }\n },\n \"parameters\": {\n \"contact_types\": []\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.explorium.ai/v2/prospects/contact_information/job")
.header("api_key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"list_id\": \"<string>\",\n \"notifications\": {\n \"email\": {\n \"enabled\": true,\n \"on\": []\n }\n },\n \"parameters\": {\n \"contact_types\": []\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.explorium.ai/v2/prospects/contact_information/job")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"list_id\": \"<string>\",\n \"notifications\": {\n \"email\": {\n \"enabled\": true,\n \"on\": []\n }\n },\n \"parameters\": {\n \"contact_types\": []\n }\n}"
response = http.request(request)
puts response.read_body{
"job_id": "<string>",
"status": "<string>",
"status_url": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Async
Contact information (async) — waterfall
POST
/
v2
/
prospects
/
contact_information
/
job
Prospects Contact Information Job
curl --request POST \
--url https://api.explorium.ai/v2/prospects/contact_information/job \
--header 'Content-Type: application/json' \
--header 'api_key: <api-key>' \
--data '
{
"list_id": "<string>",
"notifications": {
"email": {
"enabled": true,
"on": []
}
},
"parameters": {
"contact_types": []
}
}
'import requests
url = "https://api.explorium.ai/v2/prospects/contact_information/job"
payload = {
"list_id": "<string>",
"notifications": { "email": {
"enabled": True,
"on": []
} },
"parameters": { "contact_types": [] }
}
headers = {
"api_key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_key: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
list_id: '<string>',
notifications: {email: {enabled: true, on: []}},
parameters: {contact_types: []}
})
};
fetch('https://api.explorium.ai/v2/prospects/contact_information/job', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.explorium.ai/v2/prospects/contact_information/job",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'list_id' => '<string>',
'notifications' => [
'email' => [
'enabled' => true,
'on' => [
]
]
],
'parameters' => [
'contact_types' => [
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"api_key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.explorium.ai/v2/prospects/contact_information/job"
payload := strings.NewReader("{\n \"list_id\": \"<string>\",\n \"notifications\": {\n \"email\": {\n \"enabled\": true,\n \"on\": []\n }\n },\n \"parameters\": {\n \"contact_types\": []\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.explorium.ai/v2/prospects/contact_information/job")
.header("api_key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"list_id\": \"<string>\",\n \"notifications\": {\n \"email\": {\n \"enabled\": true,\n \"on\": []\n }\n },\n \"parameters\": {\n \"contact_types\": []\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.explorium.ai/v2/prospects/contact_information/job")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"list_id\": \"<string>\",\n \"notifications\": {\n \"email\": {\n \"enabled\": true,\n \"on\": []\n }\n },\n \"parameters\": {\n \"contact_types\": []\n }\n}"
response = http.request(request)
puts response.read_body{
"job_id": "<string>",
"status": "<string>",
"status_url": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Description
The Asynchronous Contact Information Enrichment retrieves verified professional emails, phone numbers, and mobile numbers for up to 10,000 prospects per job — and, unlike the synchronous endpoint, it supports waterfall enrichment: prospects that Explorium data cannot enrich are automatically retried against a verified external provider, increasing overall contact coverage. Key Benefits:- Asynchronous retrieval of enriched contact data for up to 10,000 prospects per job.
- Higher coverage — the optional waterfall falls back to an external provider for prospects with no Explorium contact data.
- Source transparency — every result is tagged with where its email and phone came from.
Asynchronous variant. This submits a job through the async job infrastructure — poll job status for progress and results. Input comes from an uploaded dataset (
list_id); limits are 10,000 rows and a 24-hour run time.For the output signal reference shared with the sync endpoint, see Contact information.Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
waterfall | enum: explorium_only / full | explorium_only | Controls which data sources are used. explorium_only enriches with Explorium contact data only — identical to today’s behavior. full runs the waterfall: Explorium first, then the external provider for prospects Explorium could not enrich. |
contact_types | array of enum: email / phone | both | Which contact types to query — email, phone, or both. |
waterfall is only available on this asynchronous endpoint. Passing it to the synchronous /enrich endpoint returns a validation error.How the waterfall works
Withwaterfall: "full", each job runs five steps:
1
Explorium enrichment
All prospects in the dataset are enriched with Explorium contact data. A prospect counts as enriched if at least one email or phone number is returned.
2
Identify gaps
Prospects with no email and no phone from Explorium are collected.
3
External fallback
The unenriched prospects are sent to the external provider, and its results are mapped onto the same contact schema (
professional_email, phone_numbers, mobile_phone, professional_email_status).4
Merge and return
One unified result set covers all prospects, with
email_source and phone_source tagging where each value came from.5
Credits charged by source
Explorium-sourced and externally-sourced results are charged at different rates — see Credit charging.
Example request
curl --request POST \
--url https://api.explorium.ai/v2/prospects/contact_information/job \
--header 'api_key: YOUR_API_KEY' \
--header 'content-type: application/json' \
--data '{
"list_id": "b8f2c1d4-...",
"parameters": {
"waterfall": "full",
"contact_types": ["email", "phone"]
}
}'
import requests
resp = requests.post(
"https://api.explorium.ai/v2/prospects/contact_information/job",
headers={"api_key": "YOUR_API_KEY", "content-type": "application/json"},
json={
"list_id": list_id, # from the dataset upload endpoint
"parameters": {
"waterfall": "full",
"contact_types": ["email", "phone"],
},
},
)
resp.raise_for_status()
job_id = resp.json()["job_id"]
list_id comes from the dataset upload endpoint — see the end-to-end guide for the full flow.
Response
Poll job status with the returnedjob_id. A finished waterfall job reports per-source totals under additional_data, alongside the usual credit usage:
Job status (completed)
{
"job_id": "6a79d925cad807e21132019e",
"status": "succeeded",
"started": "2026-08-10T13:59:01.832000+00:00",
"finished": "2026-08-10T14:10:21.560000+00:00",
"credit_usage": {
"total_credits": 35,
"total_results": 15
},
"additional_data": {
"total_external_emails": 0,
"total_external_phones": 0,
"total_explorium_emails": 10,
"total_explorium_phones": 5
},
"results": {
"format": "csv",
"download_url": "https://...",
"expires_at": "2026-08-10T15:10:21Z",
"file_expires_at": "2026-08-17T14:10:21Z"
},
"error": null
}
Result fields
Results are downloaded as a CSV fromresults.download_url. The link is valid for about an hour (expires_at) — re-poll job status for a fresh one; the file itself is kept for 7 days (file_expires_at). Each row carries the contact data plus its source tags:
| Column | Description |
|---|---|
entity_ids | The prospect identifier(s) the row corresponds to |
professional_email | The current professional email address |
professional_email_status | Validity status of the professional email: valid, catch_all, or invalid |
phone_numbers | All phone numbers found |
mobile_phone | The prospect’s direct-dial mobile number |
email_source | Where the email came from: explorium, external_source, or empty when no email was found |
phone_source | Where the phone came from: explorium, external_source, or empty when no phone was found |
Credit charging
Credits are charged per result, according to the source that produced it:| Data source | Phone | |
|---|---|---|
| Explorium | 2 credits | 5 credits |
| External provider | 3 credits | 15 credits |
| No data returned | 0 credits | 0 credits |
waterfall mode:
explorium_only(the default) — only Explorium data is used, so only Explorium rates apply. External-provider charges are impossible in this mode.full— Explorium rates apply to Explorium-sourced results, and external-provider rates apply only to prospects the external provider actually enriched. A prospect that neither source could enrich costs nothing.
Best practices
- Start with
explorium_onlyto see your Explorium-native coverage, then rerun the gaps withfullif you need more. - Use
contact_typesto control spend — externally-sourced phones cost significantly more than emails, so request only what you need. - Check
additional_dataon the job status to see how many results each source contributed before downloading. - Filter by
email_source/phone_sourcedownstream if you track data provenance per record.
Authorizations
APIKeyHeaderAPIKeyHeader
Body
application/json
Was this page helpful?