Security and data handling
Authentication
The API is called with an API key: the brand prefix (veriko_) followed by 64 random hexadecimal characters. The key identifies the account and determines its permissions and its quota; it does not sign the request and it does not expire on its own. See authentication.
On the server the key is not stored in the clear. Ordinary reads — GET /v1/users/me/api-key (console session only, not the API key) and the panel — return only the prefix and the last four characters. The full value is shown when the key is generated, and the console can show it again afterwards by requiring the account password, with a fifteen-minute lockout after three failed attempts.
What is stored for every validation
A validation keeps the material the verdict was issued from, and that material is the content of a SPEI receipt:
- What the request carried: date, amount, tracking key or numeric reference, banks and whichever accounts were sent.
- The uploaded receipt, when the validation runs from an image, along with the data extraction read from it. If the validation requests that it not be kept, the file is deleted when the validation ends and only the data read from it is kept.
- The CEP issued by Banxico, when one exists: its XML and its PDF, plus the parsed fields — sender and beneficiary names, each party's RFC when the receipt carries them, both accounts, each party's bank, the amount, the VAT and the payment concept.
Which leads to what is worth knowing before integrating: an account's history holds personal data of third parties — of whoever sent and whoever received each payment — not just account numbers. Processing it is the integrator's responsibility.
What is not stored, because the API never asks for it: the authorization data of a payment instrument — verification code, expiry date, PIN. None of them takes part in a SPEI validation.
Account numbers
Saved beneficiary accounts, and the ones that travel in each validation, are kept readable: they are the datum Banxico is queried with and the one a transfer is reconciled by. They are not encrypted at the column level.
In Veriko's interfaces a card number is masked down to its last four digits, while a CLABE is kept whole. The criterion, and the case of a receipt that arrives already masked at source, are in sensitive-data masking.
Uploaded images
Every image that comes in through POST /v1/validate-ocr goes through a sanitization that fails closed: if a step cannot complete, the request is rejected with 422 and the image is not persisted.
- Size: 40 bytes minimum, 12 MB maximum.
- Format: JPEG, PNG and WebP only, detected from the header bytes and not from the extension. A PDF follows its own sanitization, described below.
- MIME cross-check: the type the header bytes state and the one the file analysis reports have to agree.
- Structural parse: the image has to parse, with a cap of 12,000 px per axis and 60 megapixels in total.
- Polyglot scan: a body that doubles as a file of another format is rejected.
- Metadata removal: EXIF, XMP, ICC profiles, text chunks in PNG and VP8X chunks in WebP. That is where the geolocation, the phone model and the original date of the photo travel.
- Revalidation: the stripped image must keep its dimensions and its type.
When the image is fetched from an image_url, the download is hardened separately: HTTPS only, DNS resolution that rejects private and reserved addresses — with the validated address pinned into the connection, so a later resolution cannot change it — at most three redirects that each re-run the same filter, strict certificate verification, a size cap watched over the stream, and 5- and 15-second timeouts.
Uploaded PDFs
A receipt in PDF also comes in through POST /v1/validate-ocr. It is never converted into an image or rewritten: its structure is checked and, if it passes, it is kept and processed exactly as it arrived. Since the file is not rewritten, its metadata is kept. The sanitization also fails closed, with its own error code for each case:
- Size and signature: the same 12 MB cap, and
%PDF-at the first byte. - Structure: it has to parse, with no data after the end of the document and with caps on objects and nesting (
pdf_invalid_structure). - Encryption: an encrypted or password-protected PDF is rejected (
pdf_encrypted). - Active content: JavaScript, automatic actions, attached files, forms, and annotations that are not links (
pdf_active_content). - Hidden content: optional layers, forms, and text outside the visible area of the page (
pdf_hidden_content). - Revisions: a PDF modified after being issued, with more than one revision (
pdf_modified_after_issue). - Pages: 1 to 3, counted before the text is read (
pdf_too_many_pages). - Embedded images: JBIG2 encoding and any image over 60 megapixels are rejected (
pdf_unsupported_image). - Text layer: a character cap per page and per document (
pdf_text_layer_too_large).
The text the document carries is treated as receipt data, never as an instruction. On download, GET /v1/validations/{id}/image always delivers a PDF as an attachment and with Content-Security-Policy: sandbox.
Outgoing webhooks
Every delivery is signed with HMAC-SHA256 over the JSON body, using a secret of its own per endpoint. The server generates that secret when the endpoint is created, and it is rotated with POST /v1/webhooks/{id}/regenerate-secret. The signature ships in:
X-Webhook-Signature: sha256=<hex>Verification, retries and automatic disabling are detailed in webhook architecture.
Retention and deletion
| datum | how long it lives |
|---|---|
| Uploaded receipts | Five years from upload, unless they are requested not to be kept or the validation is deleted |
| Validations, with their CEP and extracted data | No automatic deletion; each one can be permanently deleted |
| Saved beneficiaries | No automatic deletion |
| Idempotency keys | 24 hours |
| Notifications and their deliveries | 90 days |
| Request log | 12 months |
Uploaded receipts are kept five years because article 30 of Mexico's Federal Tax Code sets that term for supporting documentation. Once it elapses the file is removed from storage and the validation stays with its verdict: downloading the receipt then answers that it is no longer available. That term is the default. The integrator can request that the receipt not be kept, or delete it earlier; in that case, the retention its own tax obligations require is the integrator's responsibility.
DELETE /v1/validations/{id} and DELETE /v1/beneficiaries/{id} mark the record, they do not delete it. The validation stays readable by the account itself — it shows in the listing with its deletion date — and the beneficiary turns inactive; neither operation removes anything from storage. Permanent deletion, described below, does remove it.
Effective deletion can happen in two ways. The first is one validation at a time, from the console or the API, in two steps: first it shows what will be deleted, then it is confirmed. The receipt, the CEP, the data read and the copy of that information in notices and records are deleted; only a minimal record is kept (verdict, dates and amount) so that recorded usage and financial reports remain accurate. It cannot be undone, it does not refund usage and it does not alter backups. The second is tied to the account: deleting it opens a thirty-day grace period, with an email when the closure is requested, two warnings before it ends (seven days and one day before) and a confirmation when the deletion completes, and with the account's webhooks paused while it lasts; once it elapses the validations and their on-disk files (uploaded receipts and CEP PDFs), the beneficiaries, the webhook endpoints with their deliveries, the notifications, the sessions, the idempotency keys and the quota consumption are all deleted. What tax obligations require keeping (payment receipts, refunds and credits) stays with the account identifier detached until the period set by Article 30 of the Federal Fiscal Code: it is deleted starting on January 1 of the seventh year after each record.
Compliance
There is no formal third-party attestation today: no SOC 2, no ISO 27001. Anyone who needs one in order to integrate should raise it before starting.
A security review, a vendor questionnaire, a data processing agreement or an erasure request for an end user are coordinated with the security team. The vulnerability disclosure policy, and the address to write to, are published per RFC 9116 at /.well-known/security.txt on the main site.