# Purge jobs (/api-v2/purge-jobs)



Delete revokes a handle immediately. Purge is the auditable workflow: it bumps the namespace generation, physically removes the in-scope artifacts, and returns a profile-specific receipt with a tamper-evident digest. The guarantee class never exceeds what the processors actually achieved. Purge jobs are prefixed `pjb_`; receipts are prefixed `pur_`. See [retention and purge](/concepts/retention-and-purge) and the [purge semantics guide](/guides/purge-semantics).

All requests require a bearer API key. See [authentication](/api-reference/authentication).

## Create a purge job [#create-a-purge-job]

`POST /v2/purge-jobs`

Runs the purge synchronously and stores both the job and its receipt.

<ParamField body="artifact_ids" type="array">
  The `art_...` ids to purge. Must not be empty, and each must exist in this project.
</ParamField>

```bash
curl https://api.zumik.ai/v2/purge-jobs \
  -H "Authorization: Bearer $ZUMIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "artifact_ids": ["art_01jy7n3q8v6kzr4w2m9bd5xpfh"] }'
```

```json
{
  "id": "pjb_01jy7ngh12k3l4m5n6o7p8q9rs",
  "object": "purge_job",
  "status": "completed",
  "scope": {
    "project_id": "prj_01jy7n0a4c8m2t6v9q3wrxk7bd",
    "artifact_ids": ["art_01jy7n3q8v6kzr4w2m9bd5xpfh"]
  },
  "requested_at": "2026-06-15T16:21:50Z"
}
```

<ResponseField name="id" type="string">
  Opaque purge job id, prefixed `pjb_`.
</ResponseField>

<ResponseField name="object" type="string">
  Always `purge_job`.
</ResponseField>

<ResponseField name="status" type="string">
  One of `pending`, `running`, `completed`, `failed`.
</ResponseField>

<ResponseField name="scope" type="object">
  The project and artifact ids the job covered.
</ResponseField>

<ResponseField name="requested_at" type="string">
  RFC 3339 request timestamp.
</ResponseField>

## Retrieve a purge job [#retrieve-a-purge-job]

`GET /v2/purge-jobs/{purge_job_id}`

<ParamField path="purge_job_id" type="string">
  The `pjb_...` id to fetch.
</ParamField>

```bash
curl https://api.zumik.ai/v2/purge-jobs/pjb_01jy7ngh12k3l4m5n6o7p8q9rs \
  -H "Authorization: Bearer $ZUMIK_API_KEY"
```

Returns the same job object.

## Retrieve the receipt [#retrieve-the-receipt]

`GET /v2/purge-jobs/{purge_job_id}/receipt`

Returns the signed receipt for the job, keyed by the purge job id. The receipt records each processor's outcome and the weakest guarantee across them.

<ParamField path="purge_job_id" type="string">
  The `pjb_...` id whose receipt to fetch.
</ParamField>

```bash
curl https://api.zumik.ai/v2/purge-jobs/pjb_01jy7ngh12k3l4m5n6o7p8q9rs/receipt \
  -H "Authorization: Bearer $ZUMIK_API_KEY"
```

```json
{
  "id": "pur_01jy7ngh20l4m5n6o7p8q9r0st",
  "object": "purge_receipt",
  "requested_at": "2026-06-15T16:21:50Z",
  "completed_at": "2026-06-15T16:21:50Z",
  "scope": {
    "project_id": "prj_01jy7n0a4c8m2t6v9q3wrxk7bd",
    "artifact_ids": ["art_01jy7n3q8v6kzr4w2m9bd5xpfh"]
  },
  "guarantee": "verified_physical_purge",
  "processors": [
    { "name": "state_store", "status": "purged" }
  ],
  "receipt_digest": "sha256:9c1d...e4"
}
```

<ResponseField name="id" type="string">
  Opaque receipt id, prefixed `pur_`.
</ResponseField>

<ResponseField name="object" type="string">
  Always `purge_receipt`.
</ResponseField>

<ResponseField name="requested_at" type="string">
  RFC 3339 request timestamp.
</ResponseField>

<ResponseField name="completed_at" type="string">
  RFC 3339 completion timestamp.
</ResponseField>

<ResponseField name="scope" type="object">
  The project and artifact ids the purge covered.
</ResponseField>

<ResponseField name="guarantee" type="string">
  The weakest guarantee across all processors: `access_revoked`, `best_effort_expiry`, `verified_namespace_invalidation`, `verified_physical_purge`, or `cryptographic_purge`.
</ResponseField>

<ResponseField name="processors" type="array">
  Per-processor outcomes. Each has a `name` (e.g. `state_store`, `byoc_runtime`), a `status` (`purged`, `namespace_invalidated`, `expires_by`, `failed`), and an optional `expires_at`. A `byoc_runtime` entry appears only when the project has live BYOC clusters that honor the generation bump.
</ResponseField>

<ResponseField name="receipt_digest" type="string">
  A SHA-256 over the receipt's identifying content, prefixed `sha256:`. Recompute it to confirm the receipt was not altered.
</ResponseField>

## Errors [#errors]

| Status | Code                    | When                                                              |
| ------ | ----------------------- | ----------------------------------------------------------------- |
| 400    | `invalid_request_error` | `artifact_ids` is empty, or an id does not exist in this project. |
| 401    | `invalid_api_key`       | Missing or invalid API key.                                       |
| 404    | `invalid_request_error` | The purge job or its receipt does not exist in this project.      |

See the full table on [errors](/api-reference/errors).
