# Convenciones del API Bancario

> Envelope de respuesta, correlación, reintentos seguros, paginación y formato de fechas del API Bancario.

- kind: concept
- status: stable
- api_version: 1.0.0
- last_verified: 2026-09-02
- url: https://www.tilopay.com/developers/api-bancario/convenciones

Todas las operaciones del API Bancario comparten el mismo formato de respuesta, las
mismas reglas de paginación y el mismo formato de fechas. Esta página describe lo que el
spec declara de forma transversal.

## Envelope de respuesta [#envelope]

Cada respuesta, exitosa o no, viaja en el mismo sobre:

```json
{
  "success": true,
  "http_status_code": 200,
  "response_code": "OK",
  "message": "The request was processed successfully.",
  "correlation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "data": {}
}
```

| Campo | Tipo | Descripción |
|---|---|---|
| `success` | boolean | `true` en las respuestas exitosas; `false` en las de error. |
| `http_status_code` | integer | Repite el status HTTP en el cuerpo. |
| `response_code` | string | Código del [catálogo de `response_code`](/developers/api-bancario/errores). |
| `message` | string | Mensaje legible de la respuesta. |
| `correlation_id` | string | Identificador de la llamada. |
| `data` | object | Carga útil de la operación. |

En las respuestas de error el sobre trae además `errors`, un objeto de detalle que puede
incluir campos arbitrarios como `code`, `message` o `detail`.

Ramificá tu lógica por `response_code`, no por el texto de `message`.

## Correlación [#correlacion]

Enviá `X-Correlation-Id` en el request para propagar tu propio identificador; el valor
vuelve como `correlation_id` en el sobre. Guardalo en tus logs: es el dato con el que
soporte rastrea una llamada puntual.

## Reintentos seguros [#reintentos]

Dos operaciones aceptan la cabecera `Idempotency-Key`:

```http
POST /api/public/v1/transactions/payments
POST /api/public/v1/accounts/statements
```

Reenviar la misma llave con el mismo cuerpo devuelve el resultado original en vez de
crear un segundo registro, así un timeout de red se puede reintentar sin duplicar. Si
reusás una llave con un cuerpo distinto, la respuesta es `409` con
`response_code: IDEMPOTENCY_CONFLICT`.

Generá una llave por intención de negocio (por ejemplo un UUID por orden), no una por
reintento. El resto de las operaciones son consultas y se pueden repetir sin efectos
adicionales.

## Paginación [#paginacion]

El API usa dos esquemas según el recurso.

**Cursor, en el listado de pagos.** `GET /api/public/v1/transactions/payments` acepta
`limit` (por defecto 20, máximo 100) y `cursor`. La respuesta trae
`pagination.next_cursor`: pasalo como `cursor` en el siguiente request. Cuando viene
vacío u omitido, no hay más páginas.

**Offset, en cuentas.** `GET /api/public/v1/accounts` y
`GET /api/public/v1/accounts/balances` aceptan `limit` (1 a 100) y `offset` (desde 0), y
devuelven `pagination` con `limit`, `offset` y `total`.

## Fechas y montos [#formatos]

Los parámetros y campos de fecha usan RFC 3339, por ejemplo
`2026-09-02T15:04:05Z`. Los filtros `date_from` y `date_to` del listado de pagos siguen
ese mismo formato.

## Salud y documentación del host [#host]

El propio host expone tres rutas de servicio:

```http
GET /api/public/v1/healthz
GET /openapi.yaml
GET /docs
```

`healthz` sirve para chequeo de disponibilidad, `openapi.yaml` devuelve el spec crudo y
`/docs` la interfaz de documentación del servicio. En este portal el mismo spec está en
[openapi.json](/developers/api-bancario/openapi.json) y
[openapi.yaml](/developers/api-bancario/openapi.yaml).
