Retention is a number you set, not a policy you accept. The default is thirty days, the floor is zero, and zero means results are deleted as soon as you have downloaded them.
Zero is a real setting rather than a marketing one, and it has a real cost: once the window closes you cannot re-download that batch, and a support question about a specific result becomes unanswerable because we no longer hold the row. Teams under a data-processing agreement that forbids third-party storage take that trade deliberately.
You can also delete a batch on demand, whatever the window says. The DELETE call removes the uploaded file, the per-address rows and the results export. The ledger entry stays, because a billing record with no corresponding line is its own kind of problem.
# shorten the window for this key
curl -X PATCH https://api.zapbounce.com/v1/account \
-H "Authorization: Bearer zb_live_..." \
-H "Content-Type: application/json" \
-d '{"retention_days": 0}'
# or delete one batch now
curl -X DELETE https://api.zapbounce.com/v1/batches/bat_8f2c1d \
-H "Authorization: Bearer zb_live_..."{
"batch_id": "bat_8f2c1d",
"deleted": true,
"rows_removed": 11480,
"source_file_removed": true,
"ledger_entry_retained": true,
"deleted_at": "2026-09-18T11:02:44Z"
}Fields
| Field | Type | What it carries |
|---|---|---|
| retention_days | integer | 0 to 90. Applies to results and uploaded files for this key. |
| rows_removed | integer | Per-address rows deleted. Verify against your own count. |
| ledger_entry_retained | boolean | Always true. The billing record survives; the addresses do not. |
Three teams, three retention numbers
Say an agency cleans lists for clients under contracts that forbid third-party storage. It sets retention_days to 0 and downloads the moment the webhook arrives. Its job confirms the saved file's row count before doing anything else, because once that window closes there's no second download to fall back on.
A SaaS company checking signups has a different need. Single checks leave little behind, and its weekly batch of new trial users is small, so it picks 7. That's long enough to re-download after a failed import and short enough to explain in a security review.
A marketing team that cleans one big list each quarter keeps the default 30. Its risk is a colleague asking about one odd result three weeks later, and the window keeps that question answerable.
Since settings are per key, one company can run all three. Give the client-work key zero and the internal key thirty.
A download drill for zero retention
With the window at zero, the download is on you, so rehearse it. Save to disk first. Count the rows and compare them with the batch status numbers. Copy the file to its long-term home. Only after that should your job mark the batch as done.
There's a gap we should name. This reference doesn't say whether reading some pages through the cursor counts as having downloaded. Until it does, don't assume either way. Try your exact download path on a small live batch before you trust it with a large one.
When you delete on demand, keep the response. rows_removed and deleted_at are your proof, and rows_removed should equal the row count you held. Paste the JSON into whatever log your privacy lead reads.
Remember the copies on your side as well. Deleting here does nothing about the results file sitting in a shared drive, which is usually the copy that lives longest of all.
Questions developers ask
What does retention_days zero actually do?
Results are deleted once you have downloaded them, and the uploaded file goes with them. Nothing to re-download later.
Does deleting a batch refund credits?
No. The verification was performed; the data is what is being removed.
Can I set different windows per key?
Yes. Retention is a per-key setting, so a short window on production and a longer one on a test key is a normal arrangement.