# Errores

> Los códigos HTTP que devuelve la API de Lane, qué significa cada uno y cuáles conviene reintentar.

Todos los errores tienen el mismo cuerpo: un objeto JSON con la llave `error` y una frase en inglés.

**Forma de un error**
```json
{
  "error": "amount must be a positive integer in minor units"
}
```

El mensaje describe el problema con precisión y está pensado para tu log, no para mostrárselo al comprador. Cuando el error viene del procesador, la respuesta trae además un `message` con el detalle.

## Códigos

| Código | Significa | ¿Reintentar? |
| --- | --- | --- |
| `400` | El cuerpo no cumple el contrato: falta un campo, sobra otro o el tipo no corresponde. | No, hasta corregirlo |
| `401` | La llave falta, no existe o venció. Ver [Llaves y entornos](https://lane.money/docs/autenticacion). | No |
| `404` | `{"error":"Route not found"}` — la ruta no existe. También cuando el recurso no es de tu organización. | No |
| `422` | El contrato está bien pero la operación es imposible: monto fuera del tope de un medio instantáneo, por ejemplo. | No |
| `500` | Algo se rompió de nuestro lado. | Sí, con espera creciente |

> **Cuidado: Un recurso ajeno responde 404, no 403.** Si pides un cobro que existe pero es de otra organización, la API contesta `404`. Es a propósito: un `403` confirmaría que ese identificador existe.

## Errores de validación más frecuentes

| Mensaje | Qué corregir |
| --- | --- |
| `amount must be a positive integer in minor units` | Manda centavos, como entero. Ver [Montos](https://lane.money/docs/montos). |
| `instrument_id or provider_instrument_id is required` | Un cobro contra tarjeta guardada necesita saber qué tarjeta. |
| `cvv is required when initiator is customer (CIT)` | Si el cliente está presente, el CVV es obligatorio. |
| `cvv must not be sent when initiator is merchant (MIT)` | En un cobro automático no hay quien lo escriba: no lo mandes. |
| `parent_transaction_data is required for series MIT` | Un cobro recurrente tiene que apuntar al primero de la serie. |
| `installments.quantity must be an integer >= 2` | Para un pago sin cuotas, omite el objeto `installments`. |
| `success_url must be a valid URL` | Tiene que ser `http` o `https` absoluta. |

## Reintentos

La API no tiene claves de idempotencia. Un `POST` reintentado crea un cobro nuevo, no repite el anterior. Por eso solo conviene reintentar cuando la petición **no llegó** —un timeout de red o un `500`— y aún así vale la pena guardar tu propio identificador en `metadata` para poder detectar el duplicado.

**Tu identificador viaja en metadata**
```json
{
  "amount": 11900000,
  "metadata": { "order_id": "4821" }
}
```

Después puedes buscarlo: `metadata` vuelve en el objeto del cobro y en el evento del webhook, tal como lo mandaste.
