# Códigos de respuesta

> Referencia de los códigos HTTP usados en toda la API de Rapid.

Página: https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/

Referencia de los códigos HTTP usados en toda la API de Rapid.

## Códigos de éxito

| Código | Significado |
|---|---|
| 200 | Éxito con cuerpo |
| 201 | Recurso creado |
| 204 | Éxito sin cuerpo (ej.: `DELETE`) |

## Códigos de error del cliente

| Código | Significado |
|---|---|
| 400 | El cuerpo no es un JSON válido (`INVALID_JSON`) |
| 401 | Credenciales ausentes o inválidas |
| 403 | Empresa bloqueada |
| 404 | Recurso no encontrado |
| 409 | Conflicto (duplicado, recurso inmutable) |
| 413 | Cuerpo por encima del tamaño máximo (`PAYLOAD_TOO_LARGE`) |
| 422 | Error de validación |
| 429 | Demasiadas solicitudes (rate limit) |

## Códigos de error del servidor

| Código | Significado |
|---|---|
| 500 | Error interno (`INTERNAL_ERROR`), se recomienda reintentar |

---

## Formato del cuerpo de error

Toda respuesta de error tiene esta estructura:

```json
{
  "error": {
    "code": "CODIGO_SEMANTICO",
    "message": "Descripción legible del error"
  }
}
```

El `message` viene en inglés y es para quien lee el log: el texto puede cambiar. Para decidir qué hacer en tu código, usa el `code`. Los endpoints que se mantienen del sistema anterior responden como antes.

## Códigos semánticos más comunes

| Código | HTTP | Uso |
|---|---|---|
| `INVALID_JSON` | 400 | El cuerpo no es un JSON válido |
| `UNAUTHORIZED` | 401 | Credenciales ausentes o inválidas |
| `COMPANY_BLOCKED` | 403 | Empresa bloqueada |
| `VALIDATION_ERROR` | 422 | Uno o más campos inválidos |
| `NOT_FOUND` | 404 | La dirección no existe en la API (error de tipeo en la ruta, barra final de más) |
| `TRANSACTION_NOT_FOUND` | 404 | Transacción inexistente |
| `TRANSACTION_DUPLICATE` | 409 | `external_source` + `external_id` ya registrado |
| `TRANSACTION_IMMUTABLE` | 409 | Transacción ya utilizada, no se puede modificar |
| `MERCHANT_NOT_FOUND` | 404 | Merchant inexistente |
| `ALERT_NOT_FOUND` | 404 | Alerta inexistente |
| `ALERT_INVALID_STATUS` | 422 | Estado inválido, o transición no permitida (plazo, vencimiento o estado ya definitivo) |
| `PAYLOAD_TOO_LARGE` | 413 | Cuerpo por encima del límite: 1 MB por solicitud, 5 MB en el [envío por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/) |
| `RATE_LIMIT_EXCEEDED` | 429 | Límite de solicitudes superado (ver abajo) |
| `INTERNAL_ERROR` | 500 | Error inesperado en el servidor |

## Rate limit

Todas las rutas comparten un límite de **100 solicitudes por minuto por IP**, incluidas las que responden `401` por credencial inválida. La excepción es el [envío de eventos desde el navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/), que tiene su propio tope de 120 por minuto y no cuenta en los 100.

Al superarlo, la API devuelve:

```
HTTP/1.1 429 Too Many Requests
Retry-After: 15
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 15
```

```json
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded, retry in 15 seconds"
  }
}
```

**Usa el `Retry-After`.** Indica, en segundos, cuánto falta para que la ventana se reinicie, y el mensaje repite el mismo número. Esperar exactamente eso es mejor que adivinar: una espera progresiva a ciegas puede reintentar antes de tiempo (y recibir otro `429`) o esperar más de lo necesario.

Los headers `X-RateLimit-*` vienen en **todas** las respuestas, no solo en el `429`, así que puedes adelantarte: cuando `X-RateLimit-Remaining` se acerque a cero, frena el envío en vez de esperar el error. Para volumen, prefiere el [envío por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/), que manda hasta 1000 transacciones en una solicitud y gasta una unidad del límite.

## Reintentos en errores 5xx

Los errores `5xx` suelen ser transitorios. Reintenta aumentando el intervalo entre intentos. Nunca reintentes `4xx`: indican un error de tu lado y volverán a fallar.
