Prime VerifierPrime VerifierDevelopersAPI v1
Dashboard →
API reference / Bulk jobs

Bulk jobs

Upload a large list once and process it in the background at a safe pace. Create a job, track progress, stream live updates, and download the finished results.

POST/v1/jobs

Upload a CSV file to start a bulk verification job. Keeps the user's ORIGINAL file (all columns) and verifies the chosen email column. The result columns are merged back into the original file at download time. `emailColumn` is the zero-based index of the email column; `dedupe` controls whether the downloaded file keeps one row per address. Maximum file size: 50 MB. Maximum unique emails: 500,000

!

Returns 400, 401 with the error envelope { status, error: { code, message } }. Branch on the numeric error.code, never the message.

Request
curl -X POST "https://api.primeverifier.com/v1/jobs" \
  -H "X-API-KEY: pk_live_your_api_key"
const res = await fetch("https://api.primeverifier.com/v1/jobs", {
  method: "POST",
  headers: {
    "X-API-KEY": "pk_live_your_api_key",
  },
});
const data = await res.json();
console.log(data);
import requests

res = requests.post(
    "https://api.primeverifier.com/v1/jobs",
    headers={"X-API-KEY": "pk_live_your_api_key"},
)
print(res.json())
using var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Post, "https://api.primeverifier.com/v1/jobs");
req.Headers.Add("X-API-KEY", "pk_live_your_api_key");
var res = await client.SendAsync(req);
Console.WriteLine(await res.Content.ReadAsStringAsync());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.primeverifier.com/v1/jobs"))
    .header("X-API-KEY", "pk_live_your_api_key")
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://api.primeverifier.com/v1/jobs");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_HTTPHEADER => ["X-API-KEY: pk_live_your_api_key"],
]);
$response = curl_exec($ch);
echo $response;
req, _ := http.NewRequest("POST", "https://api.primeverifier.com/v1/jobs", nil)
req.Header.Set("X-API-KEY", "pk_live_your_api_key")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
require "net/http"
require "json"

uri = URI("https://api.primeverifier.com/v1/jobs")
req = Net::HTTP::Post.new(uri)
req["X-API-KEY"] = "pk_live_your_api_key"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
Try itPOST /v1/jobs
GET/v1/jobs

List all bulk jobs for the authenticated user (paginated)

Parameters
NameInTypeRequiredDescription
pagequeryinteger · int32optional
pageSizequeryinteger · int32optional
!

Returns 401 with the error envelope { status, error: { code, message } }. Branch on the numeric error.code, never the message.

Request
curl -X GET "https://api.primeverifier.com/v1/jobs?page=string&pageSize=string" \
  -H "X-API-KEY: pk_live_your_api_key"
const res = await fetch("https://api.primeverifier.com/v1/jobs?page=string&pageSize=string", {
  method: "GET",
  headers: {
    "X-API-KEY": "pk_live_your_api_key",
  },
});
const data = await res.json();
console.log(data);
import requests

res = requests.get(
    "https://api.primeverifier.com/v1/jobs?page=string&pageSize=string",
    headers={"X-API-KEY": "pk_live_your_api_key"},
)
print(res.json())
using var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://api.primeverifier.com/v1/jobs?page=string&pageSize=string");
req.Headers.Add("X-API-KEY", "pk_live_your_api_key");
var res = await client.SendAsync(req);
Console.WriteLine(await res.Content.ReadAsStringAsync());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.primeverifier.com/v1/jobs?page=string&pageSize=string"))
    .header("X-API-KEY", "pk_live_your_api_key")
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://api.primeverifier.com/v1/jobs?page=string&pageSize=string");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => ["X-API-KEY: pk_live_your_api_key"],
]);
$response = curl_exec($ch);
echo $response;
req, _ := http.NewRequest("GET", "https://api.primeverifier.com/v1/jobs?page=string&pageSize=string", nil)
req.Header.Set("X-API-KEY", "pk_live_your_api_key")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
require "net/http"
require "json"

uri = URI("https://api.primeverifier.com/v1/jobs?page=string&pageSize=string")
req = Net::HTTP::Get.new(uri)
req["X-API-KEY"] = "pk_live_your_api_key"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
Response200 OK
{
  "status": "success",
  "data": {},
  "error": null
}
Try itGET /v1/jobs
GET/v1/jobs/{id}

Get details for a single bulk job

Parameters
NameInTypeRequiredDescription
idpathinteger · int64required
!

Returns 401, 404 with the error envelope { status, error: { code, message } }. Branch on the numeric error.code, never the message.

Request
curl -X GET "https://api.primeverifier.com/v1/jobs/123" \
  -H "X-API-KEY: pk_live_your_api_key"
const res = await fetch("https://api.primeverifier.com/v1/jobs/123", {
  method: "GET",
  headers: {
    "X-API-KEY": "pk_live_your_api_key",
  },
});
const data = await res.json();
console.log(data);
import requests

res = requests.get(
    "https://api.primeverifier.com/v1/jobs/123",
    headers={"X-API-KEY": "pk_live_your_api_key"},
)
print(res.json())
using var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://api.primeverifier.com/v1/jobs/123");
req.Headers.Add("X-API-KEY", "pk_live_your_api_key");
var res = await client.SendAsync(req);
Console.WriteLine(await res.Content.ReadAsStringAsync());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.primeverifier.com/v1/jobs/123"))
    .header("X-API-KEY", "pk_live_your_api_key")
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://api.primeverifier.com/v1/jobs/123");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => ["X-API-KEY: pk_live_your_api_key"],
]);
$response = curl_exec($ch);
echo $response;
req, _ := http.NewRequest("GET", "https://api.primeverifier.com/v1/jobs/123", nil)
req.Header.Set("X-API-KEY", "pk_live_your_api_key")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
require "net/http"
require "json"

uri = URI("https://api.primeverifier.com/v1/jobs/123")
req = Net::HTTP::Get.new(uri)
req["X-API-KEY"] = "pk_live_your_api_key"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
Response200 OK
{
  "status": "success",
  "data": {},
  "error": null
}
Try itGET /v1/jobs/{id}
DELETE/v1/jobs/{id}

Cancel a pending or processing bulk job. Cannot cancel jobs that are already completed or cancelled

Parameters
NameInTypeRequiredDescription
idpathinteger · int64required
!

Returns 400, 401, 404 with the error envelope { status, error: { code, message } }. Branch on the numeric error.code, never the message.

Request
curl -X DELETE "https://api.primeverifier.com/v1/jobs/123" \
  -H "X-API-KEY: pk_live_your_api_key"
const res = await fetch("https://api.primeverifier.com/v1/jobs/123", {
  method: "DELETE",
  headers: {
    "X-API-KEY": "pk_live_your_api_key",
  },
});
const data = await res.json();
console.log(data);
import requests

res = requests.delete(
    "https://api.primeverifier.com/v1/jobs/123",
    headers={"X-API-KEY": "pk_live_your_api_key"},
)
print(res.json())
using var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Delete, "https://api.primeverifier.com/v1/jobs/123");
req.Headers.Add("X-API-KEY", "pk_live_your_api_key");
var res = await client.SendAsync(req);
Console.WriteLine(await res.Content.ReadAsStringAsync());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.primeverifier.com/v1/jobs/123"))
    .header("X-API-KEY", "pk_live_your_api_key")
    .method("DELETE", HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://api.primeverifier.com/v1/jobs/123");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "DELETE",
    CURLOPT_HTTPHEADER => ["X-API-KEY: pk_live_your_api_key"],
]);
$response = curl_exec($ch);
echo $response;
req, _ := http.NewRequest("DELETE", "https://api.primeverifier.com/v1/jobs/123", nil)
req.Header.Set("X-API-KEY", "pk_live_your_api_key")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
require "net/http"
require "json"

uri = URI("https://api.primeverifier.com/v1/jobs/123")
req = Net::HTTP::Delete.new(uri)
req["X-API-KEY"] = "pk_live_your_api_key"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
Response200 OK
{
  "status": "success",
  "data": {},
  "error": null
}
Try itDELETE /v1/jobs/{id}
GET/v1/jobs/{id}/download

Download the CSV results for a bulk job. When the job is `Completed` this is the full file; when it is still `Processing` it streams the rows verified so far (a partial download, flagged with the `X-Partial-Result` response header) so callers don't wait for a huge job to finish

Parameters
NameInTypeRequiredDescription
idpathinteger · int64required
columnsquerystringoptional
!

Returns 400, 401, 404 with the error envelope { status, error: { code, message } }. Branch on the numeric error.code, never the message.

Request
curl -X GET "https://api.primeverifier.com/v1/jobs/123/download?columns=string" \
  -H "X-API-KEY: pk_live_your_api_key"
const res = await fetch("https://api.primeverifier.com/v1/jobs/123/download?columns=string", {
  method: "GET",
  headers: {
    "X-API-KEY": "pk_live_your_api_key",
  },
});
const data = await res.json();
console.log(data);
import requests

res = requests.get(
    "https://api.primeverifier.com/v1/jobs/123/download?columns=string",
    headers={"X-API-KEY": "pk_live_your_api_key"},
)
print(res.json())
using var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://api.primeverifier.com/v1/jobs/123/download?columns=string");
req.Headers.Add("X-API-KEY", "pk_live_your_api_key");
var res = await client.SendAsync(req);
Console.WriteLine(await res.Content.ReadAsStringAsync());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.primeverifier.com/v1/jobs/123/download?columns=string"))
    .header("X-API-KEY", "pk_live_your_api_key")
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://api.primeverifier.com/v1/jobs/123/download?columns=string");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => ["X-API-KEY: pk_live_your_api_key"],
]);
$response = curl_exec($ch);
echo $response;
req, _ := http.NewRequest("GET", "https://api.primeverifier.com/v1/jobs/123/download?columns=string", nil)
req.Header.Set("X-API-KEY", "pk_live_your_api_key")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
require "net/http"
require "json"

uri = URI("https://api.primeverifier.com/v1/jobs/123/download?columns=string")
req = Net::HTTP::Get.new(uri)
req["X-API-KEY"] = "pk_live_your_api_key"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
Response200 OK
{
  "status": "success",
  "data": {},
  "error": null
}
Try itGET /v1/jobs/{id}/download
GET/v1/jobs/{id}/stream

Live progress stream (Server-Sent Events). Emits a `progress` event about once a second with the job's current status + counts, then a final `done` event when it reaches a terminal state , so a client sees near-real-time progress over a single connection instead of polling

Per-email result push (each verdict the instant it lands) is the next layer and needs a shared bus (Redis pub/sub) between the Worker and API; this DB-backed progress stream needs no extra infra.

Parameters
NameInTypeRequiredDescription
idpathinteger · int64required
!

Returns 401, 404 with the error envelope { status, error: { code, message } }. Branch on the numeric error.code, never the message.

Request
curl -X GET "https://api.primeverifier.com/v1/jobs/123/stream" \
  -H "X-API-KEY: pk_live_your_api_key"
const res = await fetch("https://api.primeverifier.com/v1/jobs/123/stream", {
  method: "GET",
  headers: {
    "X-API-KEY": "pk_live_your_api_key",
  },
});
const data = await res.json();
console.log(data);
import requests

res = requests.get(
    "https://api.primeverifier.com/v1/jobs/123/stream",
    headers={"X-API-KEY": "pk_live_your_api_key"},
)
print(res.json())
using var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://api.primeverifier.com/v1/jobs/123/stream");
req.Headers.Add("X-API-KEY", "pk_live_your_api_key");
var res = await client.SendAsync(req);
Console.WriteLine(await res.Content.ReadAsStringAsync());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.primeverifier.com/v1/jobs/123/stream"))
    .header("X-API-KEY", "pk_live_your_api_key")
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://api.primeverifier.com/v1/jobs/123/stream");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => ["X-API-KEY: pk_live_your_api_key"],
]);
$response = curl_exec($ch);
echo $response;
req, _ := http.NewRequest("GET", "https://api.primeverifier.com/v1/jobs/123/stream", nil)
req.Header.Set("X-API-KEY", "pk_live_your_api_key")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
require "net/http"
require "json"

uri = URI("https://api.primeverifier.com/v1/jobs/123/stream")
req = Net::HTTP::Get.new(uri)
req["X-API-KEY"] = "pk_live_your_api_key"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
Try itGET /v1/jobs/{id}/stream