---
title: "Ask a running bulk job to stop"
method: POST
path: "/v1/vat/bulk/{jobId}/cancel"
tags: ["VAT validation"]
---

# Ask a running bulk job to stop

`POST /v1/vat/bulk/{jobId}/cancel`

## Request

- Base URL: `https://api.vatnode.dev`
- URL: `https://api.vatnode.dev/v1/vat/bulk/{jobId}/cancel`
- Auth: HTTP bearer

Idempotent. The job stops at its next position and ends `cancelled`;
positions already answered keep their result and stay billed – the
check ran and its record exists. Positions it had not reached stay
`pending` for good and are not charged. Cancelling an already-finished
job changes nothing and returns it as it stands.

Revoking the API key a job was submitted with stops it the same way:
revocation means nothing more is read or written with that key, and a
running batch is no exception. Such a job ends `cancelled` with
`errorCode: API_KEY_REVOKED`. Everything it had already collected stays
readable through your other keys and in your check history.

## Path parameters

- `jobId` string, uuid, required

## Response `200`

The job as it now stands.

- BulkJob
  - `jobId` string, uuid, required
  - `status` 'queued' | 'processing' | 'finished' | 'cancelled' | 'failed', required: `finished` means every position has an answer – including positions that answered with an error. It is not a claim that every VAT ID was successfully validated; read `summary`. `cancelled` means the job stopped early: positions it had already answered keep their results, the rest stay `pending` and unbilled. `failed` also means the job stopped early, for a reason of its own rather than a stop it was asked for; `errorCode` says which. Positions are treated exactly as under `cancelled`. All three are terminal. Branch on the terminal set, not on `finished` alone, so a job that ends any other way does not leave a poller running until the job expires.
  - `totalItems` integer, required
  - `processedItems` integer, required
  - `summary` object, required
    - `valid` integer, required
    - `invalid` integer, required
    - `errors` integer, required: Positions that carry an `error` object.
  - `createdAt` string, date-time, required
  - `startedAt` string, date-time, nullable
  - `finishedAt` string, date-time, nullable
  - `cancelRequestedAt` string, date-time, nullable: When a cancel was first requested; the job may still be stopping. A `cancelled` job can have this `null` – it was stopped by something other than a cancel request, and `errorCode` says what.
  - `expiresAt` string, date-time, required: When the job and its positions are deleted (30 days after submission). The underlying checks remain in your check history.
  - `errorCode` string, nullable: Why the job ended the way it did, when that needs saying. `null` for an ordinary run and for a cancel you requested. `API_KEY_REVOKED` means the API key the job was submitted with was revoked while it was running, so it stopped where it stood.

## Other responses

- `400`: The request body, query string or path parameters failed structural validation (wrong type, missing required field, out-of-range length, malformed enum, etc.). Returns the standard error envelope with code `INVALID_REQUEST`. This is distinct from a semantically well-formed request that is rejected later (e.g. `INVALID_FORMAT` for a VAT ID that parses but is not a valid VAT number).
- `401`: Missing or invalid API key.
- `404`: The addressed resource does not exist, or is not owned by the authenticated caller. Returns the standard error envelope with code `NOT_FOUND`. Ownership and existence are deliberately not distinguished, so a resource belonging to another account is reported as missing rather than forbidden.

---

[API](https://skmtc.dev/vatnode/apis/vatnode-api.md) · [All operations](https://skmtc.dev/vatnode/apis/vatnode-api/llms.txt) · [OpenAPI document](https://skmtc.dev/vatnode/apis/vatnode-api/revisions/c65828db2037?raw)
