Retention of receipts and data

A validation by image or PDF leaves three different things behind, and each has its own retention rule:

whatwhere it liveshow long it is kept
The receipt fileFile storageFive years from upload, unless something else is requested with retain_image or with the permanent deletion
The CEPThe XML in the database and the PDF in filesAs long as the validation exists
The extracted data and the Banxico resultDatabaseAs long as the validation exists

Withdrawing a validation with DELETE /v1/validations/{id} changes none of this: it only removes it from the history. Two operations do change what is kept, and each answers a different need.

Not keeping the file: retain_image

retain_image is an optional parameter of POST /v1/validate-ocr, true by default. With false, the file is deleted as soon as the validation reaches a terminal status in which it is no longer needed. It applies the same with ?async=1.

Everything else is kept: the verdict, the CEP, and the extracted data. What changes:

  • The validation publishes image_retained=false and stops publishing image_path.
  • GET /v1/validations/{id}/image responds 410 image_not_retained, a code of its own instead of a generic 404.

The file exists while the validation is processed, because the background job reads it. The deletion waits in only one case: a CEP in PDF with an open retry cycle, because each retry compares the PDF's seal against the official CEP again. When that cycle closes, as resolved, exhausted, or cancelled, the file is deleted. An image waits for nothing. A follow-up check of a valid does not read the file.

If you activate retries after the file was already deleted, the retry keeps querying Banxico with the stored data and skips the seal comparison (banxico_result._cep_upload).

Permanently deleting a validation

The permanent deletion is what DELETE /v1/validations/{id} does not do: it deletes the content, not just the history entry. It takes two steps, with the same prepare-and-execute pattern with a confirmation token that the destructive administration operations use:

  1. POST /v1/validations/{id}/purge/prepare says what would be deleted and what would be kept, warns that it is irreversible, and issues a single-use token, bound to the account and to that validation, valid for 120 seconds. It changes nothing.
  2. POST /v1/validations/{id}/purge/execute verifies the token and deletes.

Your own validations in a terminal status are accepted, including those you already withdrew from the history. A validation in progress responds 409 purge_validation_in_progress; one already purged, 410 validation_purged; one that is not yours, 404 not_found. An open retry cycle does not prevent it: the deletion cancels it.

What is deleted:

  • The receipt file and the CEP, as XML and as PDF.
  • request_data, ocr_result, banxico_result, and the normalization warnings. Of normalized_data, only the amount is kept.
  • The derived records with personal data: retry attempts, account probes, stored Idempotency-Key responses, inbox notifications, and the content of the notifications sent.
  • The sent body and the receiver response in the webhook deliveries of that validation. The record of each delivery is kept.
  • The bodies of the audit rows that name the validation and the free-form context of its security events, which is reduced to ids and codes.
  • client_ref, because it is free text that can carry personal data.

What is left: the tombstone

The validation does not disappear: it is left as a tombstone with the strict minimum for quota, statistics, finance, and history to keep adding up.

keptdeleted
id, validation_type, status, banxico_statusThe file, the CEP, and banxico_result
created_at, completed_at, deleted_at, purged_atrequest_data and ocr_result
processing_time_ms and error_codeclient_ref and normalization_warnings
The amount, in normalized_data.montoThe rest of normalized_data

GET /v1/validations/{id} responds with the tombstone with 200 and purged_at. The image, the CEP, the retries, and the follow-up check respond 410 validation_purged, and webhooks, retries, and sweeps ignore it.

The deletion does not refund quota or change what was charged, and the finance totals and the list statistics do not change. What does disappear from a report is the breakdown that depends on the deleted data: the validation no longer counts by beneficiary, by bank, or by counterparty, and the statement shows it without a tracking key or accounts.

What the deletion does not reach

The deletion is irreversible and covers what the platform stores about that validation, but some things are outside its reach:

  • Infrastructure backups are not altered. They keep a copy until their backup cycle retires it.
  • The global account catalog keeps no link to the validation: an account that a CEP confirmed entered it on its own, by account number, not by the validation, and the deletion does not touch it. What your account contributed to the catalog is removed when your account is deleted.
  • The server log files are rotated separately and are not redacted.
  • What already went out cannot be recovered: the webhooks your endpoint received, the Telegram messages, and what was sent to a third party to read the receipt.
  • Other validations with the same receipt are not touched. Each keeps its own copy of what was extracted and is deleted separately. purge/prepare lists their identifiers in same_image_validation_ids.
  • Audit rows from before version 1.61.0 do not mention the validation they created and cannot be linked to it.
  • Files that could not be deleted at the moment: the deletion responds file_removal: pending, the tombstone keeps their path without serving it, and the daily receipts sweep finishes them.

How to do it, step by step: Permanently delete a validation.