> ## Documentation Index
> Fetch the complete documentation index at: https://internal.softcrum.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Estándar — API pública (v2)

> Canónico: https://api.softcrum.com/v1/{module}/{resource}, sin segmento /api. Módulos: core, loyalty, messaging y crm; los demás módulos de la suite se suman al exponer APIs públicas.

> Traducción. Autoritativo: [`../../standards/api.md`](/standards/api).

## Base y estructura

* Canónico: `https://api.softcrum.com/v1/{module}/{resource}` (sin segmento `/api`). Módulos:
  `identity`, `core`, `loyalty`, `messaging`, `crm` (los módulos de la suite se suman a medida que
  exponen API pública).
* SIN aliases estilo Segment en v1 (`/v1/track` no existe; el canónico es `/v1/core/track`). Una capa
  de compatibilidad Segment es una feature futura explícita solo si una integración real la exige.
* Dos clases de API dentro de la misma convención:
  * **Runtime** (camino caliente, llamado en línea por los sistemas del tenant): track/identify/batch,
    canjes, validación de cupón, qualifications, members/me. SLO p95: track \<100 ms (fast-ack 202),
    lecturas de member \<150 ms, decisiones síncronas \<300 ms.
  * **Management** (CRUD de consola e integraciones): todo lo demás. SLO p95 \<1 s. Paginación
    obligatoria (por cursor).
* Los presupuestos de SLO son ítems del Definition of Done; los tests de carga con k6 gatean la
  certificación.

## Parámetros de política

**Todo parámetro de política es configurable por tenant y viene con un default publicado**
(OQ-LOY-14). Ventanas de atribución, horizontes de vencimiento, períodos de gracia, TTL de reservas,
límites de reversa, ventanas de devolución, cantidad de reintentos — un valor que elegimos es un
punto de partida, nunca una restricción con la que el tenant tenga que vivir. De ahí dos
obligaciones: el default se documenta en la referencia pública junto al parámetro, y cambiarlo surte
efecto desde ese momento hacia adelante, nunca retroactivamente sobre registros ya creados bajo el
valor anterior.

La excepción es un parámetro que gobierna una máquina de estados o un invariante de corrección. Esos
no son política y no son configurables.

## AuthN/AuthZ

* Mecanismos: API keys de tenant (con alcance, rotables) · write keys públicas (solo track, llegan
  con el widget en F1b) · OAuth2 client credentials (integraciones) · tokens de member (OTP o magic
  link nativo, o token exchange `POST /v1/core/auth/token-exchange`).
* Modelo de autorización (DEC-D5): cada endpoint declara EXACTAMENTE UN permiso
  `{module}.{resource}.{action}` (por ejemplo `loyalty.redemptions.create`). Los permisos se agrupan
  en roles; los roles se asignan a usuarios Y a máquinas (API keys y clientes OAuth = roles de
  máquina). Los scopes OAuth son agrupaciones de permisos mostradas en la pantalla de consentimiento.
* A los terceros NUNCA se les exige entregar IPs: keys + HMAC + rate limits bastan. La allowlist de
  IP por tenant existe como endurecimiento opcional, apagada por defecto.

## Convenciones

* Idempotencia: cabecera `Idempotency-Key` OBLIGATORIA en `POST /v1/loyalty/redemptions` y en toda
  mutación que la documentación marque como idempotente; el servidor guarda el resultado 24 h y lo
  reproduce.
* Errores: RFC 9457 problem+json con `code` estable (por ejemplo `UNSUPPORTED_CODE`,
  `LIMIT_EXCEEDED`, `SUPPRESSED_RECIPIENT`).
* Rate limits: PUBLICADOS por plan en la documentación; las respuestas llevan cabeceras
  `RateLimit-*` estándar.
* Deprecación: ventana mínima de 6 meses, cabecera `Sunset`, entrada en el changelog de Mintlify.
  Solo cambios aditivos dentro de v1.
* Regla de oro: la consola, el portal y el widget propios de Softcrum consumen EXCLUSIVAMENTE esta
  API pública vía `packages/api-client`. Si nuestra UI necesita algo que la API no tiene, la API
  está incompleta.
