Purge semantics
The difference between delete and purge, the five guarantee classes, the signed receipt, namespace-generation invalidation, and why a purged artifact can never be resurrected from a stale cache.
Deletion in Zumik is explicit, profile-specific, and verifiable. There are two distinct operations, and they make different promises.
Delete is not purge
| Operation | Promise |
|---|---|
DELETE /v2/artifacts/{id} | Revoke the handle immediately. The id stops resolving. |
POST /v2/purge-jobs | Remove the retained state, invalidate dependent caches, and emit a signed receipt of what was confirmed. |
GET /v2/purge-jobs/{id}/receipt | Retrieve the receipt with per-processor evidence. |
A delete makes the artifact unusable through the API. A purge goes further: it physically removes the stored bytes, bumps the isolation-namespace generation so any cached realization is poisoned, and records cryptographic evidence of the result. Use delete for routine cleanup; use purge when you need to prove state is gone - a data-subject erasure, a leaked secret, an end-of-contract teardown.
Run a purge
POST /v2/purge-jobs with the artifacts in scope. Each must be an artifact in your project.
curl https://api.zumik.ai/v2/purge-jobs \
-H "Authorization: Bearer zk_live_..." \
-H "Content-Type: application/json" \
-d '{"artifact_ids":["art_01jy…"]}'{
"id": "pjb_01jy…",
"object": "purge_job",
"status": "completed",
"scope": { "project_id": "prj_01jy…", "artifact_ids": ["art_01jy…"] },
"requested_at": "2026-06-15T12:00:00Z"
}Under the hood a purge job revokes the handles, tombstones the artifacts and bundles, invalidates the sessions and snapshots that depend on them, increments the namespace purge generation, removes the canonical blobs and materializations, drops retained traces per the project's trace mode, invalidates runtime cache namespaces, requests provider-side deletion where supported, records each processor's acknowledgment, and issues the receipt.
The receipt
GET /v2/purge-jobs/{id}/receipt returns the evidence. It is keyed by the job id.
{
"id": "pur_01jy…",
"object": "purge_receipt",
"requested_at": "2026-06-15T12:00:00Z",
"completed_at": "2026-06-15T12:00:10Z",
"scope": { "project_id": "prj_01jy…", "artifact_ids": ["art_01jy…"] },
"guarantee": "verified_physical_purge",
"processors": [ { "name": "state_store", "status": "purged" } ],
"receipt_digest": "sha256:9f86d081…"
}The receipt_digest is a recomputable SHA-256 over the job id, project id, the new namespace
generation, every artifact id, and the completion time. It is evidence you can verify, not a marketing
checkmark.
Guarantee classes
The receipt's guarantee is the weakest class any in-scope processor reported - a chain is only
as strong as its weakest link. From weakest to strongest:
| Class | Meaning |
|---|---|
access_revoked | Customer handles stop working immediately. |
best_effort_expiry | A provider-controlled cache expires under the provider's own policy; expires_at is reported. |
verified_namespace_invalidation | The namespace generation moved, so any stale physical cache can no longer be reused. |
verified_physical_purge | Managed storage and cache processors confirmed deletion of the bytes. |
cryptographic_purge | Key destruction makes encrypted retained bytes permanently unreadable. |
A purge of an artifact held only in Zumik's own store, with no BYOC runtime attached, reaches
verified_physical_purge - the state store reports purged and there is no weaker processor to drag
the guarantee down. When a self-hosted runtime profile is in scope, a
byoc_runtime processor appears and the guarantee reflects what that runtime could confirm.
The byoc_runtime processor is only added when the project has a live BYOC cluster. Zumik never
fabricates a processor for infrastructure that isn't running, so the guarantee always reflects real
acknowledgments.
Provider-profile limitation
For managed-provider traffic, Zumik can revoke access and invalidate its own caches, but it cannot
force a third-party provider to physically erase a cache faster than that provider's policy allows.
Those processors report best_effort_expiry with a concrete expires_at. The receipt states this
honestly rather than overclaiming a physical purge it cannot verify.
Resurrection prevention
The point of bumping the namespace generation is that a purged artifact can never come back to life
from a cache that outlived it. Physical caches are keyed by generation, so after a purge every prior
realization is unreachable - a stale KV block from before the purge will never be served. This is the
mechanism behind the purge_verification replay class: you can replay traffic that
referenced a purged artifact and confirm it is not reusable.
Verify erasure with replay
Run a purge_verification replay to prove invalidated artifacts cannot be reused.
Billing and budgets
The pricing tiers, prepaid credits, hard monthly caps, 50/80/100% alerts, per-API-key budgets, and opt-in overage - plus how to read your account and what each error means.
Regional policy
Set data residency and allowed regions for a project, and understand how the Execution Broker enforces them by returning region_not_allowed before any provider call.