| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Intro
This API validates that a bank account exists and tells you who owns it, by sending a one-cent SPEI transfer to the CLABE you provide — what the industry calls a penny check.
You only send the CLABE: the amount, the concept and everything else the transfer needs are set by kiban.
The answer does not come back in the same call. The transfer has to be dispatched, settled and reconciled, so this endpoint acknowledges the request and gives you an id; the verdict is read afterwards with Get by ID Account validate.
Important Points
Mandatory Fields
| field | type | required | length | Description |
|---|---|---|---|---|
| clabe | Numeric | Yes | 18 | CLABE of the account to validate. Exactly 18 digits, numbers only. |
This endpoint needs v2
The asynchronous flow rejects anything below v2: calling /api/v1/account/validate returns a 400 with invalid version. Note that the read endpoint is the opposite — it only answers on v1.
How to get the verdict
- Call this endpoint and store the
idit returns. That id is the only handle to the validation. - The answer comes back with
status: PENDING: the transfer was dispatched, nothing has been settled yet. - Ask for the result with Get by ID Account validate until the status is no longer
PENDING.
Space your polling: the verdict depends on SPEI settling and on the receiving bank, not on kiban. An interbank transfer usually reconciles in minutes, but it is not instant — checking every few seconds buys you nothing.
If you prefer to be notifiedSend the URL where you want the verdict in the
urlCallbackheader and we POST it to you when the transfer reaches a terminal status, so you do not have to poll. You can addxApiKeyCallbackwith a key of your own: we send it back asx-api-keyso your endpoint can authenticate the call.Either way the result stays readable by id, so a callback you missed is never a result you lost.
What the account holder sees
The account you validate receives one cent, with the concept Validacion de cuenta and VALIDACION as the sender's reference. It shows up in their statement, so tell your customer to expect it if the validation is part of an onboarding they are watching.
An invalid account is not billed
If the transfer bounces, the execution is closed as failed and the transaction is cancelled — a penny check against an account that does not accept the deposit is not charged.
Test the service (test cases)
We have included a query parameter in Sandbox to enable you to query the test cases that we created for running tests. To get a response, fill the testCaseId parameter with any of the following cases:
| Num | Id | Name | Description |
|---|---|---|---|
| 1 | 6875a4c100000000acc0117a | Cuenta valida (titular con RFC) | Valid account whose holder is identified by RFC |
| 2 | 6875a4c100000000acc0117b | Cuenta valida (titular con CURP) | Valid account whose holder is identified by CURP |
| 3 | 6875a4c100000000acc0117c | Cuenta invalida (transferencia rechazada) | The transfer was rejected, so the account is not valid |
| 4 | 6875a4c100000000acc0117d | Cuenta valida intra-Banco Donde (traspaso sin CEP) | Valid account reached by an internal transfer, which produces no CEP |
Sandbox answers right awayIn sandbox no transfer is sent: the test case you choose is returned as the final result, so you get the verdict in the first call instead of polling. It is the way to build your integration without waiting for SPEI.
In case you want to test your own test case created in link, you can send in the testCaseId parameter the identifier of the test case you want to use.
For more information visit our knowledge center to know more about test cases
Successful response
The answer is the acknowledgement: the transfer was dispatched and the validation is waiting for reconciliation.
| subfield | Description |
|---|---|
| id | Identifier of the validation. Store it: it is how you read the verdict. |
| createdAt | When the request started. |
| finishedAt | When the dispatch finished. |
| duration | Duration of the dispatch in milliseconds. |
| status | PENDING while the transfer has not been reconciled. |
| request | The body you sent. |
| response | Tracking data of the transfer. |
Inside response:
| subfield | Description |
|---|---|
| claveRastreo | Tracking key of the SPEI transfer. |
| status | Status the transfer was dispatched with. |
| numeroOrden | Order number, when the transfer has one. |
{
"id": "6875a4c100000000acc01180",
"createdAt": "2026-10-26T18:04:11.204Z",
"finishedAt": "2026-10-26T18:04:13.118Z",
"duration": 1914,
"status": "PENDING",
"request": {
"clabe": "012180012345678901"
},
"response": {
"claveRastreo": "KBN20261026180412",
"status": "PROCESSING"
}
}Listing the possible not success responses
Required fields
You will get a 400 bad request error when the CLABE is not provided or does not have 18 digits.
{
"clabe": "LENGTH_ERROR; should be exactly 18 digits"
}Invalid Format
The CLABE contains something other than digits.
{
"clabe": "FORMAT_ERROR; should be numeric"
}Invalid version
You called /api/v1/account/validate. This endpoint only works from v2 up.
{
"error": "invalid version"
}The account turns out to be invalid
This is not an error on this call: the transfer is dispatched the same way and the account is reported as invalid later, when it bounces. You see it when you read the result — see Get by ID Account validate.
Unauthorized
It means that the provided API is incorrect and that you are not authorized to access it. You will not receive a body, only a 401 HTTP code.
200

