API de lectura

Acceso de solo lectura, con una clave de organización, a los registros de gobernanza de IA de tu cuenta.

Disponible en los planes M2 y M3 y durante el periodo de prueba. La clave la crea y la revoca el Owner de la organización desde Ajustes → API.

Autenticación

Cada petición lleva la clave de la organización en la cabecera Authorization, como Bearer.

Authorization: Bearer alx_live_…

La clave empieza por alx_live_. Sus primeros 17 caracteres son el prefijo que ves en Ajustes → API. La clave completa se muestra una sola vez, al crearla: Alethexis guarda solo su huella SHA-256 y no puede volver a enseñártela.

Una clave revocada deja de funcionar en la petición siguiente.

Una clave ausente, desconocida, incorrecta o revocada recibe la misma respuesta 401: la API no distingue entre esos casos.

Cuota

Cada clave admite 120 peticiones por minuto y 10.000 al día.

Toda respuesta autenticada lleva X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset. Al agotarse la cuota, la respuesta es 429 con Retry-After, en segundos.

Además, cada dirección IP admite 60 peticiones cada 10 segundos. Por encima, la petición se bloquea durante 10 segundos.

Paginación

Los listados devuelven un objeto con data y next_cursor.

limit va de 1 a 200; si no se indica, 50.

Para la página siguiente, repite la petición con cursor igual al next_cursor recibido. En la última página, next_cursor es null.

El cursor es opaco: no lo construyas ni lo modifiques.

Errores

Todos los errores tienen la misma forma: un objeto error con code y message. El message está en inglés técnico; el code es estable.

EstadoCódigoSignificado
400invalid_cursorEl cursor no es válido para ese recurso.
400invalid_parameterUn parámetro no existe, está repetido o tiene un valor no admitido.
401invalid_api_keyClave ausente, desconocida, incorrecta o revocada.
403module_requiredLa organización no tiene activo M2 ni M3.
404not_foundEl recurso no existe.
429rate_limitedCuota de la clave agotada.
500internalError interno.

Recursos

Todos admiten limit, cursor y since (fecha ISO 8601 con zona horaria).

GET /api/v1/systems

Inventario de sistemas de IA de la organización.

Filtros: status

Campos: id, name, provider_name, status, is_agentic, created_at, updated_at

GET /api/v1/classifications

Clasificaciones de riesgo de cada sistema, con su historial.

Filtros: system_id, current

Campos: id, system_id, level, is_current, classified_at

GET /api/v1/controls

Controles asignados y su estado, por sistema o para toda la organización.

Filtros: system_id, status

Campos: control_id, code, title, module, kind, system_id, status, updated_at

GET /api/v1/evidence

Índice de evidencias: categoría, tamaño y fecha. No incluye el fichero.

Filtros: system_id

Campos: id, section_id, category, size_bytes, uploaded_at

GET /api/v1/sections

Estado de cada sección de la plataforma.

Filtros: status

Campos: section_id, module, status, updated_at

GET /api/v1/approvals

Actos de envío, revisión, aprobación, rechazo, sustitución y declaración, con su huella.

Filtros: subject_type

Campos: id, subject_type, subject_id, subject_version, action, decided_at, content_hash, statement_version

GET /api/v1/audit-log

Registro de auditoría de la organización, con la huella encadenada de cada fila.

Filtros: action

Campos: id, action, family, table_name, record_id, occurred_at, source, row_hash

GET /api/v1/requests

Solicitudes de uso de IA enviadas. Los borradores no se incluyen.

Filtros: status

Campos: id, status, tool_name, provider_name, urgency, involves_personal_data, submitted_at, decided_at, system_id

Qué no devuelve la API

La API no devuelve datos de personas ni textos escritos a mano. Por recurso, queda fuera:

  • systems: quién creó o editó el sistema, la persona indicada en la verificación de prácticas prohibidas, la finalidad y las notas.
  • classifications: quién clasificó y la justificación escrita.
  • controls: el responsable y el aprobador asignados, las notas y los enlaces a ficheros de evidencia.
  • evidence: el fichero, su ruta de almacenamiento, el título, la descripción y quién lo subió.
  • sections: el motivo de revisión y sus detalles.
  • approvals: quién registró el acto, sus roles y el comentario.
  • audit-log: quién actuó, la dirección IP, el navegador y los valores anteriores y posteriores al cambio.
  • requests: quién la pidió, la revisó o la decidió, la finalidad, los usuarios previstos, las notas sobre datos personales, el comentario de la decisión y los comentarios.

Webhooks

Un webhook avisa a tu sistema en cuanto pasa algo, sin que tengas que consultar la API. Los registra el Owner en Ajustes → Webhooks: una URL https, los eventos que quieres y un secreto que se muestra una sola vez.

Cada entrega es un POST con este cuerpo:

{
  "id": "0f3a…",                 // Alethexis-Event-Id
  "type": "section.closed",
  "created_at": "2026-09-18T09:12:03.412Z",
  "api_version": "v1",
  "data": { "account_id": "…", "section_id": "GOB-2", "status": "complete", "closed_at": "…" }
}

Cabeceras: Alethexis-Signature, Alethexis-Event-Id, Alethexis-Event-Type y User-Agent: Alethexis-Webhooks/1.

Firma

El valor v1 es el HMAC-SHA256 de la marca de tiempo, un punto y el cuerpo exacto que recibes, con el secreto del endpoint. Compara en tiempo constante y rechaza lo que llegue con más de cinco minutos de diferencia.

Verificación:

// Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody, header, secret, toleranceSeconds = 300) {
  const [t, v1] = header.split(',').map((part) => part.split('=')[1]);
  if (Math.abs(Date.now() / 1000 - Number(t)) > toleranceSeconds) return false;

  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  const received = Buffer.from(v1, 'hex');
  return expected.length === received.length && timingSafeEqual(expected, received);
}
# Python
import hashlib, hmac, time

def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > tolerance:
        return False

    expected = hmac.new(
        secret.encode(), f'{parts["t"]}.'.encode() + raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

Reintentos

Una respuesta 2xx es una entrega buena; cualquier otra cosa, o un tiempo de espera de 10 segundos, es un fallo. Se reintenta a la hora, a las dos, a las cuatro, a las ocho y a las dieciséis; tras el quinto intento la entrega queda agotada y puedes relanzarla a mano desde Ajustes → Webhooks. Las entregas agotadas aparecen en el informe diario interno de Alethexis.

Idempotencia

Alethexis-Event-Id identifica el evento, no el intento: un reintento repite el mismo identificador. Guarda los que ya has procesado y descarta los repetidos. Un mismo evento llega una vez a cada endpoint suscrito.

Catálogo v1

v1 tiene ocho eventos, y su lista es cerrada: un evento nuevo llega con una versión nueva del catálogo.

EventoCuándo se emiteCampos de data
section.closedAl cerrarse una sección.section_id, status, closed_at
section.reopenedAl reabrirse una sección o quedar en revisión.section_id, status, reason_key, reopened_at
system.createdAl dar de alta un sistema de IA.system_id, system_name, created_at
system.reclassifiedAl registrarse una clasificación nueva de un sistema.system_id, system_name, classification_from, classification_to, version, classified_at
risk.high_registeredAl registrarse un riesgo inherente alto (15 o más) o al cruzar un riesgo ese umbral.risk_id, system_id, system_name, risk_category, inherent_score, risk_level, registered_at
approval.registeredAl registrarse una aprobación.approval_id, subject_type, subject_id, subject_version, content_hash, decided_at
evidence.uploadedAl subirse una evidencia o registrarse un PDF como evidencia.evidence_id, section_id, system_id, category, size_bytes, uploaded_at
request.decidedAl decidirse una solicitud de uso de IA.request_id, status, tool_name, system_id, decided_at

Qué no viaja en un webhook

Las cargas llevan identificadores, estados, fechas y el nombre del sistema o de la herramienta. Nunca llevan quién hizo la acción, sus roles, comentarios, motivos escritos a mano ni direcciones de correo. Si tu sistema necesita el detalle, léelo después con la API.

Requisitos del receptor

La URL tiene que ser https y resolver a una dirección pública: no se entregan webhooks a direcciones privadas ni internas. Responde en menos de 10 segundos; si necesitas más tiempo, acepta la entrega y procesa después.

Versiones

v1 es un contrato: sus respuestas no cambian de forma incompatible. Un cambio incompatible se publica como una versión nueva, v2.

Especificación OpenAPI

La especificación OpenAPI 3.1 se genera desde los mismos esquemas que validan cada respuesta: /api/v1/openapi.json

Ejemplo

curl -H "Authorization: Bearer $ALETHEXIS_API_KEY" \
  "https://www.alethexis.com/api/v1/systems?limit=50"