Diff Batches
A diff batch compares two capture batches page by page: the reference and the candidate. Each page compared is a diff task.
Start a diff batch
POST /api/v1/projects/{project_id}/diff-batchesCompares two finished capture batches of the project. Minimum key role: Member.
curl -X POST https://deploydiff.com/api/v1/projects/{project_id}/diff-batches \
-H "Authorization: Bearer dd_…" \
-H "Content-Type: application/json" \
-d '{"reference_capture_batch_id": "00000000-0000-0000-0000-000000000003", "candidate_capture_batch_id": "00000000-0000-0000-0000-000000000002"}'| Body field | Type | Value |
|---|---|---|
reference_capture_batch_id | uuid string | The capture batch to compare against. |
candidate_capture_batch_id | uuid string | The capture batch to review. Another batch. |
The two can be of the same environment or of two environments of the project. Both must be finished: DONE or WARN.
Answers 201 with the new diff_batch, tasks included, and its address in the Location header. The diff belongs to the candidate's environment.
| Status | code | When |
|---|---|---|
| 400 | invalid_body | The body is not a JSON object with both ids as UUIDs, or names the same batch twice. |
| 404 | not_found | One of the batches is not in the project, or its environment was deleted. |
| 409 | capture_not_done | One of the batches is not finished. |
| 402 | usage_limit_reached | The organization's usage limit is reached for the period. |
| 402 | billing_blocked | The organization has an unpaid invoice that was cancelled. |
The batch carries "trigger": "API". Diffs have no interval: you can start as many as you need.
Read a diff batch
GET /api/v1/projects/{project_id}/diff-batches/{diff_batch_id}One diff_batch, with its tasks. Minimum key role: Participant.
List diff batches
GET /api/v1/projects/{project_id}/environments/{environment_id}/diff-batchesThe diff batches whose candidate is in this environment, newest first, as a list of diff_batch objects without their tasks. Takes limit and cursor. Minimum key role: Participant.
The diff_batch object
{
"object": "diff_batch",
"id": "00000000-0000-0000-0000-000000000004",
"environment_id": "00000000-0000-0000-0000-000000000001",
"status": "DONE",
"verdict": "FAIL",
"trigger": "AUTO",
"error": null,
"reference": {
"environment_id": "00000000-0000-0000-0000-000000000001",
"environment_title": "Production",
"capture_batch_id": "00000000-0000-0000-0000-000000000003",
"captured_at": "2026-11-05T10:00:00.2+00:00"
},
"candidate": {
"environment_id": "00000000-0000-0000-0000-000000000001",
"environment_title": "Production",
"capture_batch_id": "00000000-0000-0000-0000-000000000002",
"captured_at": "2026-11-06T10:00:00.31+00:00"
},
"task_counts": {
"pending": 0,
"running": 0,
"done": 11,
"error": 0,
"cancelled": 1
},
"verdict_counts": {
"pass": 10,
"warn": 1,
"fail": 1,
"skipped": 0
},
"tasks": [
{
"id": "00000000-0000-0000-0000-000000000008",
"page": {
"path": "/pricing",
"title": "Pricing"
},
"status": "DONE",
"verdict": "FAIL",
"cancellation_reason": null,
"match_pct": 87.4,
"error_code": null
}
],
"created_at": "2026-11-06T10:02:11.6+00:00",
"updated_at": "2026-11-06T10:03:40.1+00:00"
}| Field | Type | Value |
|---|---|---|
environment_id | uuid string | The candidate's environment, which the diff belongs to. |
status | string | PENDING, RUNNING, DONE, CANCELLED or ERROR — see lifecycle. DONE, CANCELLED and ERROR are final. |
verdict | string | null | PASS, WARN, FAIL or SKIPPED, the result over all its pages — see verdict. null while no page has one, and on a batch in Error. |
trigger | string | What started it: MANUAL (from the dashboard), AUTO (after a capture, by the environment's automated diffing), API (an API call). |
error | object | null | Why the batch failed as a whole, when it did: code and message (see below). null otherwise. |
reference, candidate | object | The two sides. |
….environment_id | uuid string | null | The side's environment. |
….environment_title | string | null | Its name today, or when the diff was made if it was deleted since. |
….capture_batch_id | uuid string | null | The side's capture batch; null when there was none, or once that batch has been deleted — just after a deletion, its id may still be there and read 404. |
….captured_at | timestamp | null | When that capture batch was created; null when there was none. |
task_counts | object | Its tasks by status: pending, running, done, error, cancelled. |
verdict_counts | object | Its tasks by verdict: pass, warn, fail, skipped. |
tasks | array | One entry per page compared. Not in lists. |
tasks[].id | uuid string | The diff task's id. |
tasks[].page | object | null | path and title of the page, as when the diff was made. |
tasks[].status | string | PENDING, RUNNING, DONE, CANCELLED or ERROR. |
tasks[].verdict | string | null | PASS, WARN, FAIL or SKIPPED; null until decided. |
tasks[].cancellation_reason | string | null | Why the page was not compared, when it was CANCELLED — see diff tasks. |
tasks[].match_pct | number | null | How much of the page matched, in percent; null until compared. |
tasks[].error_code | string | null | Why the comparison failed — see when a page comparison fails. |
Batch errors
A diff started automatically can fail as a whole, when there is nothing to compare against: the batch is in ERROR, has no tasks and no verdict, and error says why. Test code in your code; show message to people as it is.
error.code | When | error.message |
|---|---|---|
NO_REFERENCE_CAPTURE | The reference environment has no finished capture yet. | The reference environment "Staging" has no successful capture to compare against. |
REFERENCE_ENVIRONMENT_DELETED | The reference environment was deleted. | The reference environment "Staging" has been deleted. Pick another one in this environment's automation settings. |
A batch can also end in ERROR with error at null, when it could not be started on our side: start it again.
{
"object": "diff_batch",
"id": "00000000-0000-0000-0000-000000000011",
"environment_id": "00000000-0000-0000-0000-000000000001",
"status": "ERROR",
"verdict": null,
"trigger": "AUTO",
"error": {
"code": "NO_REFERENCE_CAPTURE",
"message": "The reference environment \"Staging\" has no successful capture to compare against."
},
"reference": {
"environment_id": "00000000-0000-0000-0000-000000000010",
"environment_title": "Staging",
"capture_batch_id": null,
"captured_at": null
},
"candidate": {
"environment_id": "00000000-0000-0000-0000-000000000001",
"environment_title": "Production",
"capture_batch_id": "00000000-0000-0000-0000-000000000002",
"captured_at": "2026-11-06T10:00:00.31+00:00"
},
"task_counts": {
"pending": 0,
"running": 0,
"done": 0,
"error": 0,
"cancelled": 0
},
"verdict_counts": {
"pass": 0,
"warn": 0,
"fail": 0,
"skipped": 0
},
"tasks": [],
"created_at": "2026-11-06T10:02:11.6+00:00",
"updated_at": "2026-11-06T10:02:11.6+00:00"
}