Job Runner
Manage scheduled HTTP jobs and trigger them on demand.
Job Runner API
List Jobs
job_runner:readPath, query, and header parameters
sizepageResponses
Job runner list returned.
{
"entities": "JobRunner",
"count": 1,
"per_page": 50,
"pages": {
"current": 1,
"max": 1
},
"elements": [
{
"id": "681f10...",
"title": "Sync CRM Contacts",
"method": "POST",
"url": "https://api.partner.com/sync",
"content_type": "application/json",
"has_body": true,
"schedulation": [
"08:00",
"14:30"
]
}
]
}Request examples
curl --request GET 'https://api.hub.donutwork.com/2026-02-01/job-runner.json' \
--header 'Authorization: Bearer YOUR_API_KEY'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/job-runner.json', {
method: 'GET',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
},
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/job-runner.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
],
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.
Create Job
job_runner:writePath, query, and header parameters
No path, query, or additional header parameters.
Request Body
{
"jobrunner": {
"title": "Sync CRM Contacts",
"method": "POST",
"url": "https://api.partner.com/sync",
"content_type": "application/json",
"body": "{\"scope\":\"daily\"}",
"schedulation": [
"08:00",
"14:30"
]
}
}jobrunnerRequiredResponses
Job runner created.
{
"id": "681f10...",
"created": true
}Validation error on payload.
{
"error": "Invalid schedulation time \"24:30\". Use HH:mm format"
}Request examples
curl --request POST 'https://api.hub.donutwork.com/2026-02-01/job-runner.json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"jobrunner": {
"title": "Sync CRM Contacts",
"method": "POST",
"url": "https://api.partner.com/sync",
"content_type": "application/json",
"body": "{\"scope\":\"daily\"}",
"schedulation": [
"08:00",
"14:30"
]
}
}'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/job-runner.json', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"jobrunner": {
"title": "Sync CRM Contacts",
"method": "POST",
"url": "https://api.partner.com/sync",
"content_type": "application/json",
"body": "{\"scope\":\"daily\"}",
"schedulation": [
"08:00",
"14:30"
]
}
}),
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/job-runner.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => '{
"jobrunner": {
"title": "Sync CRM Contacts",
"method": "POST",
"url": "https://api.partner.com/sync",
"content_type": "application/json",
"body": "{\\"scope\\":\\"daily\\"}",
"schedulation": [
"08:00",
"14:30"
]
}
}',
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.
Run Job
job_runner:writePath, query, and header parameters
jobRunnerIdRequiredResponses
Job execution completed.
{
"job_runner_id": "681f10...",
"status": "success",
"headers": [
"HTTP/1.1 200 OK"
],
"response": "{\"ok\":true}",
"ms": 122.45
}Request examples
curl --request POST 'https://api.hub.donutwork.com/2026-02-01/job-runner/JOBRUNNERID/run.json' \
--header 'Authorization: Bearer YOUR_API_KEY'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/job-runner/JOBRUNNERID/run.json', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
},
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/job-runner/JOBRUNNERID/run.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
],
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.
Delete Job
job_runner:writePath, query, and header parameters
jobRunnerIdRequiredResponses
Job runner deleted.
{
"id": "681f10...",
"deleted": true
}Request examples
curl --request DELETE 'https://api.hub.donutwork.com/2026-02-01/job-runner/JOBRUNNERID.json' \
--header 'Authorization: Bearer YOUR_API_KEY'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/job-runner/JOBRUNNERID.json', {
method: 'DELETE',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
},
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/job-runner/JOBRUNNERID.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
],
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.