# Conciliar

Cuadrar tus movimientos contra tus registros.

Concilia con [`GET /v1/movements`](/docs/operaciones/listar-movimientos/) como fuente de lo que pasó en tu cuenta, y con [`GET /v1/events`](/docs/operaciones/listar-eventos/) para saber qué cambió desde tu última lectura. Cada consulta de eventos empieza sin cursor, en el más nuevo: ver [El evento siempre queda guardado](/docs/webhooks/#el-evento-siempre-queda-guardado).

## Método

1. Consulta movimientos con un cursor durable. Ver [Movimientos y recibos](/docs/recetas/movimientos-y-recibos/).
2. Empata cada movimiento con tu registro. `payment_id` es el `pay_` del pago de origen y `external_ref` es tu referencia. `payment_id` viene en `null` en depósitos, en lo que no salió de esta API y en un cobro, que sí trae `external_ref`.
3. Revisa `read_status`: `partial` significa que el dato aún no está completo y debes releerlo.
4. Trata `returned` después de `completed` como una reversa, y cualquier otro retroceso publicado como una corrección.
5. Guarda el recibo de los movimientos terminales.

## Eventos

Pide la lista sin `cursor` y recorre con `next_cursor` hacia el pasado hasta llegar a un evento que ya procesaste. No guardes `next_cursor` entre consultas: sólo camina hacia el pasado.

**Variables de estas muestras: simulador público, sin cuenta**

Define esto en tu terminal. Con estos valores las muestras corren tal cual contra el simulador público:

```bash
export FITAL_API="https://widget.fital.xyz/explorar/v1"
export FITAL_KEY="sk_test_sandbox_publica"
```

En la cuenta de prueba o en producción cambia la base, la llave y el secreto, y sustituye los `id` de ejemplo por los tuyos. Ver [Ambientes](/docs/ambientes/).

```bash
# Empieza sin cursor, en el evento más nuevo. CURSOR sólo sirve para seguir esta vuelta hacia atrás: no lo guardes entre consultas.
CURSOR=""
curl -sS -G "$FITAL_API/events" \
  -H "Authorization: Bearer $FITAL_KEY" \
  --data-urlencode "limit=25" \
  ${CURSOR:+--data-urlencode "cursor=$CURSOR"}
```

```js
// Empieza sin cursor, en el evento más nuevo. cursor sólo sirve para seguir esta vuelta hacia atrás: no lo guardes entre consultas.
const cursor = null;
const q = new URLSearchParams({ limit: '25', ...(cursor ? { cursor } : {}) });
const r = await fetch(`${process.env.FITAL_API}/events?${q}`, {
  headers: { Authorization: `Bearer ${process.env.FITAL_KEY}` },
});
const pagina = await r.json();
console.log(r.status, pagina.data.length, pagina.has_more, pagina.next_cursor);
```

```python
import json, os, urllib.error, urllib.parse, urllib.request
# Empieza sin cursor, en el evento más nuevo. cursor sólo sirve para seguir esta vuelta hacia atrás: no lo guardes entre consultas.
cursor = None
q = {"limit": "25", **({"cursor": cursor} if cursor else {})}
pet = urllib.request.Request(os.environ["FITAL_API"] + "/events?" + urllib.parse.urlencode(q),
    headers={"Authorization": "Bearer " + os.environ["FITAL_KEY"]})
try:
    with urllib.request.urlopen(pet) as r:
        pagina = json.load(r)
        print(r.status, len(pagina["data"]), pagina["has_more"], pagina["next_cursor"])
except urllib.error.HTTPError as e:
    print(e.code, e.read().decode())
```

```php
<?php
// Empieza sin cursor, en el evento más nuevo. $cursor sólo sirve para seguir esta vuelta hacia atrás: no lo guardes entre consultas.
$cursor = null;
$q = http_build_query(['limit' => 25] + ($cursor ? ['cursor' => $cursor] : []));
$c = curl_init(getenv('FITAL_API') . '/events?' . $q);
curl_setopt_array($c, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('FITAL_KEY')],
]);
$pagina = json_decode(curl_exec($c), true);
echo count($pagina['data']), ' ', var_export($pagina['has_more'], true), ' ', $pagina['next_cursor'] ?? 'null', "\n";
```

> **Próximo.** En producción, [`GET /v1/events`](/docs/operaciones/listar-eventos/) recibe eventos desde que se activa la API. En la cuenta de prueba ya los recibe, en [`GET /sandbox/v1/events`](/docs/operaciones/listar-eventos/).

## Devoluciones tardías

Una devolución puede no llegar sola: fuera de `latam` depende del aviso del riel, en cualquier plazo, y en `latam` la vigilancia dura 120 días. Si tu cierre depende de un pago, consulta [`GET /v1/payments/{id}`](/docs/operaciones/consultar-pago/), que lee en vivo. Ver [Vigilancia de un pago completado](/docs/conceptos/#vigilancia-de-un-pago-completado).

## Errores comunes

- Cerrar el día con movimientos en `processing`.
- Usar para eventos un cursor durable, como el de movimientos. En [`GET /v1/events`](/docs/operaciones/listar-eventos/) no verías lo nuevo.
- Ignorar `returned`: un pago `completed` puede revertirse después.
- Conciliar con [`GET /v1/payments`](/docs/operaciones/listar-pagos/): es una vista y puede ir atrasada. Usa movimientos y el detalle del pago.

## Qué sigue

[Reintentos](/docs/recetas/reintentos/).
