# Errores

> Los errores llegan en application/problem+json (RFC 9457) con el código HTTP real y un code estable para programar contra él.

Página: https://safeonuba.com/desarrolladores/errores · API de SafeOnuba v1 (`api_version: "2026-09-24"`), en vista previa: el contrato puede cambiar.

Los errores llegan con el **código HTTP real** y un cuerpo en `application/problem+json`, el formato de la [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457). La excepción es el endpoint del token, que sigue el formato de OAuth2 (ver [Errores del token](https://safeonuba.com/desarrolladores/autenticacion#errores-del-token)).

## El cuerpo

| Campo | Qué es |
| --- | --- |
| `type` | URI que identifica el tipo de problema. |
| `title` | Resumen legible. |
| `status` | El código HTTP, repetido. |
| `detail` | Explicación de este caso concreto. |
| `instance` | La ruta que ha fallado. |
| `code` | **Código estable del error, para programar contra él.** El texto de `title` y `detail` puede cambiar; `code` no. |

```json
{
  "type": "https://api.safeonuba.com/problems/insufficient-scope",
  "title": "Falta un permiso del token",
  "status": 403,
  "detail": "Esta petición necesita el scope alerts:write.",
  "instance": "/v1/alerts/0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "code": "insufficient_scope"
}
```

Programa contra `status` y `code`, nunca contra el texto.

## Códigos

| Código | Cuándo | Qué hacer |
| --- | --- | --- |
| `401` | Falta el token, ha caducado o se ha revocado. | Pide un token nuevo y reintenta una vez. |
| `403` | Al token le falta el scope que pide la ruta, o el centro no es de tu cliente. | Pide el token con ese scope; si tu cliente no lo tiene, pídelo. No reintentes. |
| `404` | No existe, o tu identidad no lo ve (otro centro, otra contrata). | No reintentes. |
| `409` | La transición no es posible: por ejemplo, reconocer o cerrar una alerta ya cerrada. En el sandbox, también demasiados escenarios abiertos. | Vuelve a leer el recurso: probablemente ya está en el estado que querías. |
| `422` | La petición no cumple el contrato: un campo que falta, un valor fuera de rango, una URL de webhook que no es `https`. | Corrige la petición. `detail` dice qué falla. |
| `429` | Has superado un límite de uso. | Espera lo que diga `Retry-After` (ver [Límites de uso](https://safeonuba.com/desarrolladores/limites)). |

> **Un 404 no siempre es «no existe»**
>
> La API ve lo mismo que una persona del panel con esos permisos. Una alerta de otro centro, o de una contrata que tu identidad no cubre, responde `404` igual que una que no existe. No filtra que exista.

## Reintentar o no

- `401`: sí, una vez, con un token nuevo.
- `429`: sí, después de `Retry-After`.
- Errores de red y `5xx`: sí, con espera creciente. Las lecturas se pueden repetir sin problema. Antes de repetir un `PUT /v1/alerts/{id}`, vuelve a leer la alerta: puede que el primero sí llegara.
- `403`, `404`, `409` y `422`: no. Repetir la misma petición dará el mismo resultado.
