openapi: 3.1.0 jsonSchemaDialect: https://json-schema.org/draft/2020-12/schema info: title: Orquestador NMP version: 1.0.0 description: Contrato objetivo del MVP. Solicitudes, eventos, ejecuciones, conciliación, tareas e historial implementados hasta T15; simulación administrativa implementada en T16. JWT y autorización por recurso obligatorios. Campos opcionales ausentes se omiten; no se usa null salvo en datos configurables. servers: - url: /api/v1 security: - bearerAuth: [] tags: - name: Requests - name: Administration paths: /requests: post: operationId: createRequest summary: Crear solicitud y fijar flujo activo description: 'Owner y businessScope se derivan del JWT autorizado. Idempotencia durable por actor/scope: repetición idéntica retorna la respuesta original de creación (201, Location y ETag originales), incluso si cambió el flujo activo o avanzó la solicitud; otro hash retorna 409. GET devuelve el estado actual. data se valida con initialDataSchema y dataSchema del flujo. Máximo de datos 256 KiB. No se aceptan estado, propietario o resultados de proveedor como autoridad del cliente. Tipo inexistente retorna 404; tipo deshabilitado, sin flujo publicado activo o cambiado durante la asignación retorna 409 INVALID_FLOW_STATE. Un 409 por cambio concurrente permite reintentar la misma clave, que no queda reservada.' tags: - Requests parameters: - $ref: '#/components/parameters/IdempotencyKey' responses: '201': description: Crear solicitud y fijar flujo activo content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/RequestView example: id: 00000000-0000-0000-0000-000000000123 typeKey: CREDITO flow: id: 00000000-0000-0000-0000-000000000456 flowKey: SCORING_DEMO version: 1 currentState: BURO_PENDIENTE data: clienteId: CLI-DEMO consentimientoId: CONS-DEMO revision: 7 createdAt: '2026-10-26T17:20:00Z' updatedAt: '2026-10-26T17:20:00Z' headers: ETag: description: Revisión fuerte, entre comillas, por ejemplo "7". schema: type: string pattern: ^"[0-9]+"$ Location: description: URI del recurso creado o ejecución aceptada. schema: type: string format: uri-reference '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '413': $ref: '#/components/responses/PayloadTooLarge' '422': $ref: '#/components/responses/UnprocessableEntity' '503': $ref: '#/components/responses/Unavailable' requestBody: required: true content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/CreateRequest example: typeKey: CREDITO data: clienteId: CLI-DEMO consentimientoId: CONS-DEMO /requests/{id}: get: operationId: getRequest summary: Consultar solicitud autorizada description: Consultar solicitud autorizada tags: - Requests parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Consultar solicitud autorizada content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/RequestView example: id: 00000000-0000-0000-0000-000000000123 typeKey: CREDITO flow: id: 00000000-0000-0000-0000-000000000456 flowKey: SCORING_DEMO version: 1 currentState: BURO_PENDIENTE data: clienteId: CLI-DEMO consentimientoId: CONS-DEMO revision: 7 createdAt: '2026-10-26T17:20:00Z' updatedAt: '2026-10-26T17:20:00Z' headers: ETag: description: Revisión fuerte, entre comillas, por ejemplo "7". schema: type: string pattern: ^"[0-9]+"$ '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '503': $ref: '#/components/responses/Unavailable' /requests/{id}/available-events: get: operationId: availableEvents summary: Consultar tareas y eventos permitidos description: 'Orientativo: el POST revalida roles y guardias. Con ejecución activa, events vacío y blockedByExecutionId presente. Sólo se exponen causas de bloqueo no sensibles. Filtra por propietario, ámbito y roles; usa la versión fijada incluso retirada. Guardias dependientes de event.data se difieren al POST. Cache-Control no-store, sin ETag; revision sirve para If-Match del evento.' tags: - Requests parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Consultar tareas y eventos permitidos content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/AvailableEvents example: requestId: 00000000-0000-0000-0000-000000000123 revision: 8 events: [] blocked: [] blockedByExecutionId: 00000000-0000-0000-0000-000000000789 '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '503': $ref: '#/components/responses/Unavailable' /requests/{id}/events: post: operationId: acceptEvent summary: Aceptar un evento durable description: 'Una transición por evento; sin HTTP externo en la transacción de aceptación. El hash incluye evento, datos y revisión esperada canónicos. Primero comprobar acceso e idempotencia y después revisión; un replay idéntico devuelve el mismo executionId/status actual incluso si cambió revision. Nueva clave mientras existe ejecución activa: REQUEST_BUSY (se comprueba revisión antes de busy). Validar data con schema del evento. Reintentar conservando If-Match original. 202 no equivale a éxito de negocio; GET de ejecución permite seguimiento; el worker se habilita explícitamente con WORKER_ENABLED.' tags: - Requests parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' - $ref: '#/components/parameters/IfMatch' responses: '202': description: Aceptar un evento durable content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/AcceptedEvent example: executionId: 00000000-0000-0000-0000-000000000789 requestId: 00000000-0000-0000-0000-000000000123 status: PENDING headers: Location: description: URI del recurso creado o ejecución aceptada. schema: type: string format: uri-reference '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '412': $ref: '#/components/responses/PreconditionFailed' '413': $ref: '#/components/responses/PayloadTooLarge' '422': $ref: '#/components/responses/UnprocessableEntity' '428': $ref: '#/components/responses/PreconditionRequired' '503': $ref: '#/components/responses/Unavailable' requestBody: required: true content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/EventCommand example: event: REGISTRAR_LICENCIA data: documentId: 00000000-0000-0000-0000-000000000789 /executions/{id}: get: operationId: getExecution summary: Consultar ejecución autorizada description: Verificar acceso a la solicitud asociada. SUCCEEDED es éxito técnico y puede contener resultado de negocio desfavorable; los fallos asíncronos se consultan aquí. El cliente hace polling con backoff y después actualiza solicitud/ETag. tags: - Requests parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Consultar ejecución autorizada content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/ExecutionView example: id: 00000000-0000-0000-0000-000000000789 requestId: 00000000-0000-0000-0000-000000000123 event: ASIGNAR_CLIENTE status: SUCCEEDED result: outcome: CLIENTE_NO_ENCONTRADO fromState: CREADA toState: CREADA reasonCodes: - NO_MATCH createdAt: '2026-10-26T17:20:00Z' updatedAt: '2026-10-26T17:20:00Z' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '503': $ref: '#/components/responses/Unavailable' /requests/{id}/history: get: operationId: getHistory summary: Consultar auditoría paginada y filtrada description: Orden ascendente (createdAt,id), cursor opaco asociado a solicitud y filtros. Máximo 100. Omitir nextCursor al terminar. from inclusivo y to exclusivo, UTC Z. Propietario y ámbito obligatorios, sin bypass administrativo. Detail se proyecta por lista permitida (IDs de reglas/acciones, razones y códigos); no entrega evidencia ni resultados completos. Cache-Control no-store. Cursor representa posición, no autorización; no promete snapshot entre páginas concurrentes. tags: - Requests parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/Limit' - name: kind in: query schema: type: string pattern: ^[A-Za-z][A-Za-z0-9_.-]{0,99}$ - name: executionId in: query schema: type: string format: uuid - name: from in: query schema: type: string format: date-time pattern: Z$ - name: to in: query schema: type: string format: date-time pattern: Z$ responses: '200': description: Consultar auditoría paginada y filtrada content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/HistoryPage example: items: - id: 00000000-0000-0000-0000-000000000789 requestId: 00000000-0000-0000-0000-000000000123 kind: EVENT_ACCEPTED actorSubject: analista-demo flowId: 00000000-0000-0000-0000-000000000456 fromState: CREADA detail: transitionId: asignar-cliente createdAt: '2026-10-26T17:20:00Z' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '503': $ref: '#/components/responses/Unavailable' /admin/flows: post: operationId: createDraft summary: Crear borrador description: Clave/versión únicas. Cuerpo máximo 1 MiB. El borrador puede tener errores semánticos que se reportarán al validar; siempre debe cumplir el schema estructural. tags: - Administration parameters: [] responses: '201': description: Crear borrador content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/FlowView example: id: 00000000-0000-0000-0000-000000000456 status: DRAFT revision: 0 definition: schemaVersion: 1 flowKey: SCORING_DEMO version: 1 initialState: BURO_PENDIENTE dataSchema: type: object properties: clienteId: type: string consentimientoId: type: string validaciones: type: object required: - clienteId - consentimientoId additionalProperties: false states: - key: BURO_PENDIENTE terminal: false - key: PASO_N terminal: true - key: PASO_M terminal: true - key: REVISION_MANUAL terminal: true events: - key: VALIDAR_BURO inputSchema: type: object additionalProperties: false transitions: - id: consultar-buro from: BURO_PENDIENTE event: VALIDAR_BURO allowedRoles: - ANALISTA actions: - id: buro type: INVOKE_INTEGRATION integrationKey: BURO_CONSULTA contractVersion: '1' inputs: clienteId: path: /request/data/clienteId consentimientoId: path: /request/data/consentimientoId resultKey: buro decision: RUTA_SCORING destinations: N: PASO_N M: PASO_M MANUAL: REVISION_MANUAL updates: - target: /validaciones/buro value: path: /results/buro decisions: - id: RUTA_SCORING hitPolicy: UNIQUE rules: - id: alto when: op: GT left: path: /results/buro/score right: literal: 70 output: N - id: medio when: op: AND args: - op: GT left: path: /results/buro/score right: literal: 60 - op: LTE left: path: /results/buro/score right: literal: 70 output: M defaultOutput: MANUAL tasks: [] createdAt: '2026-10-26T17:20:00Z' createdBy: editor-demo headers: ETag: description: Revisión fuerte, entre comillas, por ejemplo "7". schema: type: string pattern: ^"[0-9]+"$ Location: description: URI del recurso creado o ejecución aceptada. schema: type: string format: uri-reference '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '413': $ref: '#/components/responses/PayloadTooLarge' '422': $ref: '#/components/responses/UnprocessableEntity' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - FLOW_EDITOR requestBody: required: true content: application/json: schema: $ref: ../schemas/flow-definition.schema.json example: schemaVersion: 1 flowKey: SCORING_DEMO version: 1 initialState: BURO_PENDIENTE dataSchema: type: object properties: clienteId: type: string consentimientoId: type: string validaciones: type: object required: - clienteId - consentimientoId additionalProperties: false states: - key: BURO_PENDIENTE terminal: false - key: PASO_N terminal: true - key: PASO_M terminal: true - key: REVISION_MANUAL terminal: true events: - key: VALIDAR_BURO inputSchema: type: object additionalProperties: false transitions: - id: consultar-buro from: BURO_PENDIENTE event: VALIDAR_BURO allowedRoles: - ANALISTA actions: - id: buro type: INVOKE_INTEGRATION integrationKey: BURO_CONSULTA contractVersion: '1' inputs: clienteId: path: /request/data/clienteId consentimientoId: path: /request/data/consentimientoId resultKey: buro decision: RUTA_SCORING destinations: N: PASO_N M: PASO_M MANUAL: REVISION_MANUAL updates: - target: /validaciones/buro value: path: /results/buro decisions: - id: RUTA_SCORING hitPolicy: UNIQUE rules: - id: alto when: op: GT left: path: /results/buro/score right: literal: 70 output: N - id: medio when: op: AND args: - op: GT left: path: /results/buro/score right: literal: 60 - op: LTE left: path: /results/buro/score right: literal: 70 output: M defaultOutput: MANUAL tasks: [] /admin/flows/{id}: put: operationId: updateDraft summary: Reemplazar definición de borrador description: Sólo DRAFT. flowKey/version no cambian; crear otra versión para cambiar identidad. Publicados/retirados son inmutables. Máximo 1 MiB. tags: - Administration parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IfMatch' responses: '200': description: Reemplazar definición de borrador content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/FlowView example: id: 00000000-0000-0000-0000-000000000456 status: DRAFT revision: 0 definition: schemaVersion: 1 flowKey: SCORING_DEMO version: 1 initialState: BURO_PENDIENTE dataSchema: type: object properties: clienteId: type: string consentimientoId: type: string validaciones: type: object required: - clienteId - consentimientoId additionalProperties: false states: - key: BURO_PENDIENTE terminal: false - key: PASO_N terminal: true - key: PASO_M terminal: true - key: REVISION_MANUAL terminal: true events: - key: VALIDAR_BURO inputSchema: type: object additionalProperties: false transitions: - id: consultar-buro from: BURO_PENDIENTE event: VALIDAR_BURO allowedRoles: - ANALISTA actions: - id: buro type: INVOKE_INTEGRATION integrationKey: BURO_CONSULTA contractVersion: '1' inputs: clienteId: path: /request/data/clienteId consentimientoId: path: /request/data/consentimientoId resultKey: buro decision: RUTA_SCORING destinations: N: PASO_N M: PASO_M MANUAL: REVISION_MANUAL updates: - target: /validaciones/buro value: path: /results/buro decisions: - id: RUTA_SCORING hitPolicy: UNIQUE rules: - id: alto when: op: GT left: path: /results/buro/score right: literal: 70 output: N - id: medio when: op: AND args: - op: GT left: path: /results/buro/score right: literal: 60 - op: LTE left: path: /results/buro/score right: literal: 70 output: M defaultOutput: MANUAL tasks: [] createdAt: '2026-10-26T17:20:00Z' createdBy: editor-demo headers: ETag: description: Revisión fuerte, entre comillas, por ejemplo "7". schema: type: string pattern: ^"[0-9]+"$ '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '412': $ref: '#/components/responses/PreconditionFailed' '413': $ref: '#/components/responses/PayloadTooLarge' '422': $ref: '#/components/responses/UnprocessableEntity' '428': $ref: '#/components/responses/PreconditionRequired' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - FLOW_EDITOR requestBody: required: true content: application/json: schema: $ref: ../schemas/flow-definition.schema.json example: schemaVersion: 1 flowKey: SCORING_DEMO version: 1 initialState: BURO_PENDIENTE dataSchema: type: object properties: clienteId: type: string consentimientoId: type: string validaciones: type: object required: - clienteId - consentimientoId additionalProperties: false states: - key: BURO_PENDIENTE terminal: false - key: PASO_N terminal: true - key: PASO_M terminal: true - key: REVISION_MANUAL terminal: true events: - key: VALIDAR_BURO inputSchema: type: object additionalProperties: false transitions: - id: consultar-buro from: BURO_PENDIENTE event: VALIDAR_BURO allowedRoles: - ANALISTA actions: - id: buro type: INVOKE_INTEGRATION integrationKey: BURO_CONSULTA contractVersion: '1' inputs: clienteId: path: /request/data/clienteId consentimientoId: path: /request/data/consentimientoId resultKey: buro decision: RUTA_SCORING destinations: N: PASO_N M: PASO_M MANUAL: REVISION_MANUAL updates: - target: /validaciones/buro value: path: /results/buro decisions: - id: RUTA_SCORING hitPolicy: UNIQUE rules: - id: alto when: op: GT left: path: /results/buro/score right: literal: 70 output: N - id: medio when: op: AND args: - op: GT left: path: /results/buro/score right: literal: 60 - op: LTE left: path: /results/buro/score right: literal: 70 output: M defaultOutput: MANUAL tasks: [] /admin/flows/{id}/validate: post: operationId: validateFlow summary: Validar configuración sin publicarla description: Errores semánticos devuelven 200 con valid=false y JSON Pointers. Sin invocar proveedores. Incluye grafo, catálogos, límites de AST y mappings. tags: - Administration parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Validar configuración sin publicarla content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/ValidationReport example: valid: false errors: - pointer: /transitions/0/to code: UNKNOWN_STATE message: Estado destino inexistente. '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - FLOW_EDITOR - FLOW_PUBLISHER /admin/flows/{id}/simulate: post: operationId: simulateFlow summary: Simular evaluación pura description: Sin HTTP ni efectos persistentes. requestData/actor/results son fixtures administrativos, nunca comandos de negocio. Evaluar guardia/decisión/updates con resultados suministrados; rechazo de tipos y ambigüedad como problem 422. Body máximo 1 MiB; requestData/event.data/cada resultado máximo 256 KiB. results usa exactamente los resultKey externos de la transición. NO_OP sólo permitido en simulación, toma output de la definición sin fixture externo. Cache-Control no-store. Actor de fixture no sustituye JWT FLOW_EDITOR ni ámbito administrativo. tags: - Administration parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Simular evaluación pura content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/SimulationResult example: transitionId: consultar-buro outcome: N toState: PASO_N data: clienteId: CLI-DEMO consentimientoId: CONS-DEMO validaciones: buro: score: 71 consultationId: SIM-001 matchedRuleIds: - alto '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '413': $ref: '#/components/responses/PayloadTooLarge' '422': $ref: '#/components/responses/UnprocessableEntity' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - FLOW_EDITOR requestBody: required: true content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/SimulationInput example: state: BURO_PENDIENTE requestData: clienteId: CLI-DEMO consentimientoId: CONS-DEMO event: event: VALIDAR_BURO data: {} actor: subject: analista-demo roles: - ANALISTA businessScope: DEMO results: buro: score: 71 consultationId: SIM-001 /admin/flows/{id}/publish: post: operationId: publishFlow summary: Publicar versión inmutable description: Valida semántica, resuelve versiones de contratos/perfiles, calcula SHA-256 del JSON canónico y registra auditoría. Rechaza NO_OP. Debe ser DRAFT. tags: - Administration parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IfMatch' responses: '200': description: Publicar versión inmutable content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/FlowView example: id: 00000000-0000-0000-0000-000000000456 status: PUBLISHED revision: 1 definition: schemaVersion: 1 flowKey: SCORING_DEMO version: 1 initialState: BURO_PENDIENTE dataSchema: type: object properties: clienteId: type: string consentimientoId: type: string validaciones: type: object required: - clienteId - consentimientoId additionalProperties: false states: - key: BURO_PENDIENTE terminal: false - key: PASO_N terminal: true - key: PASO_M terminal: true - key: REVISION_MANUAL terminal: true events: - key: VALIDAR_BURO inputSchema: type: object additionalProperties: false transitions: - id: consultar-buro from: BURO_PENDIENTE event: VALIDAR_BURO allowedRoles: - ANALISTA actions: - id: buro type: INVOKE_INTEGRATION integrationKey: BURO_CONSULTA contractVersion: '1' inputs: clienteId: path: /request/data/clienteId consentimientoId: path: /request/data/consentimientoId resultKey: buro decision: RUTA_SCORING destinations: N: PASO_N M: PASO_M MANUAL: REVISION_MANUAL updates: - target: /validaciones/buro value: path: /results/buro decisions: - id: RUTA_SCORING hitPolicy: UNIQUE rules: - id: alto when: op: GT left: path: /results/buro/score right: literal: 70 output: N - id: medio when: op: AND args: - op: GT left: path: /results/buro/score right: literal: 60 - op: LTE left: path: /results/buro/score right: literal: 70 output: M defaultOutput: MANUAL tasks: [] createdAt: '2026-10-26T17:20:00Z' createdBy: editor-demo checksum: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa publishedAt: '2026-10-26T17:20:00Z' headers: ETag: description: Revisión fuerte, entre comillas, por ejemplo "7". schema: type: string pattern: ^"[0-9]+"$ '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '412': $ref: '#/components/responses/PreconditionFailed' '422': $ref: '#/components/responses/UnprocessableEntity' '428': $ref: '#/components/responses/PreconditionRequired' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - FLOW_PUBLISHER /admin/request-types/{key}/active-flow: put: operationId: activateFlow summary: Activar flujo de un tipo existente description: If-Match corresponde al tipo, no al flujo. Sólo versión PUBLISHED. Tipos se provisionan mediante migración/configuración administrativa; tipo inexistente retorna 404. Activación y retiro se serializan. Nuevas solicitudes fijan esta versión; existentes no migran. tags: - Administration parameters: - $ref: '#/components/parameters/TypeKey' - $ref: '#/components/parameters/IfMatch' responses: '200': description: Activar flujo de un tipo existente content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/RequestTypeView example: typeKey: CREDITO activeFlowId: 00000000-0000-0000-0000-000000000456 enabled: true revision: 1 headers: ETag: description: Revisión fuerte, entre comillas, por ejemplo "7". schema: type: string pattern: ^"[0-9]+"$ '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '412': $ref: '#/components/responses/PreconditionFailed' '413': $ref: '#/components/responses/PayloadTooLarge' '422': $ref: '#/components/responses/UnprocessableEntity' '428': $ref: '#/components/responses/PreconditionRequired' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - FLOW_ADMIN requestBody: required: true content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/ActivateFlow example: flowId: 00000000-0000-0000-0000-000000000456 /admin/flows/{id}/retire: post: operationId: retireFlow summary: Retirar versión para nuevas asignaciones description: Sólo PUBLISHED a RETIRED. Bloquear asignaciones concurrentes; conservar ejecución de instancias existentes. No borrar la definición. tags: - Administration parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IfMatch' responses: '200': description: Retirar versión para nuevas asignaciones content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/FlowView example: id: 00000000-0000-0000-0000-000000000456 status: RETIRED revision: 1 definition: schemaVersion: 1 flowKey: SCORING_DEMO version: 1 initialState: BURO_PENDIENTE dataSchema: type: object properties: clienteId: type: string consentimientoId: type: string validaciones: type: object required: - clienteId - consentimientoId additionalProperties: false states: - key: BURO_PENDIENTE terminal: false - key: PASO_N terminal: true - key: PASO_M terminal: true - key: REVISION_MANUAL terminal: true events: - key: VALIDAR_BURO inputSchema: type: object additionalProperties: false transitions: - id: consultar-buro from: BURO_PENDIENTE event: VALIDAR_BURO allowedRoles: - ANALISTA actions: - id: buro type: INVOKE_INTEGRATION integrationKey: BURO_CONSULTA contractVersion: '1' inputs: clienteId: path: /request/data/clienteId consentimientoId: path: /request/data/consentimientoId resultKey: buro decision: RUTA_SCORING destinations: N: PASO_N M: PASO_M MANUAL: REVISION_MANUAL updates: - target: /validaciones/buro value: path: /results/buro decisions: - id: RUTA_SCORING hitPolicy: UNIQUE rules: - id: alto when: op: GT left: path: /results/buro/score right: literal: 70 output: N - id: medio when: op: AND args: - op: GT left: path: /results/buro/score right: literal: 60 - op: LTE left: path: /results/buro/score right: literal: 70 output: M defaultOutput: MANUAL tasks: [] createdAt: '2026-10-26T17:20:00Z' createdBy: editor-demo checksum: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa publishedAt: '2026-10-26T17:20:00Z' headers: ETag: description: Revisión fuerte, entre comillas, por ejemplo "7". schema: type: string pattern: ^"[0-9]+"$ '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '412': $ref: '#/components/responses/PreconditionFailed' '428': $ref: '#/components/responses/PreconditionRequired' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - FLOW_ADMIN /admin/executions/{id}/resolve: post: operationId: resolveExecution summary: Conciliar una ejecución incierta description: Sólo RECONCILIATION_REQUIRED, con acceso por scope. Evidencia referenciada y verificada por operador autorizado; no admite elegir estado destino. RESUME registra resultados verificados y reencola PENDING; CLOSE_WITHOUT_TRANSITION registra ausencia/compensación verificada por el operador y cierra FAILED conservando negocio. No consulta automáticamente al proveedor. Idempotencia durable por ejecución/clave y comando canónico; replay exige el mismo sujeto operador y devuelve la misma resolución. Auditoría obligatoria. tags: - Administration parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: Conciliar una ejecución incierta content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/ReconciliationView example: resolutionId: 00000000-0000-0000-0000-000000000456 executionId: 00000000-0000-0000-0000-000000000789 status: PENDING resolvedAt: '2026-10-26T17:20:00Z' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '412': $ref: '#/components/responses/PreconditionFailed' '413': $ref: '#/components/responses/PayloadTooLarge' '422': $ref: '#/components/responses/UnprocessableEntity' '503': $ref: '#/components/responses/Unavailable' x-required-roles: - EXECUTION_OPERATOR requestBody: required: true content: application/json: schema: $ref: ../schemas/api.schema.json#/$defs/ReconciliationCommand example: mode: RESUME evidence: reference: CASE-DEMO-001 reason: Resultado verificado con proveedor. verifiedActions: - actionId: buro result: score: 71 consultationId: SIM-001 providerReference: SIM-001 components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT parameters: Id: name: id in: path required: true schema: type: string format: uuid TypeKey: name: key in: path required: true schema: type: string pattern: ^[A-Za-z][A-Za-z0-9_.-]{0,99}$ IfMatch: name: If-Match in: header required: true description: Una única revisión fuerte entre comillas; no se admite * ni ETag débil. schema: type: string pattern: ^"[0-9]+"$ IdempotencyKey: name: Idempotency-Key in: header required: true schema: type: string minLength: 1 maxLength: 200 pattern: ^[!-~]+$ Cursor: name: cursor in: query required: false schema: type: string minLength: 1 maxLength: 2000 Limit: name: limit in: query required: false schema: type: integer minimum: 1 maximum: 100 default: 50 responses: BadRequest: description: Sintaxis o cabeceras inválidas. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: Sintaxis o cabeceras inválidas. status: 400 code: BAD_REQUEST correlationId: demo-correlation-001 Unauthorized: description: JWT ausente, inválido o vencido. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: JWT ausente, inválido o vencido. status: 401 code: UNAUTHORIZED correlationId: demo-correlation-001 headers: WWW-Authenticate: schema: type: string description: Challenge Bearer. Forbidden: description: Permiso insuficiente. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: Permiso insuficiente. status: 403 code: FORBIDDEN correlationId: demo-correlation-001 NotFound: description: Recurso inexistente o no visible; se oculta existencia ajena. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: Recurso inexistente o no visible; se oculta existencia ajena. status: 404 code: NOT_FOUND correlationId: demo-correlation-001 Conflict: description: REQUEST_BUSY, INVALID_EVENT, IDEMPOTENCY_CONFLICT o conflicto de ciclo de vida. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: REQUEST_BUSY, INVALID_EVENT, IDEMPOTENCY_CONFLICT o conflicto de ciclo de vida. status: 409 code: REQUEST_BUSY correlationId: demo-correlation-001 PreconditionFailed: description: La revisión If-Match no coincide. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: La revisión If-Match no coincide. status: 412 code: REVISION_MISMATCH correlationId: demo-correlation-001 PayloadTooLarge: description: Se excedió el límite de tamaño. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: Se excedió el límite de tamaño. status: 413 code: PAYLOAD_TOO_LARGE correlationId: demo-correlation-001 UnprocessableEntity: description: Schema/guardia incumplida o configuración semánticamente inválida. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: Schema/guardia incumplida o configuración semánticamente inválida. status: 422 code: VALIDATION_ERROR correlationId: demo-correlation-001 PreconditionRequired: description: Falta If-Match. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: Falta If-Match. status: 428 code: PRECONDITION_REQUIRED correlationId: demo-correlation-001 Unavailable: description: Infraestructura no disponible para aceptar la operación. content: application/problem+json: schema: $ref: ../schemas/api.schema.json#/$defs/Problem example: type: about:blank title: Infraestructura no disponible para aceptar la operación. status: 503 code: SERVICE_UNAVAILABLE correlationId: demo-correlation-001