Saltar al contenido
Errores
Contrato OpenAPI 3.1: openapi.yaml
Convenciones

Errores de la API

Un solo formato para todos los errores. Decide por `code`, que es estable; el `message` es para personas y puede cambiar.

json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta clave no tiene el scope passengers:read",
    "request_id": "req_9f8e7d6c5b4a39281706",
    "details": {
      "required_scope": "passengers:read"
    }
  }
}
CampoQué es
error.codeCódigo estable, de la tabla de abajo. Forma parte del contrato.
error.messageFrase en castellano para una persona. No la interpretes: puede cambiar sin aviso.
error.request_idEl mismo valor que la cabecera X-WAT-Request-Id. Guárdalo: es lo que identifica la petición en el servidor.
error.detailsOpcional. Claves habituales: param, field, allowed, required_scope, retry_after.

Los mensajes nunca llevan SQL, trazas, nombres de tabla ni secretos. Lo que no es un error previsto sale como internal y el detalle se queda en el servidor, ligado al request_id.

Códigos

HTTPcodeCuándo
400invalid_cursorEl cursor está manipulado, truncado o es de otra lista.
400validation_errorUn parámetro o campo no es válido. details.param o details.field dice cuál; details.allowed, los valores admitidos.
401expired_keyLa clave ha caducado.
401invalid_keyLa clave no tiene la forma esperada o no existe.
401revoked_keyLa clave fue revocada (rotación o baja).
401unauthorizedFalta Authorization: Bearer.
401wrong_environmentClave de test contra live o al revés.
403api_disabledLa API no está activada para la organización, o el trozo que pides (por ejemplo los webhooks) no lo está.
403forbiddenReservado. Hoy ningún endpoint de v1 lo devuelve: los 403 reales son insufficient_scope, api_disabled e integration_disabled.
403insufficient_scopeFalta un scope. details.required_scope dice cuál.
403integration_disabledLa integración está desactivada o revocada.
404not_foundNo existe o no es de tu organización (misma respuesta en los dos casos).
405method_not_allowedEl método HTTP no existe en esa ruta. Ver la nota de abajo: este 405 lo contesta el servidor antes que la API.
409conflictEl estado actual no lo permite (p. ej. un external_id ya usado por otro recurso).
409idempotency_conflictLa misma Idempotency-Key se usó antes con otro cuerpo.
409idempotency_in_progressUna petición con esa Idempotency-Key sigue en curso. Caduca a los 5 minutos: si el proceso que la tenía murió, el siguiente intento se ejecuta.
413payload_too_largeEl cuerpo supera 256 KB medidos en bytes UTF-8 (no en caracteres).
415unsupported_media_typeEl cuerpo no es application/json, o va sin Content-Type.
429rate_limitedDemasiadas peticiones. Espera Retry-After segundos.
500internalError interno. El detalle queda en el servidor con el request_id.
501not_implementedReservado para operaciones anunciadas y aún no disponibles. Hoy ningún endpoint de v1 lo devuelve.

Cómo tratarlos

Si recibesHaz
401No reintentes con la misma clave. Revisa la clave, el entorno y si ha sido rotada.
403No reintentes. Pide el scope o la activación que falta.
404El id no es tuyo o ya no existe. No hay diferencia entre los dos casos.
400 / 409 / 413 / 415Corrige la petición. Reintentar sin cambiarla dará lo mismo.
429Espera Retry-After segundos y reintenta con espera exponencial. Ver Límites.
500Reintenta con espera exponencial (un puñado de veces). Si persiste, escribe a soporte con el request_id.
El 405 es la excepción del formato

Un método que la ruta no tiene —por ejemplo DELETE /v1/bookings— lo rechaza el servidor antes de llegar a la API: responde 405 con la cabecera Allow, pero sin el sobre { "error": … } y sin X-WAT-Request-Id. Es el único caso en toda la v1 en que un error no lleva el formato de arriba, y por eso conviene decidir también por el código HTTP y no solo por error.code. Todo lo demás, incluidos los 404, va con el sobre completo y su request_id.

Ejemplo de validación con los valores admitidos:

json
{
  "error": {
    "code": "validation_error",
    "message": "status no válido",
    "request_id": "req_9f8e7d6c5b4a39281706",
    "details": {
      "param": "status",
      "allowed": [
        "requested",
        "unconfirmed",
        "confirmed",
        "en_route",
        "in_progress",
        "completed",
        "cancelled",
        "no_show",
        "rejected"
      ]
    }
  }
}
Errores · API de WAT