curl --request POST \
--url https://async.api.zenrows.com/v1/jobs \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"type": "regular",
"status": "closed"
}
'import requests
url = "https://async.api.zenrows.com/v1/jobs"
payload = {
"type": "regular",
"status": "closed"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({type: 'regular', status: 'closed'})
};
fetch('https://async.api.zenrows.com/v1/jobs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://async.api.zenrows.com/v1/jobs';
const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({type: 'regular', status: 'closed'})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://async.api.zenrows.com/v1/jobs"
payload := strings.NewReader("{\n \"type\": \"regular\",\n \"status\": \"closed\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-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))
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://async.api.zenrows.com/v1/jobs",
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([
'type' => 'regular',
'status' => 'closed'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}require 'uri'
require 'net/http'
url = URI("https://async.api.zenrows.com/v1/jobs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"regular\",\n \"status\": \"closed\"\n}"
response = http.request(request)
puts response.read_bodyHttpResponse<String> response = Unirest.post("https://async.api.zenrows.com/v1/jobs")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"regular\",\n \"status\": \"closed\"\n}")
.asString();{
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"status": "closed",
"accepted_tasks": 2,
"latest_run": {
"run_id": "01M4E06YS7VZPY4G25DV6FR3B8",
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"run_sequence": 1,
"status": "running",
"trigger": "manual",
"last_batch_received": false,
"stats": {
"total": 2,
"completed": 0,
"successful": 0,
"failed": 0
},
"created_at": "2026-10-08T14:55:52Z",
"updated_at": "2026-10-08T14:56:06Z"
}
}{
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"status": "closed",
"accepted_tasks": 2,
"latest_run": {
"run_id": "01M4E06YS7VZPY4G25DV6FR3B8",
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"run_sequence": 1,
"status": "running",
"trigger": "manual",
"last_batch_received": false,
"stats": {
"total": 2,
"completed": 0,
"successful": 0,
"failed": 0
},
"created_at": "2026-10-08T14:55:52Z",
"updated_at": "2026-10-08T14:56:06Z"
}
}{
"code": "invalid_argument",
"detail": "Validation failed.",
"instance": "/v1",
"status": 400,
"title": "Validation failed (invalid_argument)",
"type": "https://docs.zenrows.com/api-error-codes#invalid_argument"
}{
"code": "unauthenticated",
"detail": "Invalid API key.",
"instance": "/v1",
"status": 401,
"title": "Unauthenticated (unauthenticated)",
"type": "https://docs.zenrows.com/api-error-codes#unauthenticated"
}{
"code": "payment_required",
"detail": "No credits available.",
"instance": "/v1",
"status": 402,
"title": "No credits available (payment_required)",
"type": "https://docs.zenrows.com/api-error-codes#payment_required"
}{
"code": "idempotency_key_conflict",
"detail": "Idempotency key already used.",
"instance": "/v1",
"status": 409,
"title": "Idempotency key already used (idempotency_key_conflict)",
"type": "https://docs.zenrows.com/api-error-codes#idempotency_key_conflict"
}{
"code": "quota_exceeded",
"detail": "Too many active jobs.",
"instance": "/v1",
"status": 429,
"title": "Too many active jobs (quota_exceeded)",
"type": "https://docs.zenrows.com/api-error-codes#quota_exceeded"
}{
"code": "internal",
"detail": "Temporary failure, retry with backoff.",
"instance": "/v1",
"status": 503,
"title": "Temporary failure, retry with backoff (internal)",
"type": "https://docs.zenrows.com/api-error-codes#internal"
}Create a batch job (many URLs in one request)
Submit a job. A closed job carries all its URLs up front in tasks; an open job (status: open) is created empty and receives URLs through addBatchTasks until one call sets last_batch. A scheduled job (type: scheduled) stores its URLs as a template and each fire creates a run. zenrows_params applies to every task and a per-task zenrows_params overrides it. Returns 201 under 10,000 inline tasks and 202 at or above that (or for a CSV input); the body is identical, so treat both the same. Documented at https://docs.zenrows.com/batch/developer-guide-restapi#1-create-your-jobs.
curl --request POST \
--url https://async.api.zenrows.com/v1/jobs \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"type": "regular",
"status": "closed"
}
'import requests
url = "https://async.api.zenrows.com/v1/jobs"
payload = {
"type": "regular",
"status": "closed"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({type: 'regular', status: 'closed'})
};
fetch('https://async.api.zenrows.com/v1/jobs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://async.api.zenrows.com/v1/jobs';
const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({type: 'regular', status: 'closed'})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://async.api.zenrows.com/v1/jobs"
payload := strings.NewReader("{\n \"type\": \"regular\",\n \"status\": \"closed\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-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))
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://async.api.zenrows.com/v1/jobs",
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([
'type' => 'regular',
'status' => 'closed'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}require 'uri'
require 'net/http'
url = URI("https://async.api.zenrows.com/v1/jobs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"regular\",\n \"status\": \"closed\"\n}"
response = http.request(request)
puts response.read_bodyHttpResponse<String> response = Unirest.post("https://async.api.zenrows.com/v1/jobs")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"regular\",\n \"status\": \"closed\"\n}")
.asString();{
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"status": "closed",
"accepted_tasks": 2,
"latest_run": {
"run_id": "01M4E06YS7VZPY4G25DV6FR3B8",
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"run_sequence": 1,
"status": "running",
"trigger": "manual",
"last_batch_received": false,
"stats": {
"total": 2,
"completed": 0,
"successful": 0,
"failed": 0
},
"created_at": "2026-10-08T14:55:52Z",
"updated_at": "2026-10-08T14:56:06Z"
}
}{
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"status": "closed",
"accepted_tasks": 2,
"latest_run": {
"run_id": "01M4E06YS7VZPY4G25DV6FR3B8",
"job_id": "01M4E06YS7BDRECVN5QRHJA6HR",
"run_sequence": 1,
"status": "running",
"trigger": "manual",
"last_batch_received": false,
"stats": {
"total": 2,
"completed": 0,
"successful": 0,
"failed": 0
},
"created_at": "2026-10-08T14:55:52Z",
"updated_at": "2026-10-08T14:56:06Z"
}
}{
"code": "invalid_argument",
"detail": "Validation failed.",
"instance": "/v1",
"status": 400,
"title": "Validation failed (invalid_argument)",
"type": "https://docs.zenrows.com/api-error-codes#invalid_argument"
}{
"code": "unauthenticated",
"detail": "Invalid API key.",
"instance": "/v1",
"status": 401,
"title": "Unauthenticated (unauthenticated)",
"type": "https://docs.zenrows.com/api-error-codes#unauthenticated"
}{
"code": "payment_required",
"detail": "No credits available.",
"instance": "/v1",
"status": 402,
"title": "No credits available (payment_required)",
"type": "https://docs.zenrows.com/api-error-codes#payment_required"
}{
"code": "idempotency_key_conflict",
"detail": "Idempotency key already used.",
"instance": "/v1",
"status": 409,
"title": "Idempotency key already used (idempotency_key_conflict)",
"type": "https://docs.zenrows.com/api-error-codes#idempotency_key_conflict"
}{
"code": "quota_exceeded",
"detail": "Too many active jobs.",
"instance": "/v1",
"status": 429,
"title": "Too many active jobs (quota_exceeded)",
"type": "https://docs.zenrows.com/api-error-codes#quota_exceeded"
}{
"code": "internal",
"detail": "Temporary failure, retry with backoff.",
"instance": "/v1",
"status": 503,
"title": "Temporary failure, retry with backoff (internal)",
"type": "https://docs.zenrows.com/api-error-codes#internal"
}Authorizations
Batch, Crawl, the Extract endpoints and the account endpoint read the same key from the X-API-Key header.
Headers
Optional guard against creating duplicate jobs. Each key can be used once: the first submit with a key creates the job, and any later submit reusing it returns 409 idempotency_key_conflict, whether or not the body is identical. The original response is not replayed, so this is not a safe-retry token: if a submit fails midway, list your recent jobs to see whether it was created, then reuse its job_id or submit again with a new key.
Body
regular runs when submitted; scheduled runs on the schedule.
regular, scheduled closed carries every URL now; open accepts URLs over time through addBatchTasks.
closed, open Your own label for the job.
Your own identifier for the job.
Your own key-value data, returned with the job.
Fetch parameters applied to every task, with the names the fetchPage operation uses.
The URLs to run, up to 100,000 per submit. Omit for an open job and when file_input_id is set.
100000Show child attributes
Show child attributes
From uploadBatchInput, to run the job from an uploaded CSV instead of inline tasks. Always answers 202.
Exactly one of at, rate or calendar, plus timezone for at and calendar. Times of day are full hours; runs are at least 60 minutes apart.
Show child attributes
Show child attributes
Where run notifications (run.completed, run.failed) are delivered.
Show child attributes
Show child attributes
Response
Job accepted, under 10,000 inline tasks.
Was this page helpful?