eva.integration.projects.v1
1 método
Asegurar proyecto y escenario
Un POST PAT idempotente. Crea el proyecto si el código no existe y enlaza el escenario de catálogo si falta. Ingest sigue siendo lookup-only: si no hay match, 404.
Ruta
POST /api/v1/integrations/projects
Scope ingest (mismo cupo CIDR/rate-limit que ingest). JWT de sesión → 401 TOKEN_TYPE_NOT_ALLOWED. Directo a Flask, sin BFF.
Cuerpo
| Campo | Obligatorio | Uso |
|---|---|---|
project_name | sí | Identidad; match case-insensitive como ingest |
project_code | sí | Lookup get_by_code (trim + mayúsculas) |
scenario_key | sí | Clave de catálogo (WEB, API, EXTERNAL…), no el título |
client_code | sí | Centro de costo de 6 dígitos. En alta se persiste; si el proyecto ya existe debe coincidir |
client_emails | no | Mismo campo que la UI Correos del cliente (no el gestor/PM). Solo al crear el proyecto. No se pisan si ya existía |
start_date / end_date | no | Solo al enlazar un escenario nuevo. No se pisan si ya está linkeado |
mode / sold_workdays / notes | no | Defaults de la UI (CN, 0.00) |
No se envían responsables internos ni catálogo nuevo: el scenario_key debe existir. Un alta nueva marca origin = integration. Si el proyecto ya existía, no se pisan origin ni client_emails.
Respuesta
201 si se creó el proyecto o se enlazó el escenario. 200 si ambos ya existían y coincidían.
{
"contract": "eva.integration.projects.v1",
"project_id": "…",
"scenario_id": "…",
"project_code": "BNK-1",
"project_name": "Banco XYZ 2026",
"client_code": "006002",
"scenario_key": "WEB",
"client_emails": ["cliente@banco.example"],
"created": { "project": true, "scenario": true },
"origin": { "project": "integration", "scenario": "integration" }
}
Fixture: ensure_project.example.json.
Idempotencia y conflictos
| Estado | Resultado |
|---|---|
| Código ausente | Crea proyecto + enlaza escenario → 201 |
Código, nombre y client_code coinciden; escenario ya linkeado | 200, no toca nada |
| Código existe, escenario no linkeado | Enlaza escenario → 201 |
| Código existe, nombre distinto | 409 PROJECT_CODE_CONFLICT (nunca renombra) |
Código existe, client_code distinto | 409 PROJECT_CLIENT_CONFLICT |
scenario_key ausente en catálogo | 422 VALIDATION_ERROR |
scenario_key ambiguo en catálogo o duplicado en el proyecto | 409 SCENARIO_AMBIGUOUS |
| Consultor, client manager o sin membresía | 404 NOT_FOUND |
Service manager: client_code fuera de sus accesos | 404 NOT_FOUND |
Tras un 200/201, llame ingest con los mismos project_name, project_code y scenario_key.