Endpoints // Bulk
Stop a job an API key or an AI assistant started, for good. Items not started are never charged, and the results of the items done stay downloadable.
Credits
Free.
Items that had not started are never charged.
Introduction
The Cancel a job endpoint stops a job for good. Items already in flight may finish and are charged as usual; items not started are never charged and read skipped in the results. The job then reads cancelled, and the results of the items done can be downloaded with Download job results. An item in flight finishes within the hour: until then, its row of the results file reads running, and Read job results by page waits for it.
Any key of the workspace that can read a job can cancel it, whichever key started it: a rotated key can still stop a job its predecessor created. This covers every job of the history that an API key or an AI assistant started (source is api or mcp), a List import included. A job a person started in the app or with Ask is stopped there: cancelling it here returns 403 JOB_STARTED_BY_A_PERSON.
Cancelling is free (0 credits), also at a zero balance, and final: a cancelled job is never resumed, and a new run needs a new job. Cancelling a job already cancelled answers it again. When the job has a webhookUrl, that URL receives the cancelled state.
Authorization
| Name | Type | Required | Description |
|---|---|---|---|
apikey | string | Yes | Your API key from the developer dashboard. Pass it via Authorization: Bearer YOUR_API_KEY header. |
Request
The route is POST /v2/jobs/:jobId/cancel.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
jobId | string | Yes | The id of the job (UUID) |
The request has no body.
Response structure
| Field | Type | Description |
|---|---|---|
success | boolean | true if the job was cancelled |
error | null | Always null on success |
data is the cancelled job, with the fields of Get a job and status set to cancelled. Its progress can still move while the items in flight finish, and credits.used stays null until the job has settled its credits (a List import counts them as it goes): read the job again to see the final counts.
quotas and metadata are the blocks of every V2 response: see Usage.
Errors
| Status | Code | Meaning |
|---|---|---|
403 | JOB_STARTED_BY_A_PERSON | A person started this job in the app or with Ask: stop it there |
404 | JOB_NOT_FOUND | No job with this id in your workspace, or one your key may not read |
409 | JOB_NOT_CANCELLABLE | The job already completed or failed: there is nothing left to stop |
422 | VALIDATION_ERROR | jobId is not a UUID |
Code examples
Code Examples
curl -X POST https://api.reversecontact.com/v2/jobs/7b1e4c2a-5d3f-4e8b-9a6c-1f2d3e4b5a60/cancel \
-H "Authorization: Bearer YOUR_API_KEY"const jobId = "7b1e4c2a-5d3f-4e8b-9a6c-1f2d3e4b5a60";
const response = await fetch(`https://api.reversecontact.com/v2/jobs/${jobId}/cancel`, {
method: "POST",
headers: { "Authorization": "Bearer YOUR_API_KEY" }
});
const { data, error } = await response.json();
console.log(error ? error.code : `${data.status}, ${data.progress.remaining} items not started`);import requests
job_id = "7b1e4c2a-5d3f-4e8b-9a6c-1f2d3e4b5a60"
response = requests.post(
f"https://api.reversecontact.com/v2/jobs/{job_id}/cancel",
headers={"Authorization": "Bearer YOUR_API_KEY"}
)
payload = response.json()
print(payload["error"]["code"] if payload["error"] else payload["data"]["status"])Example response
Example Response
{
"success": true,
"data": {
"id": "5e8d2c1b-9a4f-4b3e-8c7d-6f5a4b3c2d10",
"type": "enrich_persons",
"entity": "persons",
"status": "cancelled",
"source": "api",
"name": "Leads, Q4",
"listId": null,
"progress": {
"total": 500,
"processed": 120,
"succeeded": 97,
"failed": 23,
"skipped": 0,
"remaining": 380
},
"credits": { "estimated": 1000, "used": null },
"estimatedSecondsRemaining": null,
"error": null,
"createdAt": "2026-11-04T10:02:00.000Z",
"startedAt": "2026-11-04T10:02:01.000Z",
"completedAt": "2026-11-04T10:04:30.000Z",
"links": {
"self": "/v2/jobs/5e8d2c1b-9a4f-4b3e-8c7d-6f5a4b3c2d10",
"results": "/v2/jobs/5e8d2c1b-9a4f-4b3e-8c7d-6f5a4b3c2d10/results",
"operation": null
}
},
"error": null,
"quotas": {
"creditsConsumed": 0,
"workspace": {
"id": "ws_abc123",
"credits": { "total": 10000, "used": 5472, "left": 4528 }
}
},
"metadata": {
"requestId": "req_c1a2n3c4e5l6",
"executionTimeMs": 48
}
}{
"success": false,
"data": null,
"error": {
"code": "JOB_NOT_CANCELLABLE",
"message": "The job is completed and can no longer be cancelled"
},
"quotas": {
"creditsConsumed": 0,
"workspace": {
"id": "ws_abc123",
"credits": { "total": 10000, "used": 4528, "left": 5472 }
}
},
"metadata": {
"requestId": "req_c1a2n3c4e5l7",
"executionTimeMs": 21
}
}