API reference / Jobs
Jobs
A job is a single unit of background work: a target URL, a JSON payload, and the rules for when and how Tend should run it. Create a job with run_at for a delayed one-off, or omit it to run immediately. Tend delivers the payload to your target, records each attempt as a run, and retries failures with exponential backoff and full jitter. Payloads are limited to 256 KB after JSON encoding, and a single attempt may run for up to 15 minutes.
The job object
| Field | Type | Description |
|---|---|---|
id | string | Unique job identifier, prefixed job_. Immutable. |
status | string | One of queued, running, succeeded, failed, or canceled. A job is failed only after its final retry attempt. |
target_url | string | The HTTPS URL that receives the payload when the job runs. |
payload | object | Arbitrary JSON delivered to the target. Maximum 256 KB after encoding. |
run_at | string (ISO 8601) | When the job is scheduled to first run. Equal to created_at for immediate jobs. |
region | string | Region that executes the job: us-east, us-west, eu-central, or ap-southeast. Defaults to us-east. |
retry_policy | object | Contains max_attempts (default 5, maximum 25), base_seconds (default 10), and cap_seconds (default 3600, range 1 to 86400). |
attempts | integer | Number of runs recorded so far, including the one in progress. |
created_at | string (ISO 8601) | Timestamp of job creation, in UTC. |
#Create a job
POST /v2/jobs
Creates a job and queues it for execution at run_at, or immediately if run_at is omitted. Send an Idempotency-Key header to make retries of this call safe for 24 hours. Requests with a run_at more than 60 seconds in the past are rejected with run_at_in_past.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
target_url | body | string | yes | HTTPS URL that will receive the payload. |
payload | body | object | no | JSON payload to deliver. Defaults to an empty object. Maximum 256 KB. |
run_at | body | string (ISO 8601) | no | Time of first execution. Omit to run immediately. |
region | body | string | no | Region to execute in. Hobby projects are limited to us-east. |
retry_policy | body | object | no | Overrides max_attempts, base_seconds, and cap_seconds for this job. |
Idempotency-Key | header | string | no | Unique string per logical request. Reusing it within 24 hours with a different body returns idempotency_conflict. |
curl -X POST https://api.tendcomputer.com/v2/jobs \
-H "Authorization: Bearer tnd_live_8fQ2xLm9Zc41" \
-H "Idempotency-Key: invoice-4471-reminder" \
-H "Content-Type: application/json" \
-d '{"target_url":"https://billing.example-shop.dev/hooks/remind","payload":{"invoice_id":4471},"run_at":"2026-05-14T09:00:00Z","region":"eu-central","retry_policy":{"max_attempts":8}}'{
"id": "job_01HZX7Q4M2",
"status": "queued",
"target_url": "https://billing.example-shop.dev/hooks/remind",
"payload": { "invoice_id": 4471 },
"run_at": "2026-05-14T09:00:00Z",
"region": "eu-central",
"retry_policy": {
"max_attempts": 8,
"base_seconds": 10,
"cap_seconds": 3600
},
"attempts": 0,
"created_at": "2026-05-12T16:22:41Z"
}#Retrieve a job
GET /v2/jobs/{job_id}
Returns a single job by ID, including its current status and attempt count. Jobs are scoped to the environment of the key, so a tnd_dev_ key cannot read a job created with a tnd_live_ key and receives resource_not_found instead.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
job_id | path | string | yes | The job ID, beginning with job_. |
curl https://api.tendcomputer.com/v2/jobs/job_01HZX7Q4M2 \
-H "Authorization: Bearer tnd_live_8fQ2xLm9Zc41"{
"id": "job_01HZX7Q4M2",
"status": "succeeded",
"target_url": "https://billing.example-shop.dev/hooks/remind",
"payload": { "invoice_id": 4471 },
"run_at": "2026-05-14T09:00:00Z",
"region": "eu-central",
"retry_policy": {
"max_attempts": 8,
"base_seconds": 10,
"cap_seconds": 3600
},
"attempts": 2,
"created_at": "2026-05-12T16:22:41Z"
}#List jobs
GET /v2/jobs
Returns jobs in reverse chronological order using cursor-based pagination. Pass limit (default 50, maximum 200) and the next_cursor value from the previous response to fetch the next page. When next_cursor is null, you have reached the end.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | no | Page size. Default 50, maximum 200. |
cursor | query | string | no | The next_cursor value from the previous response. |
status | query | string | no | Filter by status: queued, running, succeeded, failed, or canceled. |
region | query | string | no | Filter by region ID. |
curl "https://api.tendcomputer.com/v2/jobs?status=failed&limit=2" \
-H "Authorization: Bearer tnd_live_8fQ2xLm9Zc41"{
"data": [
{
"id": "job_01HZX9B7T5",
"status": "failed",
"target_url": "https://api.example-shop.dev/sync",
"region": "us-west",
"attempts": 5,
"created_at": "2026-05-13T08:04:10Z"
},
{
"id": "job_01HZX6D1K8",
"status": "failed",
"target_url": "https://api.example-shop.dev/export",
"region": "us-east",
"attempts": 5,
"created_at": "2026-05-11T22:47:03Z"
}
],
"next_cursor": "cur_WzE3NDc5"
}#Cancel a job
DELETE /v2/jobs/{job_id}
Cancels a job that is still queued, preventing any further attempts. A job that is already running finishes its current attempt but is not retried. Jobs in a terminal state cannot be canceled and return invalid_request.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
job_id | path | string | yes | The job ID, beginning with job_. |
curl -X DELETE https://api.tendcomputer.com/v2/jobs/job_01HZXB3N6R \
-H "Authorization: Bearer tnd_live_8fQ2xLm9Zc41"{
"id": "job_01HZXB3N6R",
"status": "canceled",
"target_url": "https://billing.example-shop.dev/hooks/remind",
"run_at": "2026-05-20T09:00:00Z",
"region": "us-east",
"attempts": 0,
"created_at": "2026-05-13T10:15:56Z"
}