Todas las respuestas de la API comparten un mismo sobre. Lo que varía entre un endpoint y otro es el contenido de data; la estructura que lo rodea es idéntica en las 456 operaciones, incluidas las que devuelven error.

El sobre sigue la convención JSON:API con dos claves de primer nivel mutuamente excluyentes —data en las respuestas correctas, errors en las fallidas— y una clave meta presente en ambas.

Documento de respuesta correcta

{
  "data": {
    "type": "webhook_endpoint",
    "id": "wh_9f3c2a1b",
    "attributes": {
      "url": "https://receptor.example/hooks/spei",
      "status": "active"
    }
  },
  "meta": {
    "version": "1.57.0",
    "api_version": "v1",
    "request_id": "c4d5e6f7a8b9",
    "datetime": { "timezone": "UTC", "format": "ISO 8601" }
  }
}

Cada recurso se identifica con type e id, y sus campos viven bajo attributes. La forma de data depende de la operación:

forma de dataoperaciones que la devuelven
Objeto {type, id, attributes}Consulta de un recurso concreto y creación de recursos
Arreglo de objetos {type, id, attributes}Listados
nullOperaciones sin recurso asociado, como los borrados que responden 200
Sin cuerpoRespuestas 204, que no incluyen documento

Las operaciones que acompañan el recurso principal con recursos relacionados añaden la clave included al mismo nivel que data, con objetos de la misma forma.

Documento de error

{
  "errors": [
    {
      "status": "422",
      "code": "webhook_url_not_https",
      "detail": "La URL debe usar HTTPS.",
      "source": { "pointer": "/data/attributes/url" }
    }
  ],
  "meta": {
    "version": "1.57.0",
    "api_version": "v1",
    "request_id": "d5e6f7a8b9c0",
    "datetime": { "timezone": "UTC", "format": "ISO 8601" }
  }
}

errors es siempre un arreglo, incluso cuando contiene un único elemento. Un rechazo de validación sobre tres campos devuelve tres entradas, cada una con su source.pointer señalando el campo responsable.

El code es el identificador estable del error, en snake_case, y es el único campo sobre el que debe ramificar una integración. El detail es texto legible y varía con el idioma de la petición: compararlo como cadena rompe la integración en cuanto un cliente solicita otro idioma.

Los rechazos cuyo motivo tiene un valor concreto lo exponen en meta en lugar de dejarlo dentro de la frase: meta.limit cuando se alcanza un tope, meta.event cuando se recibe un valor no reconocido. El inventario completo de códigos está en la taxonomía de errores.

Bloque meta

Presente en todas las respuestas, correctas y fallidas, con estos campos base:

campocontenido
versionVersión de la API que atendió la petición
api_versionFamilia de rutas que la resolvió (v1)
request_idIdentificador único de la petición, requerido para cualquier consulta a soporte
datetime.timezoneSiempre UTC
datetime.formatSiempre ISO 8601

El par datetime es una garantía verificable en tiempo de ejecución: todo campo *_at, *_start, *_end y *_date de cualquier respuesta se emite en ISO 8601 con sufijo Z, sin necesidad de consultar la especificación en cada versión.

Una operación puede añadir claves propias a meta —la paginación de un listado, por ejemplo— sin alterar las anteriores.

Contrato de consumo

  1. El código de estado HTTP determina el tratamiento: 204 no incluye documento.
  2. La presencia de errors indica fallo; la ramificación se hace sobre code.
  3. La presencia de data indica éxito; los campos del recurso están bajo attributes.
  4. El request_id debe registrarse junto a cada respuesta: es el dato que permite localizar una petición concreta en una incidencia.