Get a batch job
Poll a batch job for its status and accumulated results, for free.
https://api.up2data.ai/v1/batch/{job_id}Poll as often as desired; this call is always free. Every entry in results and failures carries the operation that produced it (e.g. enrich.profile, profiles.activity, search.jobs); every results entry also carries input, echoing what you submitted for it - the url string when the item was identified by url, or its request body otherwise. A profile, company, post, or Sales Navigator search item is charged in full at submission and none of that refunds later, whether it succeeds, comes back unprocessable_target (not found, private, deleted, or unreachable), or fails with a retryable error (429, 500, 504). Every other operation reserves the same worst case at submission but settles down to what it actually billed once its queue finishes, so a failed or empty item on those costs 0 and refunds in full - only a Sales Navigator search item's unused max_results reservation refunds the same way. In the example below, none of the items are search items or other operations, so the 32 failures don't change the total - the job still shows the full 1,000 credits charged at submission.
#Request
| Field | Type | Notes |
|---|---|---|
job_idrequired | string | Path parameter. The job_id returned by POST /batch. |
#Call it
curl -X GET "https://api.up2data.ai/v1/batch/job_7hd92kfa" \
-H "X-API-Key: YOUR_API_KEY"import requests
url = "https://api.up2data.ai/v1/batch/job_7hd92kfa"
headers = {
"X-API-Key": "YOUR_API_KEY",
}
response = requests.get(url, headers=headers)
print(response.json())const url = "https://api.up2data.ai/v1/batch/job_7hd92kfa";
const headers = {
"X-API-Key": "YOUR_API_KEY",
};
const response = await fetch(url, {
method: "GET",
headers,
});
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://api.up2data.ai/v1/batch/job_7hd92kfa"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Key", "YOUR_API_KEY")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
fmt.Println(string(respBody))
}#Response
{
"data": {
"job_id": "job_7hd92kfa", "status": "completed", "total": 1000, "succeeded": 968, "failed": 32,
"results": [
{ "type": "profile", "operation": "enrich.profile", "url": "https://linkedin.com/in/a", "status": "ok", "input": "https://linkedin.com/in/a", "data": { "full_name": "...", "headline": "..." } },
{ "type": "company", "operation": "enrich.company", "url": "https://linkedin.com/company/acme", "status": "ok", "input": "https://linkedin.com/company/acme", "data": { "name": "Acme", "headcount": 512 } },
{ "type": "comment", "operation": "posts.engagement.comments", "status": "ok", "input": { "urn": "7267273010393358336", "max_results": 500 }, "data": { "text": "Great insights!", "commenter": { "full_name": "Jane Doe" } } }
],
"failures": [
{ "type": "profile", "url": "https://linkedin.com/in/gone", "status": "unprocessable_target" },
{ "type": "company", "url": "https://linkedin.com/company/timed-out", "status": "upstream_timeout" }
]
},
"meta": { "creditsUsed": 1000, "creditsRemaining": 421012, "billed": true, "reason": "job_completed", "requestId": "req_v82n1kd0" }
}#Errors
| Status | Type | When | Billed |
|---|---|---|---|
| 401 | invalid_api_key | Missing, malformed, or revoked key. | No |
| 404 | not_found | No job with this job_id. | No |
| 429 | rate_limited | Over the 300 requests/min limit. Honor Retry-After. | No |
| 500 | internal_error | Something broke on the server side. | No |
See the Errors guide for every error type this version can return.