La conciliación de 3 vías de Winal (ledger propio ↔ liquidación del conector ↔ estado de cuenta bancario) suma una 4ª vía: importa el CSV del estado de cuenta que descargas del portal de tu banco y Winal lo casa contra los abonos que esperabas recibir por tus liquidaciones — sin capturar nada a mano.
Importa un estado de cuenta
El archivo viaja como multipart/form-data (o como cuerpo crudo, con
filename por query). No exige Idempotency-Key: no mueve dinero,
solo importa y casa datos ya asentados — su idempotencia real es el hash del archivo.
Metadatos requeridos: bank, period_start/period_end
(yyyy-MM-dd); tolerance_days es opcional (default: la tolerancia
estándar de la conciliación de liquidaciones).
curl -s https://api.winal.com.mx/v1/reconciliation/bank-statements \
-H "Authorization: Bearer $SK" \
-F "bank=bbva" \
-F "period_start=2026-07-01" \
-F "period_end=2026-07-08" \
-F "preset=bbva" \
-F "file=@estado_bbva.csv;type=text/csv"
{
"id": "271a21c8-be04-4d6e-909a-8f1394fd333a",
"object": "bank_statement",
"bank": "bbva",
"period_start": "2026-07-01",
"period_end": "2026-07-08",
"filename": "estado_bbva.csv",
"lines_total": 2,
"matched": 0,
"partial": 0,
"unmatched": 1,
"exceptions": 2,
"already_imported": false
}
Mapeo de columnas: preset o explícito
Cada banco exporta el estado de cuenta con su propio layout de columnas — por eso el mapeo
siempre es explícito. preset pre-llena tres conocidos, pero
ninguno está verificado contra un export real todavía (el propio código lo advierte):
confírmalo contra tu archivo antes de confiar en él en producción, o usa el mapeo explícito
directamente.
| Preset | fecha | descripción | referencia | cargo | abono | encabezado |
|---|---|---|---|---|---|---|
bbva | col. 0 | col. 1 | col. 2 | col. 3 | col. 4 | sí |
banorte | col. 0 | col. 1 | — | col. 2 | col. 3 | sí |
santander | col. 0 | col. 1 | col. 2 | col. 3 | col. 4 | sí |
Mapeo explícito (0-based), si tu export no coincide con ningún preset o quieres verificarlo tú
mismo: date_column, description_column, credit_column
(abono), debit_column (cargo) son requeridos; reference_column es
opcional; has_header (default true, manda "false" si tu
CSV no trae encabezado).
"$1,234.56"). Solo CSV en fase 0 — si tu banco solo exporta .xlsx,
conviértelo primero (Excel/LibreOffice "Guardar como").
Consulta el estado de cuenta importado
curl -s https://api.winal.com.mx/v1/reconciliation/bank-statements -H "Authorization: Bearer $SK"
{
"object": "list",
"data": [
{
"id": "271a21c8-be04-4d6e-909a-8f1394fd333a",
"object": "bank_statement",
"bank": "bbva",
"period_start": "2026-07-01",
"period_end": "2026-07-08",
"filename": "estado_bbva.csv",
"lines_total": 2,
"imported_at": "2026-07-08T02:22:42.583562+00:00"
}
]
}
Líneas del estado de cuenta, filtrables por estado de casado
curl -s "https://api.winal.com.mx/v1/reconciliation/bank-statements/271a21c8-.../lines?match_status=unmatched" \
-H "Authorization: Bearer $SK"
{
"object": "list",
"data": [
{
"id": 3,
"object": "bank_statement_line",
"value_date": "2026-07-01",
"description": "SPEI RECIBIDO ANTECH",
"reference": "REF001",
"credit_minor": 50000,
"currency": "MXN",
"match_status": "unmatched"
},
{
"id": 4,
"object": "bank_statement_line",
"value_date": "2026-07-02",
"description": "COMISION MENSUAL",
"reference": "REF002",
"debit_minor": 15000,
"currency": "MXN",
"match_status": "unmatched"
}
]
}
match_status es matched, partial o
unmatched; el filtro ?match_status= es opcional (sin filtro, trae
todas las líneas). Cada línea trae o credit_minor o
debit_minor, nunca ambos — un movimiento bancario es uno solo.
Los 3 tipos de excepción de la conciliación bancaria
Se suman a los tipos ya existentes de la conciliación de liquidaciones
(missing_local, missing_in_report, amount_mismatch,
fee_mismatch, unparsed_line) — visibles todas juntas en el visor de
excepciones del portal.
| Tipo | Qué significa |
|---|---|
bank_deposit_unexpected | Hay un abono en el estado de cuenta que no corresponde a ninguna liquidación esperada — dinero que entró sin que Winal supiera de dónde viene. |
bank_deposit_missing | Winal esperaba un abono por una liquidación ya reportada por el conector, pero no aparece en el estado de cuenta bancario dentro de la tolerancia de días configurada. |
bank_amount_mismatch | Hay un abono cerca de la fecha esperada, pero el monto no cuadra con la liquidación reportada. |
{
"object": "recon_exception",
"id": 4,
"connector_key": "bank",
"provider_ref": "REF001",
"type": "bank_deposit_unexpected",
"report_amount_minor": 50000,
"detail": "Abono del estado de cuenta sin ninguna liquidación esperada que lo explique.",
"created_at": "2026-07-08T02:22:42.623309+00:00"
}
Las excepciones de conciliación bancaria comparten el mismo visor del portal que las de
liquidación de conectores — se distinguen por connector_key: "bank" y por su
type. No hay un endpoint público de /v1/* para listarlas: revísalas
en portal → Conciliación → Excepciones.
Endpoints
| Método | Ruta | Notas |
|---|---|---|
| POST | /v1/reconciliation/bank-statements | Multipart o cuerpo crudo; tope de archivo 5 MiB. |
| GET | /v1/reconciliation/bank-statements | Lista los estados de cuenta importados. |
| GET | /v1/reconciliation/bank-statements/{id}/lines?match_status= | Filtro opcional por estado de casado. |
Errores de bank_statement
| HTTP | code | Causa |
|---|---|---|
400 | bank_statement.bank_required | Falta bank. |
400 | bank_statement.invalid_period | Faltan o son inválidos period_start/period_end, o period_start > period_end. |
400 | bank_statement.invalid_tolerance | tolerance_days negativo. |
400 | bank_statement.unknown_preset | preset no es bbva/banorte/santander. |
400 | bank_statement.mapping_required | No se dio preset ni un mapeo explícito completo. |
400 | bank_statement.invalid_mapping | El mapeo explícito de columnas es inconsistente. |
400 | bank_statement.invalid_match_status | ?match_status= no es matched/unmatched/partial. |
400 | bank_statement.too_large | El archivo excede 5 MiB. |
400 | bank_statement.parse_error | Una fila no parsea: fecha/monto inválidos, o trae abono Y cargo (o ninguno) a la vez. |
Ver el envelope completo de error en Errores.