Docs

Fincore · Guides

Validate a bank account

Use Penny Validation to send 0.01 MXN to a destination instrument and receive the CEP ownership data from Banxico through webhooks.

Penny Validation verifies account ownership. Monato sends a 0.01 MXN transfer to the destination instrument and retrieves the CEP data for it from Banxico. The CEP data gives you the account holder’s name and RFC.

Use it when you need ownership data before you send production funds.

Two ways to start it

Entry point Behavior
Start Penny Validation, POST /v1/transactions/penny_validation Applies the defaults for you: sends 0.01 MXN in MXN, rejects internal Monato-to-Monato transactions, and marks the transaction as a validation flow.
Create Money Out transaction with amount "0.01" Treated as Penny Validation only when the validation flow is enabled for your client and the destination is eligible.

Before you start

Requirement Where
Bearer token Quickstart
Source instrument from your Centralizing Account Retrieve client accounts
Registered destination instrument Register instrument
CEP webhook configuration Create webhook configuration

Register the CEP webhook before you start validations, so you receive every status change.

1. Start the validation

Start Penny Validation
curl -X POST https://apicore.stg.finch.lat/v1/transactions/penny_validation \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "c2d1d1e3-3340-4170-980e-e9269bbbc551",
    "source_instrument_id": "709448c3-7cbf-454d-a87e-feb23801269a",
    "destination_instrument_id": "d3fdb481-2058-46c8-807d-4eaf866ae1ec",
    "description": "Account validation",
    "external_reference": "1234567"
  }'
Field Rule
client_id, source_instrument_id, destination_instrument_id Required UUIDs.
description Optional. Up to 40 characters. The 2026-01-07 changelog adds: letters, numbers and spaces only, with no special characters except ñ/Ñ.
external_reference Optional. Numeric, 1 to 7 digits.

If you omit description or external_reference, the backend sets a default. Both values are reflected in Retrieve a transaction.

Idempotency-Key is supported and works the same as for Money Out.

200 OK
{
  "id": "1eb4b5ac-09ac-4a64-b853-6939728621d2",
  "trackingId": "20250815FINCHPV123456",
  "transactionStatus": "INITIALIZED",
  "amount": "0.01",
  "currency": "MXN",
  "bankId": "9d84b03a-28d1-4898-a69c-38824239e2b1",
  "clientId": "c2d1d1e3-3340-4170-980e-e9269bbbc551",
  "externalReference": "1234567",
  "description": "Account validation",
  "category": "DEBIT_TRANS",
  "subCategory": "SPEI_DEBIT",
  "metadata": {
    "dataCep": {
      "status": "PENDING",
      "cepUrl": "https://www.banxico.org.mx/cep/...",
      "validationId": "f4ebe9af-50ac-42e5-97c7-3164d2693d6e"
    }
  }
}

Treat this response as pending. It only confirms the request was accepted; it is not the validation result. When the validation CEP exists, the response includes metadata.dataCep.

For field optionality and forward-compatible parsing, see Concepts.

2. Wait for the CEP webhook

  1. Monato sends the 0.01 MXN transfer to the destination instrument.
  2. The transfer settles. Only then can a CEP exist for it.
  3. Monato retrieves the CEP from Banxico. How long this takes depends on the beneficiary’s bank and varies significantly between institutions.
  4. You receive a CEP webhook each time the status changes. A single validation can produce more than one event.
  5. The validation ends as COMPLETED or FAILED.
CEP event
{
  "id_msg": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "msg_name": "CEP",
  "msg_date": "2025-08-15",
  "body": {
    "id": "11111111-2222-3333-4444-555555555555",
    "tracking_key": "20250815XXXXXX123456789",
    "beneficiary_account": "000000000000000000",
    "beneficiary_name": "Jane Doe",
    "beneficiary_rfc": "XAXX010101000",
    "status": "COMPLETED",
    "processed_at": "2025-08-15T22:42:39.327Z"
  }
}

Treat the validation as unresolved until you receive a terminal status. Drive your flow from the webhook, not from the synchronous response. You do not need to poll or re-send anything: while a validation is PENDING or DELAYED, Monato keeps working on it in the background until it reaches a terminal status.

3. Handle the result

Status What to do
INITIALIZED, PENDING Show the validation as in progress. Wait for the webhook. INITIALIZED appears on API reads only; treat it like PENDING.
DELAYED Keep waiting. It means the CEP is taking longer than usual, not that something went wrong. Do not start a new validation.
COMPLETED Read beneficiaryName and beneficiaryRfc (beneficiary_name and beneficiary_rfc in the webhook) to confirm ownership, and store cepUrl for your records.
FAILED Treat ownership as unverified. Starting a new validation is a business decision; the account may simply belong to a slow bank.

Starting a new validation does not speed up a pending one. It creates a separate 0.01 MXN transfer and a separate validation record.

The full lifecycle and allowed transitions are in Transaction statuses.

Read the current state

Retrieve a transaction returns the validation with metadata.dataCep. metadata.dataCep.status uses the same values as the webhook, plus INITIALIZED.

processedAt is set whenever the validation record is updated, including intermediate updates. Do not use it as a signal that the validation finished; use status.

Errors

HTTP When it happens
400 Request fields are missing, malformed or invalid, or the client or rail state prevents validation.
401 The bearer token is missing, expired, invalid, or not valid for the environment.
404 Source instrument, destination instrument, client, bank or related account was not found.
409 The Idempotency-Key conflicts with a previous request.
500 Unexpected server error.