curl --request POST \
--url https://api.retriever.run/v1/services/jobs/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"service": "getPhoneNumber",
"inputs": [
{}
]
}
'import requests
url = "https://api.retriever.run/v1/services/jobs/batch"
payload = {
"service": "getPhoneNumber",
"inputs": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({service: 'getPhoneNumber', inputs: [{}]})
};
fetch('https://api.retriever.run/v1/services/jobs/batch', 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.retriever.run/v1/services/jobs/batch",
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([
'service' => 'getPhoneNumber',
'inputs' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.retriever.run/v1/services/jobs/batch"
payload := strings.NewReader("{\n \"service\": \"getPhoneNumber\",\n \"inputs\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.retriever.run/v1/services/jobs/batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"service\": \"getPhoneNumber\",\n \"inputs\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.retriever.run/v1/services/jobs/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"service\": \"getPhoneNumber\",\n \"inputs\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"batch_id": "svcbatch_9f2c4b1e8a7d6c5f",
"service": "<string>",
"size": 123,
"status": "queued",
"counts": {
"queued": 123,
"running": 123,
"completed": 123,
"failed": 123,
"cancelled": 123
},
"jobs": [
{
"job_id": "<string>",
"service": "<string>",
"status": "queued",
"attempt": 123,
"reused": true,
"result": {},
"error": {
"code": "<string>",
"message": "<string>",
"retryable": true
},
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"input_index": 123
}
],
"poll_url": "<string>"
}{
"ok": true,
"batch_id": "svcbatch_9f2c4b1e8a7d6c5f",
"service": "<string>",
"size": 123,
"status": "queued",
"counts": {
"queued": 123,
"running": 123,
"completed": 123,
"failed": 123,
"cancelled": 123
},
"jobs": [
{
"job_id": "<string>",
"service": "<string>",
"status": "queued",
"attempt": 123,
"reused": true,
"result": {},
"error": {
"code": "<string>",
"message": "<string>",
"retryable": true
},
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"input_index": 123
}
],
"poll_url": "<string>"
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_authenticated",
"message": "A valid API key is required."
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Retry later."
}
}Run a slow service (a list of 1 to 100 inputs)
The only way to run a slow service (getEmail, getPhoneNumber,
webResearch, getLinkedInUserComments, getLinkedInUserReactions):
1 to 100 inputs in one call, one job per input, in the order sent. Put
every person of a task in the same list.
Every input is validated first; one bad input refuses the whole list
with its index, and no job is created.
An input the schema accepts but that names too little to search (a
contact with no LinkedIn profile, and no first and last name with a
company) is not refused here: its line ends provider_rejected.
Each line follows the job rules. For getEmail and getPhoneNumber
only, an answer your organization already has for that person from the
last 7 days is reused and the line comes back with
reused: true (nothing is charged for it). Other slow services never
reuse a finished answer: they only share a search still running, like
every service does. A failed line is never reused: the same input sent
again gets a new job. The batch and its jobs are
created together or not at all. Retriever-Fresh: true forces a
fresh, billed execution of every line. Collect the results with
GET /v1/services/jobs/batch/{id}. Requests and results are emptied
after 30 days.
Each line reserves its worst-case price before its search. When the
balance cannot reserve even the cheapest line that needs a new search,
the whole list is refused with 402 insufficient_credits and no job
is created. Otherwise the list is accepted, and a line that finds no
balance left ends failed with usage_limit: top up, then send the
failed inputs again. No line carries its own charge: compare
GET /credits before and after the batch for its total.
getPhoneNumber returns every number its sources found in phones
(number, country, line type, line status, source), best first;
phone_number is the first entry.
curl --request POST \
--url https://api.retriever.run/v1/services/jobs/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"service": "getPhoneNumber",
"inputs": [
{}
]
}
'import requests
url = "https://api.retriever.run/v1/services/jobs/batch"
payload = {
"service": "getPhoneNumber",
"inputs": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({service: 'getPhoneNumber', inputs: [{}]})
};
fetch('https://api.retriever.run/v1/services/jobs/batch', 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.retriever.run/v1/services/jobs/batch",
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([
'service' => 'getPhoneNumber',
'inputs' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.retriever.run/v1/services/jobs/batch"
payload := strings.NewReader("{\n \"service\": \"getPhoneNumber\",\n \"inputs\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.retriever.run/v1/services/jobs/batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"service\": \"getPhoneNumber\",\n \"inputs\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.retriever.run/v1/services/jobs/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"service\": \"getPhoneNumber\",\n \"inputs\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"batch_id": "svcbatch_9f2c4b1e8a7d6c5f",
"service": "<string>",
"size": 123,
"status": "queued",
"counts": {
"queued": 123,
"running": 123,
"completed": 123,
"failed": 123,
"cancelled": 123
},
"jobs": [
{
"job_id": "<string>",
"service": "<string>",
"status": "queued",
"attempt": 123,
"reused": true,
"result": {},
"error": {
"code": "<string>",
"message": "<string>",
"retryable": true
},
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"input_index": 123
}
],
"poll_url": "<string>"
}{
"ok": true,
"batch_id": "svcbatch_9f2c4b1e8a7d6c5f",
"service": "<string>",
"size": 123,
"status": "queued",
"counts": {
"queued": 123,
"running": 123,
"completed": 123,
"failed": 123,
"cancelled": 123
},
"jobs": [
{
"job_id": "<string>",
"service": "<string>",
"status": "queued",
"attempt": 123,
"reused": true,
"result": {},
"error": {
"code": "<string>",
"message": "<string>",
"retryable": true
},
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"input_index": 123
}
],
"poll_url": "<string>"
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_authenticated",
"message": "A valid API key is required."
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Retry later."
}
}Authorizations
API key ret_live_… created in Settings → API keys.
Headers
true: a new, billed search for every line, even when your organization has a recent answer.
true Body
Response
Every input already had an answer: the batch is complete.
"svcbatch_9f2c4b1e8a7d6c5f"
completed once every job has ended, whatever each one's outcome.
queued, running, completed Show child attributes
Show child attributes
One entry per input, in the order sent.
Show child attributes
Show child attributes