Skip to content

REST API

La API de SocTalk es una app FastAPI. Toda su superficie se genera desde el código como un esquema OpenAPI y se sirve bajo /api/ (el ingress enruta /api/* a la API y todo lo demás a la consola web):

  • OpenAPI JSON: https://mssp.your-mssp.example/api/openapi.json
  • Swagger UI: https://mssp.your-mssp.example/api/docs
  • ReDoc: https://mssp.your-mssp.example/api/redoc

La superficie OpenAPI es la fuente de verdad. Con estos docs se distribuye una instantánea en /openapi.json, y el catálogo de abajo se genera a partir de ese esquema — no puede desviarse del código.

Regenerar el catálogo

El catálogo de endpoints lo produce npm run gen:api, que lee docs/public/openapi.json. Actualiza primero el esquema desde el código de la API:

bash
# en el repo soctalk
python scripts/dump_openapi.py <soctalk-docs>/docs/public/openapi.json
# en soctalk-docs
npm run gen:api

Todo lo que está entre los marcadores GENERATED se sobrescribe; la prosa a su alrededor se cura a mano.

Catálogo de endpoints

La columna Auth se deriva del guard require_role / require_tenant_role de cada ruta. Una etiqueta de session cookie significa que se acepta cualquier sesión autenticada en el handler — pero los roles con alcance de tenant siguen confinados a sus propios datos por row-level security, así que un tenant_admin solo ve las filas de su tenant incluso en una ruta estilo MSSP sin control de acceso.

97 operaciones en 23 grupos, generadas a partir del esquema OpenAPI (versión de API 0.1.0). Auth se deriva de los guards require_role / require_tenant_role de la ruta.

auth

MétodoRutaResumenAuth
POST/api/auth/assume-tenantAssume Tenantsession cookie (login) / none
POST/api/auth/loginLoginsession cookie (login) / none
POST/api/auth/logoutLogoutsession cookie (login) / none
GET/api/auth/meMesession cookie (login) / none
POST/api/auth/password/changePassword Changesession cookie (login) / none

auth-admin

MétodoRutaResumenAuth
POST/api/mssp/users/{user_id}/password/resetAdmin Resetsession — roles: mssp_admin / platform_admin

chat

MétodoRutaResumenAuth
GET/api/chat/conversationsList Conversationssession cookie
POST/api/chat/conversationsCreate Conversationsession cookie
GET/api/chat/conversations/{conv_id}Get Conversationsession cookie
DELETE/api/chat/conversations/{conv_id}Delete Conversationsession cookie
POST/api/chat/conversations/{conv_id}/messagesPost Messagesession cookie
POST/api/chat/conversations/{conv_id}/messages/{msg_id}/confirmConfirm Actionsession cookie
POST/api/chat/conversations/{conv_id}/stopStop Conversationsession cookie

health

MétodoRutaResumenAuth
GET/health/liveLivenone (public)
GET/health/readyReadynone (public)

internal-adapter

MétodoRutaResumenAuth
GET/api/internal/adapter/checkpointGet Checkpointservice JWT (adapter token)
PUT/api/internal/adapter/checkpointPut Checkpointservice JWT (adapter token)
GET/api/internal/adapter/configFetch Configservice JWT (adapter token)
POST/api/internal/adapter/eventsIngest Eventsservice JWT (adapter token)
POST/api/internal/adapter/heartbeatHeartbeatservice JWT (adapter token)

internal-worker

MétodoRutaResumenAuth
POST/api/internal/worker/runs/{run_id}/completeComplete Runservice JWT (worker token)
POST/api/internal/worker/runs/{run_id}/heartbeatHeartbeat Runservice JWT (worker token)
POST/api/internal/worker/runs/claimClaim Runservice JWT (worker token)

investigations-bridge

MétodoRutaResumenAuth
GET/api/investigationsList Investigationssession cookie
GET/api/investigations/{investigation_id}Get Investigationsession cookie
POST/api/investigations/{investigation_id}/cancelPost Cancel Investigationsession — roles: analyst / mssp_admin / platform_admin
GET/api/investigations/{investigation_id}/eventsGet Eventssession cookie

ir-alerts

MétodoRutaResumenAuth
GET/api/mssp/alertsList Alertssession — roles: analyst / mssp_admin / platform_admin

ir-integrations

MétodoRutaResumenAuth
GET/api/mssp/tenants/{tenant_id}/integrationsGet Integrationssession — roles: mssp_admin / platform_admin
PATCH/api/mssp/tenants/{tenant_id}/integrationsPatch Integrationssession — roles: mssp_admin / platform_admin

ir-mssp

MétodoRutaResumenAuth
GET/api/mssp/investigationsList Cases Msspsession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/investigations/{investigation_id}Get Case Msspsession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/investigations/{investigation_id}/eventsList Case Events Msspsession — roles: analyst / mssp_admin / platform_admin
PATCH/api/mssp/investigations/{investigation_id}/factsPatch Case Factssession — roles: analyst / mssp_admin / platform_admin
POST/api/mssp/investigations/{investigation_id}/messagesPost Analyst Messagesession — roles: analyst / mssp_admin / platform_admin

ir-proposals

MétodoRutaResumenAuth
GET/api/mssp/proposalsList Pending Proposalssession — roles: analyst / mssp_admin / platform_admin
POST/api/mssp/proposals/{proposal_id}/approveApprove Proposal Routesession — roles: analyst / mssp_admin / platform_admin
POST/api/mssp/proposals/{proposal_id}/rejectReject Proposal Routesession — roles: analyst / mssp_admin / platform_admin

ir-tenant

MétodoRutaResumenAuth
GET/api/tenant/investigationsList Cases Tenanttenant session (customer_viewer / tenant_admin)
GET/api/tenant/investigations/{investigation_id}Get Case Tenanttenant session (customer_viewer / tenant_admin)

l2-agent

MétodoRutaResumenAuth
POST/api/agent/heartbeatHeartbeatL2 agent install token (bearer)
POST/api/agent/jobs:claimClaim JobL2 agent install token (bearer)
POST/api/agent/jobs/{job_id}/completeComplete JobL2 agent install token (bearer)
POST/api/agent/jobs/{job_id}/eventsPost EventL2 agent install token (bearer)
POST/api/agent/registerRegisterL2 agent install token (bearer)

legacy-stubs

MétodoRutaResumenAuth
GET/api/analytics/ai-behaviorAnalytics Ai Behaviorsession cookie
GET/api/analytics/human-reviewAnalytics Human Reviewsession cookie
GET/api/analytics/kpisAnalytics Kpissession cookie
GET/api/analytics/outcomesAnalytics Outcomessession cookie
GET/api/analytics/summaryAnalytics Summarysession cookie
GET/api/auditAudit Listsession cookie
GET/api/audit/event-typesAudit Event Typessession cookie
GET/api/audit/investigation/{investigation_id}Audit Investigationsession cookie
GET/api/audit/statsAudit Statssession cookie
GET/api/events/streamEvents Streamsession cookie
GET/api/review/{review_id}Review Detailsession cookie
POST/api/review/{review_id}/approveReview Approvesession cookie
POST/api/review/{review_id}/expireReview Expiresession cookie
POST/api/review/{review_id}/rejectReview Rejectsession cookie
POST/api/review/{review_id}/request-infoReview Request Infosession cookie
GET/api/review/pendingReview Pendingsession cookie
GET/api/settingsSettings Getsession cookie

metrics-bridge

MétodoRutaResumenAuth
GET/api/metrics/hourlyHourlysession cookie
GET/api/metrics/overviewOverviewsession cookie

mssp-analytics

MétodoRutaResumenAuth
GET/api/mssp/analytics/heatmapHeatmapsession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/analytics/rankingRankingsession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/analytics/trendsTrendssession — roles: analyst / mssp_admin / platform_admin

mssp-dashboard

MétodoRutaResumenAuth
GET/api/mssp/dashboard/open-by-tenantOpen By Tenantsession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/dashboard/pending-reviewsPending Reviewssession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/dashboard/repeated-iocsRepeated Iocssession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/dashboard/stuck-investigationsStuck Investigationssession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/dashboard/tenant-healthTenant Healthsession — roles: analyst / mssp_admin / platform_admin

mssp-tenant-branding

MétodoRutaResumenAuth
PATCH/api/mssp/tenants/{tenant_id}/brandingUpdate Tenant Brandingsession — roles: mssp_admin / platform_admin

mssp-tenant-llm

MétodoRutaResumenAuth
GET/api/mssp/tenants/{tenant_id}/llmGet Tenant Llmsession — roles: mssp_admin / platform_admin
PATCH/api/mssp/tenants/{tenant_id}/llmUpdate Tenant Llmsession — roles: mssp_admin / platform_admin
DELETE/api/mssp/tenants/{tenant_id}/llm/api-keyClear Tenant Llm Api Keysession — roles: mssp_admin / platform_admin

mssp-tenants

MétodoRutaResumenAuth
GET/api/mssp/tenantsList Tenantssession — roles: analyst / mssp_admin / platform_admin
POST/api/mssp/tenantsCreate Tenantsession — roles: mssp_admin / platform_admin
GET/api/mssp/tenants/{tenant_id}Get Tenantsession — roles: analyst / mssp_admin / platform_admin
POST/api/mssp/tenants/{tenant_id}:decommissionDecommission Tenantsession — roles: mssp_admin / platform_admin
POST/api/mssp/tenants/{tenant_id}:issue-agentIssue Agentsession — roles: mssp_admin / platform_admin
POST/api/mssp/tenants/{tenant_id}:resumeResume Tenantsession — roles: mssp_admin / platform_admin
POST/api/mssp/tenants/{tenant_id}:retryRetry Provisioningsession — roles: mssp_admin / platform_admin
POST/api/mssp/tenants/{tenant_id}:retry-installRetry Installsession — roles: mssp_admin / platform_admin
POST/api/mssp/tenants/{tenant_id}:suspendSuspend Tenantsession — roles: mssp_admin / platform_admin
GET/api/mssp/tenants/{tenant_id}/adapter-statusGet Tenant Adapter Statussession — roles: mssp_admin / platform_admin
GET/api/mssp/tenants/{tenant_id}/eventsList Eventssession — roles: analyst / mssp_admin / platform_admin
GET/api/mssp/tenants/{tenant_id}/external-siemGet Tenant External Siemsession — roles: mssp_admin / platform_admin
PATCH/api/mssp/tenants/{tenant_id}/external-siemUpdate Tenant External Siemsession — roles: mssp_admin / platform_admin
POST/api/mssp/tenants/onboardOnboard Tenantsession — roles: mssp_admin / platform_admin

public-tenant

MétodoRutaResumenAuth
GET/api/public/mssp-by-slug/{slug}Mssp By Slugnone (public)
GET/api/public/scope-by-slug/{slug}Scope By Slugnone (public)
GET/api/public/tenant-by-slug/{slug}Tenant By Slugnone (public)

tenant-branding

MétodoRutaResumenAuth
GET/api/tenant/brandingGet Own Brandingtenant session (customer_viewer / tenant_admin)

tenant-llm

MétodoRutaResumenAuth
GET/api/tenant/llmTenant Get Llmtenant session (tenant_admin)
PUT/api/tenant/llm/api-keyTenant Put Llm Keytenant session (tenant_admin)
DELETE/api/tenant/llm/api-keyTenant Clear Llm Keytenant session (tenant_admin)

Esquema de autenticación

Los navegadores usan una session cookie establecida por POST /api/auth/login. Los clientes programáticos pueden:

  1. Ejecutar el flujo de login (preferido para scripts de vida corta):
    bash
    curl -c jar -X POST https://mssp.../api/auth/login \
      -H 'Content-Type: application/json' \
      -d '{"email":"admin@example","password":"..."}'
    curl -b jar https://mssp.../api/mssp/tenants
  2. Emitir un token de API de larga vida (planificado; aún no expuesto en la UI). Hoy, los únicos llamadores sin cookie son los pods adapter y runs-worker por tenant, que se autentican en /api/internal/* con tokens con alcance de tenant que la API acuña y rota (ver Endpoints internos).

En SOCTALK_AUTH_MODE=proxy, la API confía en los headers upstream X-Forwarded-User / X-Forwarded-Email / X-Forwarded-Groups y toda la superficie de autenticación de sesión se desmonta — /api/auth/* (login, logout, me, assume-tenant, password/change) y/api/mssp/users/{id}/password/reset devuelven 404 (no 405). Tu IdP es dueño de la superficie de identidad.

CSRF

El CSRF se aplica de forma global, no por prefijo: internal_session_middleware valida el header Origin / Referer en cada solicitud que modifica estado (POST / PUT / PATCH / DELETE) que lleva la session cookie. Es validación de header, no un token de cookie de doble envío (ese patrón apareció en borradores anteriores, pero el runtime usa validación de header). Los orígenes aceptados provienen de SOCTALK_PUBLIC_ORIGIN (y SOCTALK_PUBLIC_ORIGIN_BASE para hosts de cliente con comodín de slug), que el chart deriva de ingress.hostnames. Las solicitudes que no llevan session cookie (p. ej. las llamadas con token bearer del adapter/worker, o la propia solicitud de login) están exentas. Los navegadores envían Origin automáticamente; los clientes que no son navegadores pueden:

  • Hacer coincidir Origin con uno de los hostnames aceptados, o
  • Establecer Host: <accepted-hostname> + Origin: https://<accepted-hostname> independientemente del destino TCP real (el paso de onboarding de firstboot.sh usa este truco).

Flujos comunes

Dar de alta un tenant

bash
curl -b jar -X POST https://mssp.../api/mssp/tenants/onboard \
  -H 'Content-Type: application/json' \
  -d '{
    "slug": "acme-corp",
    "display_name": "Acme Corp",
    "profile": "persistent"
  }'

profile se valida en el servidor contra ^(poc|persistent|provided)$. Ver ciclo de vida del tenant / perfiles para la semántica de cada valor. Para provided (BYO-Wazuh), el payload requiere adicionalmente un objeto external_siem (URL del indexer, URL de la API del Manager, credenciales de basic-auth) más un llm_api_key por tenant; el servidor devuelve 422 con errores a nivel de campo si falta alguno.

Devuelve 202 con el ID del nuevo tenant. Observa GET /api/mssp/tenants/{id} para ver las transiciones de estado, o consulta GET /api/mssp/tenants/{id}/events para la lista de eventos del ciclo de vida. (/api/events/stream existe pero en esta versión solo emite pings de keep-alive.)

Obtener el log de auditoría

bash
curl -b jar 'https://mssp.../api/audit?start_date=2026-01-01T00:00:00Z&end_date=2026-02-01T00:00:00Z&event_type=review.completed&page=1&page_size=50'

El router de auditoría es de nivel superior (/api/audit), no está bajo /api/mssp/. Filtros: start_date / end_date (ISO 8601), event_type, aggregate_type e investigation_id. Los resultados se paginan por offset con page / page_size.

Enviar una decisión de revisión humana

El router de revisión expone un endpoint por decisión (no hay una única ruta /decision). Elige el que corresponda:

bash
# Aprobar — el campo del payload es `feedback` (texto libre), no `rationale`
curl -b jar -X POST https://mssp.../api/review/<review-id>/approve \
  -H 'Content-Type: application/json' \
  -d '{"feedback":"Confirmed brute-force pattern."}'

# Rechazar — cierra el caso como auto_closed_fp; `feedback` es opcional
curl -b jar -X POST https://mssp.../api/review/<review-id>/reject \
  -d '{"feedback":"Looks like a known scanner; benign."}'

# Se necesita más información — el payload es `questions: list[str]` (cada uno se renderiza como una viñeta)
curl -b jar -X POST https://mssp.../api/review/<review-id>/request-info \
  -d '{"questions":["What is the source IP geo?","Any prior alerts on this user?"]}'

# Expirar — retira una revisión pendiente sin veredicto (razón opcional)
curl -b jar -X POST https://mssp.../api/review/<review-id>/expire \
  -d '{"reason":"superseded by newer investigation"}'

Las cuatro devuelven 409 si la revisión ya no está pending.

Para las propuestas de IR (la superficie de gestión de casos), los endpoints equivalentes están bajo /api/mssp/proposals/{id}/approve y /api/mssp/proposals/{id}/reject.

Transmitir eventos

bash
curl -N -b jar 'https://mssp.../api/events/stream'

Server-Sent Events. En esta versión el stream solo emite pings de keep-alive (un ping aproximadamente cada 25 s) — la difusión de eventos de dominio (actualizaciones de investigaciones, ciclo de vida de tenants, etc.) está en el roadmap. Trata el endpoint como una prueba de conectividad a nivel de cable por ahora.

Generar un cliente de Python

El esquema se genera limpiamente, así que la forma más rápida de llamar a la API desde Python es generar un cliente tipado con openapi-python-client en lugar de armar solicitudes a mano. Aquí está de principio a fin, leyendo investigaciones.

1. Generar + instalar el cliente

bash
pip install openapi-python-client
openapi-python-client generate \
  --url https://mssp.your-mssp.example/api/openapi.json --meta setup
pip install ./soc-talk-v1-client   # el nombre del paquete deriva del título del esquema

2. Consumir investigaciones

python
import httpx
from soc_talk_v1_client import Client
from soc_talk_v1_client.api.investigations_bridge import (
    list_investigations_api_investigations_get as list_investigations,
    get_investigation_api_investigations_investigation_id_get as get_investigation,
)

BASE = "https://mssp.your-mssp.example"

# 1. Inicia sesión para obtener una session cookie (las rutas de investigaciones usan una sesión).
with httpx.Client(base_url=BASE) as h:
    h.post("/api/auth/login",
           json={"email": "admin@example", "password": "..."}).raise_for_status()
    session = h.cookies["soctalk_session"]

# 2. Maneja el cliente tipado generado con esa cookie.
client = Client(base_url=BASE, cookies={"soctalk_session": session})

page = list_investigations.sync(client=client, page=1, page_size=5)  # -> InvestigationList
print(f"{page.total} investigations")
for inv in page.items:                                               # -> Investigation
    print(inv.id, inv.status, inv.max_severity, inv.title)

detail = get_investigation.sync(client=client, investigation_id=str(page.items[0].id))
print(detail.phase, detail.alert_count, detail.verdict_decision)

Las funciones de endpoint se nombran según el operationId que FastAPI deriva de la ruta (list_investigations_api_investigations_get) — asígnales un alias al importarlas, como arriba, para mayor legibilidad. sync() devuelve el modelo deserializado (InvestigationList, cuyos .items son Investigation); sync_detailed() devuelve el Response en bruto con el código de estado si lo necesitas.

Una versión ejecutable — generar, iniciar sesión, listar + leer — se distribuye como la prueba de humo de codegen tests/e2e/smoke_openapi_client.py, que el pipeline de despliegue ejecuta contra la API en vivo, de modo que un esquema que deja de generar un cliente funcional hace fallar la build.

Endpoints internos (/api/internal/*)

Usados por el adapter y el runs-worker por tenant (ver los grupos internal-adapter e internal-worker en el catálogo de arriba). No son para consumo humano — se listan para que los MSSP puedan ver qué hacen esos pods.

Cada llamada lleva un token con alcance de tenant que la API acuña en el aprovisionamiento y auto-renueva antes de que expire (los tokens de adapter viven 7 días, los de worker 30 días; el plano de control los vuelve a acuñar bien dentro de esa ventana). Los tokens están vinculados al tenant — un adapter solo puede actuar sobre las URLs de su propio tenant.

Límites de tasa

La API en sí no impone límites de tasa por ruta en esta versión. Usa la capa de ingress para el rate limiting global (middleware de Traefik, anotaciones de ingress-nginx) si lo necesitas.

Versionado

El documento OpenAPI lleva la versión de la app. Apuntamos a cambios aditivos dentro de una minor; cambios que rompen compatibilidad solo en un salto de major. Las notas de la versión señalan cada cambio que afecta a la API.

Punteros al código fuente

Todos los routers viven bajo src/soctalk/core/api/.

ConceptoArchivo
Router de auth + middleware de sesióncore/api/auth.py, core/auth/middleware.py
Ciclo de vida del tenant MSSPcore/api/tenants.py
Configuración de LLM por tenantcore/api/llm_config.py
Investigaciones / IR / propuestascore/api/investigations_bridge.py, core/api/ir.py
Auditoría / revisión / analítica / configuración / eventos (stubs)core/api/legacy_stubs.py
Chatcore/api/chat.py
Rutas de worker (internas)core/api/worker_runs.py
Rutas de adapter (internas)core/api/adapter.py
Generador de OpenAPIscripts/dump_openapi.py

Publicado bajo la Licencia Apache 2.0.