# Gerado por scripts/generate-openapi-user-docs.ts a partir de public/openapi.json.
# Não edite à mão: rode `npm run docs:generate`.
openapi: 3.1.0
info:
  title: API do Kadu
  version: 1.0.0
  description: |-
    API multi-tenant para la orquestación de agentes.

    ## Autenticación

    Toda ruta exige `Authorization: Bearer <token>`, donde el token es un access token RS256 emitido por el Authorization Server de Kobana (Cuenta Kobana) para el recurso `kadu`. Kadu solo verifica el token, con las claves públicas que publica el AS; no emite tokens. La organización es el claim `org`.

    ## Alcances

    Los alcances se exigen en toda ruta, excepto `GET /v1/me`. Cada solicitud exige un único nivel de acceso, y un nivel nunca sustituye a otro:

    | Nivel | Concede |
    | --- | --- |
    | `read` | lectura (`GET`) |
    | `write` | creación y modificación (`POST`, `PATCH`, `PUT`) — y lectura |
    | `delete` | eliminación (`DELETE`) |
    | `import` | importación masiva (ningún endpoint hoy) |
    | `export` | exportación masiva (ningún endpoint hoy) |
    | `all` | todos los niveles anteriores |

    Un token con alcances `kadu/{recurso}` (ej.: `kadu/tasks`) queda restringido a esos recursos, y el nivel vale solo dentro de ellos; `kadu/all` alcanza todos los recursos. El recurso de una ruta es el primer segmento después de `/v1` (`/executions/{id}/logs` → `executions`). Recursos: `activities`, `environments`, `executions`, `files`, `memberships`, `memories`, `organizations`, `repository`, `roles`, `schedules`, `secrets`, `system_events`, `tasks`, `todos`, `usage`, `users`, `webhook_deliveries`, `webhooks`, `workspaces`.

    ## Permisos del usuario

    Además de los alcances, un token emitido para una persona (con `email`) queda limitado a su rol en la organización (`Role.permissions`): cada ruta exige `agent.<recurso>.<acción>` (`list`, `read`, `create`, `update`, `delete`, y las acciones `executions.run`, `webhook_deliveries.replay` y `repository.sync`), con los comodines `*`, `agent.*` y `agent.<recurso>.*`. Un rol que no lo concede responde `403 USER_PERMISSION_DENIED` (`details.required`); una persona sin vínculo con la organización, `403 NOT_A_MEMBER`. Un token de integración, sin persona, vale solo por los alcances. `GET /v1/me` no verifica el rol.

    ## Permisos de la organización

    Las rutas de lanzamiento, logs, webhooks, entregas, entornos, secrets, programaciones, endpoint de la Task, repositorio y uso respetan también las habilitaciones que Kobana da a la organización para las pantallas de la consola. Una operación no habilitada responde `403 FEATURE_NOT_ENABLED`, con `details.permission`.

    Un token sin ningún alcance que Kadu reconozca no alcanza nada más allá de `/me`. Un alcance insuficiente responde `403 INSUFFICIENT_SCOPE`, con `details.required` (los niveles que bastarían).

    ## Contrato

    - Wire en `snake_case`; los mapas libres (`custom_metadata`, `payload`, `parameters`…) son opacos.
    - Los valores monetarios y de costo son `number` (USD en `*_usd`, reales en `*_brl`).
    - Éxito: `{ data }` o `{ data, meta }`; error: `{ error: { code, message, details? } }` con `code` en UPPER_SNAKE.
    - Listados por cursor: `cursor` + `limit` (máx. 100), ordenación por `sort_by` + `sort_order`; `meta: { next_cursor, limit }`.
    - `X-Idempotency-Key` en todo `POST`/`PUT`/`PATCH` (24h por organización).
    - Cuerpo de `POST`/`PUT`/`PATCH` de hasta 1 MiB; por encima de eso, `413 PAYLOAD_TOO_LARGE`.
servers:
  - url: https://api.kadu.ia.br
    description: Producción
  - url: https://api.staging.kadu.ia.br
    description: Staging
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: "Access token RS256 (`typ: at+jwt`) emitido por el Authorization Server de Kobana (`iss` = `https://account.kobana.com.br`), con `aud` que contiene `https://api.kadu.ia.br` (staging: `https://api.staging.kadu.ia.br`) y `exp` obligatorio. La organización es el claim `org` (`organizations.public_id`); `sub` es la persona. El encabezado debe tener `typ: at+jwt` (RFC 9068): otro JWT del mismo emisor, como un ID token, se rechaza. Los alcances se exigen en toda ruta — ver la descripción de la API."
  schemas:
    PaginationMeta:
      type: object
      properties:
        next_cursor:
          type:
            - string
            - "null"
        limit:
          type: number
      required:
        - next_cursor
        - limit
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: "UPPER_SNAKE estable: VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, INSUFFICIENT_SCOPE, NOT_FOUND, CONFLICT, IDEMPOTENCY_KEY_REUSED, IDEMPOTENCY_REQUEST_IN_PROGRESS, RATE_LIMITED, INTERNAL_ERROR, además de los códigos específicos de cada ruta."
              example: VALIDATION_ERROR
            message:
              type: string
            details: {}
          required:
            - code
            - message
      required:
        - error
    Organization:
      type: object
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type:
            - string
            - "null"
        public_id:
          type:
            - string
            - "null"
          format: uuid
        label:
          type: string
        monthly_cost_limit:
          type:
            - number
            - "null"
          description: Tope mensual de costo en USD, definido por Kobana. null = sin límite.
        monthly_cost_accumulated_usd:
          type: number
        timezone:
          type: string
        custom_metadata:
          type: object
          additionalProperties: {}
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - external_id
        - public_id
        - label
        - monthly_cost_limit
        - monthly_cost_accumulated_usd
        - timezone
        - custom_metadata
        - created_at
        - updated_at
    Workspace:
      type: object
      properties:
        id:
          type: string
          format: uuid
        label:
          type: string
        organization_id:
          type: string
          format: uuid
        created_at:
          type: string
      required:
        - id
        - label
        - organization_id
        - created_at
    Activity:
      type: object
      properties:
        id:
          type: string
          format: uuid
        label:
          type: string
        organization_id:
          type: string
          format: uuid
        workspace_id:
          type: string
          format: uuid
        created_at:
          type: string
      required:
        - id
        - label
        - organization_id
        - workspace_id
        - created_at
    Task:
      type: object
      properties:
        id:
          type: string
          format: uuid
        label:
          type: string
        skill_slug:
          type: string
        organization_id:
          type: string
          format: uuid
        workspace_id:
          type: string
          format: uuid
        activity_id:
          type: string
          format: uuid
        parameters_schema: {}
        parameters_sensitive:
          type: boolean
        conversational:
          type: boolean
          description: "Acepta continuar la conversación: `POST /executions/{id}/continue`."
      required:
        - id
        - label
        - skill_slug
        - organization_id
        - workspace_id
        - activity_id
        - parameters_sensitive
        - conversational
    Execution:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        workspace_id:
          type: string
          format: uuid
        activity_id:
          type: string
          format: uuid
        task_id:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - pending
            - queued
            - running
            - success
            - failed
            - cancelled
        source:
          type: string
        reference_date:
          type:
            - string
            - "null"
        started_at:
          type: string
        finished_at:
          type:
            - string
            - "null"
        cost_usd:
          type:
            - number
            - "null"
        parent_execution_id:
          type:
            - string
            - "null"
          format: uuid
          description: Ronda anterior de la conversación (Task conversacional); null en la primera.
        root_execution_id:
          type:
            - string
            - "null"
          format: uuid
          description: Primera ronda de la conversación; null en ella misma.
      required:
        - id
        - organization_id
        - workspace_id
        - activity_id
        - task_id
        - status
        - source
        - reference_date
        - started_at
        - finished_at
        - cost_usd
        - parent_execution_id
        - root_execution_id
    Memory:
      type: object
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type:
            - string
            - "null"
        organization_id:
          type: string
          format: uuid
        workspace_id:
          type:
            - string
            - "null"
          format: uuid
        activity_id:
          type:
            - string
            - "null"
          format: uuid
        entity_type:
          type:
            - string
            - "null"
        entity_value:
          type:
            - string
            - "null"
        key:
          type:
            - string
            - "null"
        content:
          type: string
        summary:
          type:
            - string
            - "null"
        status:
          type:
            - string
            - "null"
        custom_metadata:
          type: object
          additionalProperties: {}
        system_metadata:
          type: object
          additionalProperties: {}
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type:
            - string
            - "null"
      required:
        - id
        - external_id
        - organization_id
        - workspace_id
        - activity_id
        - entity_type
        - entity_value
        - key
        - content
        - summary
        - status
        - custom_metadata
        - system_metadata
        - created_at
        - updated_at
        - deleted_at
    Environment:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        label:
          type: string
        color:
          type: string
          example: "#16a34a"
        branch:
          type: string
          description: Branch del Playbook usada en el lanzamiento.
        repo_managed:
          type: boolean
          description: "Declarado en el `kadu.yaml` del repositorio de la organización: el sync recrea el entorno y reaplica el color y el branch declarados. No se puede borrar por la API."
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type:
            - string
            - "null"
      required:
        - id
        - organization_id
        - label
        - color
        - branch
        - repo_managed
        - created_at
        - updated_at
        - deleted_at
    Secret:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        environment_id:
          type: string
          format: uuid
        workspace_id:
          type:
            - string
            - "null"
          format: uuid
          description: null = aplica a todos los workspaces de la organización.
        key:
          type: string
        notes:
          type:
            - string
            - "null"
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type:
            - string
            - "null"
      required:
        - id
        - organization_id
        - environment_id
        - workspace_id
        - key
        - notes
        - created_at
        - updated_at
        - deleted_at
      description: "El valor es write-only: ninguna ruta lo devuelve."
    Schedule:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        task_id:
          type: string
          format: uuid
        environment_id:
          type: string
          format: uuid
        cron:
          type: string
          example: 0 9 * * 1-5
        timezone:
          type: string
          example: America/Sao_Paulo
        paused:
          type: boolean
        paused_at:
          type:
            - string
            - "null"
        repo_managed:
          type: boolean
          description: "Declarado en el `schedules` del frontmatter de la skill: el sync reaplica el cron, la zona horaria y la pausa declarados. No se puede borrar por la API."
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type:
            - string
            - "null"
      required:
        - id
        - organization_id
        - task_id
        - environment_id
        - cron
        - timezone
        - paused
        - paused_at
        - repo_managed
        - created_at
        - updated_at
        - deleted_at
    TaskEndpoint:
      type: object
      properties:
        task_id:
          type: string
          format: uuid
        endpoint:
          type:
            - object
            - "null"
          properties:
            enabled:
              type: boolean
            auth:
              type: string
              enum:
                - basic
                - bearer
                - header
                - params
            auth_basic_user:
              type:
                - string
                - "null"
            auth_header_key:
              type:
                - string
                - "null"
            auth_param_key:
              type:
                - string
                - "null"
            auth_basic_password_set:
              type: boolean
            auth_bearer_token_set:
              type: boolean
            auth_header_value_set:
              type: boolean
            auth_param_value_set:
              type: boolean
          required:
            - enabled
            - auth
            - auth_basic_user
            - auth_header_key
            - auth_param_key
            - auth_basic_password_set
            - auth_bearer_token_set
            - auth_header_value_set
            - auth_param_value_set
          description: null = la Task nunca tuvo un endpoint configurado.
      required:
        - task_id
        - endpoint
    File:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        task_id:
          type:
            - string
            - "null"
          format: uuid
        execution_id:
          type:
            - string
            - "null"
          format: uuid
        kind:
          type: string
          enum:
            - input
            - output
        status:
          type: string
          enum:
            - pending
            - uploaded
        filename:
          type: string
        content_type:
          type: string
        size_bytes:
          type: number
        custom_metadata:
          type: object
          additionalProperties: {}
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type:
            - string
            - "null"
      required:
        - id
        - organization_id
        - task_id
        - execution_id
        - kind
        - status
        - filename
        - content_type
        - size_bytes
        - custom_metadata
        - created_at
        - updated_at
        - deleted_at
    SlackInstallation:
      type: object
      properties:
        id:
          type: string
          format: uuid
        team_id:
          type:
            - string
            - "null"
        team_name:
          type:
            - string
            - "null"
        enterprise_id:
          type:
            - string
            - "null"
        is_enterprise_install:
          type: boolean
        settings:
          type: object
          properties:
            allowed_channel_types:
              type: array
              items:
                type: string
                enum:
                  - im
                  - private_channel
                  - public_channel
                  - mpim
                  - shared_channel
            files_mode:
              type: string
              enum:
                - link
                - upload
            max_upload_bytes:
              type: integer
            log_detail:
              type: string
              enum:
                - milestones
                - verbose
          required:
            - allowed_channel_types
            - files_mode
            - max_upload_bytes
            - log_detail
        connected_users:
          type: integer
        created_at:
          type: string
      required:
        - id
        - team_id
        - team_name
        - enterprise_id
        - is_enterprise_install
        - settings
        - connected_users
        - created_at
    Todo:
      type: object
      properties:
        id:
          type: number
        execution_id:
          type: string
          format: uuid
        title:
          type: string
        description:
          type:
            - string
            - "null"
        status:
          type: string
          enum:
            - todo
            - resolved
        payload: {}
        resolved_at:
          type:
            - string
            - "null"
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - execution_id
        - title
        - description
        - status
        - resolved_at
        - created_at
        - updated_at
    Webhook:
      type: object
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type:
            - string
            - "null"
        label:
          type: string
        organization_id:
          type: string
          format: uuid
        workspace_id:
          type:
            - string
            - "null"
          format: uuid
        status:
          type: string
          enum:
            - active
            - inactive
        auth:
          type: string
          enum:
            - basic
            - bearer
            - header
        auth_basic_user:
          type:
            - string
            - "null"
        auth_header_key:
          type:
            - string
            - "null"
        auth_configured:
          type: boolean
        url:
          type: string
        subscribed_events:
          type: array
          items:
            type: string
        previous_signing_secret_expires_at:
          type:
            - string
            - "null"
        consecutive_failures:
          type: number
        emails:
          type: array
          items:
            type: object
            properties:
              address:
                type: string
            required:
              - address
        repo_managed:
          type: boolean
          description: "Declarado en el `kadu.yaml`: el sync reaplica URL, eventos, estado, correos y metadata; las credenciales y el secreto de firma siguen definiéndose por la API. No se puede borrar por la API."
        custom_metadata:
          type: object
          additionalProperties: {}
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type:
            - string
            - "null"
      required:
        - id
        - external_id
        - label
        - organization_id
        - workspace_id
        - status
        - auth
        - auth_basic_user
        - auth_header_key
        - auth_configured
        - url
        - subscribed_events
        - previous_signing_secret_expires_at
        - consecutive_failures
        - emails
        - repo_managed
        - custom_metadata
        - created_at
        - updated_at
        - deleted_at
      description: Los secretos y las credenciales nunca se devuelven.
    WebhookDelivery:
      type: object
      properties:
        id:
          type: string
          format: uuid
        webhook_id:
          type: string
          format: uuid
        system_event_id:
          type: string
          format: uuid
        attempt:
          type: number
        status:
          type: string
          enum:
            - pending
            - success
            - failed
        request_headers:
          type: object
          additionalProperties:
            type: string
          description: Los encabezados de autenticación aparecen como `[redacted]`.
        request_body: {}
        response_status:
          type:
            - number
            - "null"
        response_headers:
          type:
            - object
            - "null"
          additionalProperties:
            type: string
        response_body:
          type:
            - string
            - "null"
        error:
          type:
            - string
            - "null"
        duration_ms:
          type:
            - number
            - "null"
        delivered_at:
          type:
            - string
            - "null"
        next_retry_at:
          type:
            - string
            - "null"
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - webhook_id
        - system_event_id
        - attempt
        - status
        - request_headers
        - response_status
        - response_headers
        - response_body
        - error
        - duration_ms
        - delivered_at
        - next_retry_at
        - created_at
        - updated_at
    OperationApproval:
      type: object
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - pending
            - approved
            - executed
            - declined
            - failed
            - expired
          description: "`pending` (esperando la decisión, dentro del plazo), `approved` (confirmada, en proceso), `executed`, `declined` (cancelada), `failed` (confirmada, pero la ejecución falló), `expired` (el enlace venció sin decisión — incluye pendiente vencida)."
        resource:
          type: string
          description: Recurso de la API afectado, p. ej. `tasks`.
          example: tasks
        operation:
          type: string
          description: Operación en el recurso, p. ej. `run`.
          example: run
        action:
          type: string
          description: Tool del MCP que lo solicitó.
          example: kadu_tasks_run
        requester:
          type: object
          properties:
            client_id:
              type:
                - string
                - "null"
              description: Cliente OAuth del token que lo solicitó (verificado). null = token personal.
            client_name:
              type:
                - string
                - "null"
              description: Nombre que el cliente MCP declaró sobre sí mismo (no verificado).
          required:
            - client_id
            - client_name
        created_at:
          type: string
        expires_at:
          type: string
        decided_at:
          type:
            - string
            - "null"
        executed_at:
          type:
            - string
            - "null"
      required:
        - id
        - status
        - resource
        - operation
        - action
        - requester
        - created_at
        - expires_at
        - decided_at
        - executed_at
    OperationApprovalDetail:
      allOf:
        - $ref: "#/components/schemas/OperationApproval"
        - type: object
          properties:
            organization_name:
              type:
                - string
                - "null"
            card:
              type: object
              additionalProperties: {}
              description: "Lo que muestra la pantalla de aprobación: registros afectados (`sections`), argumentos con etiqueta (`args`) y sin etiqueta (`other`). Después de la decisión, el retrato de lo que se decidió."
            args:
              type: object
              additionalProperties: {}
              description: Argumentos de la llamada.
            result:
              description: "Respuesta de la operación, o `{ error: { code, message } }`. Secretos enmascarados."
          required:
            - organization_name
            - card
            - args
    Role:
      type: object
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type:
            - string
            - "null"
        label:
          type: string
        organization_id:
          type: string
          format: uuid
        permissions:
          type: array
          items:
            type: string
        custom_metadata:
          type: object
          additionalProperties: {}
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - external_id
        - label
        - organization_id
        - permissions
        - custom_metadata
        - created_at
        - updated_at
    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type:
            - string
            - "null"
        name:
          type:
            - string
            - "null"
        email:
          type:
            - string
            - "null"
        role_id:
          type: string
          format: uuid
        last_sign_in_at:
          type:
            - string
            - "null"
        created_at:
          type: string
      required:
        - id
        - external_id
        - name
        - email
        - role_id
        - last_sign_in_at
        - created_at
    Membership:
      type: object
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type:
            - string
            - "null"
        organization_id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        role_id:
          type: string
          format: uuid
        custom_metadata:
          type: object
          additionalProperties: {}
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - external_id
        - organization_id
        - user_id
        - role_id
        - custom_metadata
        - created_at
        - updated_at
    SystemEvent:
      type: object
      properties:
        id:
          type: string
          format: uuid
        slug:
          type: string
          example: execution.created
        organization_id:
          type: string
          format: uuid
        workspace_id:
          type:
            - string
            - "null"
          format: uuid
        activity_id:
          type:
            - string
            - "null"
          format: uuid
        task_id:
          type:
            - string
            - "null"
          format: uuid
        execution_id:
          type:
            - string
            - "null"
          format: uuid
        actor_user_id:
          type:
            - string
            - "null"
          format: uuid
        payload: {}
        created_at:
          type: string
      required:
        - id
        - slug
        - organization_id
        - workspace_id
        - activity_id
        - task_id
        - execution_id
        - actor_user_id
        - created_at
  parameters: {}
paths:
  /v1/me:
    get:
      tags:
        - Identidad
      summary: Identidad detrás del token
      description: "Devuelve la persona, la organización y el token (tipo, alcances, nivel de acceso, expiración) de la credencial Bearer. Sirve para probar si el token configurado es válido: es la única ruta exenta de la verificación de alcance, así que cualquier token válido responde. `user` es la persona del `sub` cuando el token trae correo, y null en un token de máquina. Nunca devuelve el token."
      security:
        - bearerAuth: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      user:
                        type:
                          - object
                          - "null"
                        properties:
                          id:
                            type: string
                          name:
                            type:
                              - string
                              - "null"
                          email:
                            type: string
                        required:
                          - id
                          - name
                          - email
                      organization:
                        type: object
                        properties:
                          id:
                            type: string
                            format: uuid
                          name:
                            type: string
                          external_id:
                            type:
                              - string
                              - "null"
                        required:
                          - id
                          - name
                          - external_id
                      token:
                        type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - oauth
                          scopes:
                            type: array
                            items:
                              type: string
                          access_level:
                            type: string
                            enum:
                              - read
                              - write
                              - all
                          expires_at:
                            type:
                              - string
                              - "null"
                        required:
                          - type
                          - scopes
                          - access_level
                          - expires_at
                    required:
                      - user
                      - organization
                      - token
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-me
  /v1/organizations:
    get:
      tags:
        - Organizaciones
      summary: Lista organizaciones
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Organization"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-organizations
  /v1/organizations/{id}:
    get:
      tags:
        - Organizaciones
      summary: Detalla la organización
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Organization"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-organizations-id
    patch:
      tags:
        - Organizaciones
      summary: Actualiza la organización del token
      description: "`monthly_cost_limit` y `bypass_subscription` los define Kobana y se rechazan (403). Otra organización: 403."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                  maxLength: 255
                timezone:
                  type: string
                  example: America/Sao_Paulo
                custom_metadata:
                  type: object
                  additionalProperties: {}
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Organization"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: FORBIDDEN
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-organizations-id
  /v1/workspaces:
    get:
      tags:
        - Workspaces
      summary: Lista workspaces
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Workspace"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-workspaces
    post:
      tags:
        - Workspaces
      summary: Crea workspace
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                external_id:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: Id del registro en el sistema de origen (texto libre).
                custom_metadata:
                  type: object
                  additionalProperties: {}
              required:
                - label
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Workspace"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: CONFLICT — registro duplicado / IDEMPOTENCY_KEY_REUSED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-workspaces
  /v1/workspaces/{id}:
    get:
      tags:
        - Workspaces
      summary: Detalla el workspace
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Workspace"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-workspaces-id
    patch:
      tags:
        - Workspaces
      summary: Actualiza workspace
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                custom_metadata:
                  type: object
                  additionalProperties: {}
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Workspace"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-workspaces-id
    delete:
      tags:
        - Workspaces
      summary: Elimina workspaces (soft delete)
      description: "Exige el nivel `delete` (o `all`): `write` no elimina. Cascada: activities, tasks, ejecuciones, webhooks, memorias y secrets del workspace; cancela programaciones y desactiva el endpoint de las tasks."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Workspace"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-workspaces-id
  /v1/activities:
    get:
      tags:
        - Actividades
      summary: Lista actividades
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Activity"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-activities
    post:
      tags:
        - Actividades
      summary: Crea activity
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                workspace_id:
                  type: string
                  format: uuid
                external_id:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: Id del registro en el sistema de origen (texto libre).
                custom_metadata:
                  type: object
                  additionalProperties: {}
              required:
                - label
                - workspace_id
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Activity"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — workspace fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-activities
  /v1/activities/{id}:
    get:
      tags:
        - Actividades
      summary: Detalla la actividad
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Activity"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-activities-id
    patch:
      tags:
        - Actividades
      summary: Actualiza activity
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                custom_metadata:
                  type: object
                  additionalProperties: {}
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Activity"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-activities-id
    delete:
      tags:
        - Actividades
      summary: Elimina activities (soft delete)
      description: "Exige el nivel `delete` (o `all`): `write` no elimina. Cascada: tasks, ejecuciones y memorias de la activity; cancela programaciones y desactiva el endpoint de las tasks."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Activity"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-activities-id
  /v1/tasks:
    get:
      tags:
        - Tareas
      summary: Lista tareas
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Task"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-tasks
    post:
      tags:
        - Tareas
      summary: Crea task
      description: La task nace en el tier de precio predeterminado; el tier y el modelo de IA los define Kobana (`model` en el cuerpo se rechaza).
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                workspace_id:
                  type: string
                  format: uuid
                activity_id:
                  type: string
                  format: uuid
                skill_slug:
                  type: string
                  description: "`<plugin>:<skill>` del repositorio de la organización: plugin del workspace (cuando tiene uno), skill presente en el catálogo sincronizado (cuando hay catálogo), nunca `kadu:*`."
                  example: finance:task-baixar-pagamentos-via-boleto-pix
                parameters_schema:
                  type:
                    - object
                    - "null"
                  additionalProperties: {}
                parameters_sensitive:
                  type: boolean
                external_id:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: Id del registro en el sistema de origen (texto libre).
                custom_metadata:
                  type: object
                  additionalProperties: {}
              required:
                - label
                - workspace_id
                - activity_id
                - skill_slug
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Task"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — workspace/activity fuera de la organización o `skill_slug` no permitido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-tasks
  /v1/tasks/{id}:
    get:
      tags:
        - Tareas
      summary: Detalla la tarea
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Task"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-tasks-id
    patch:
      tags:
        - Tareas
      summary: Actualiza task
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                skill_slug:
                  type: string
                  description: "`<plugin>:<skill>` del repositorio de la organización: plugin del workspace (cuando tiene uno), skill presente en el catálogo sincronizado (cuando hay catálogo), nunca `kadu:*`."
                  example: finance:task-baixar-pagamentos-via-boleto-pix
                parameters_schema:
                  type:
                    - object
                    - "null"
                  additionalProperties: {}
                parameters_sensitive:
                  type: boolean
                custom_metadata:
                  type: object
                  additionalProperties: {}
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Task"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: FORBIDDEN — `model` lo define el tier (Kobana)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — `skill_slug` no permitido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-tasks-id
    delete:
      tags:
        - Tareas
      summary: Elimina tasks (soft delete)
      description: "Exige el nivel `delete` (o `all`): `write` no elimina. Cascada: ejecuciones y archivos de la task; cancela programaciones y desactiva el endpoint."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Task"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-tasks-id
  /v1/tasks/{id}/run:
    post:
      tags:
        - Tareas
      summary: Lanza ejecución
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reference_date:
                  type: string
                  pattern: ^\d{4}-\d{2}-\d{2}$
                parameters:
                  type: object
                  additionalProperties: {}
                  default: {}
                environment_id:
                  type: string
                  format: uuid
                locale:
                  type: string
                  pattern: ^[a-z]{2}(-[A-Z]{2})?$
                additional_instructions:
                  type: string
                  maxLength: 8000
                input_file_ids:
                  type: array
                  items:
                    type: string
                    format: uuid
                  maxItems: 50
                  description: Archivos enviados por `POST /files` (confirmados y aún no usados).
                mode:
                  type: string
                  enum:
                    - default
                    - resolve_pendencies
                  default: default
                  description: '`resolve_pendencies` solo resuelve los pendientes de las ejecuciones anteriores de la Task (consola: "Resolver pendientes"); `parameters` se ignora.'
              required:
                - reference_date
                - environment_id
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      execution_id:
                        type: string
                        format: uuid
                      status:
                        type: string
                        enum:
                          - queued
                    required:
                      - execution_id
                      - status
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: 'INSUFFICIENT_SCOPE — exige `write` (o `all`). ENTITLEMENT_REQUIRED — la organización no tiene un plan contratado de Kadu (ni cortesía vigente). details: { reason: "no_plan" | "missing_product", required_product: string | null }. Se verifica antes del tope mensual de costo.'
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: COST_LIMIT_REACHED / INVALID_PARAMETERS / ENVIRONMENT_REQUIRED / MISSING_SECRETS (details.keys) / INVALID_INPUT_FILES
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-tasks-id-run
  /v1/executions:
    get:
      tags:
        - Ejecuciones
      summary: Lista ejecuciones
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Execution"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-executions
  /v1/executions/{id}:
    get:
      tags:
        - Ejecuciones
      summary: Detalla la ejecución
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Execution"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-executions-id
  /v1/executions/{id}/cancel:
    post:
      tags:
        - Ejecuciones
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      responses:
        "200":
          description: cancelled (o el estado terminal actual, si ya terminó)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      status:
                        type: string
                    required:
                      - id
                      - status
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-executions-id-cancel
      summary: Cancela la ejecución
  /v1/executions/{id}/continue:
    post:
      tags:
        - Ejecuciones
      summary: Continúa la conversación (próxima ronda)
      description: "Solo para Task conversacional (`conversational`): crea una ejecución hija de esta que retoma la sesión del agente (contexto, archivos de salida y estado) y atiende el pedido en `message`. Usa los parámetros, la fecha de referencia y el entorno de esta ejecución, que debe estar terminada (`success` o `failed`). Continuar una ronda antigua abre una rama. La nueva ejecución trae `parentExecutionId` (esta) y `rootExecutionId` (la primera ronda)."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                message:
                  type: string
                  minLength: 1
                  maxLength: 8000
                locale:
                  type: string
                  pattern: ^[a-z]{2}(-[A-Z]{2})?$
                input_file_ids:
                  type: array
                  items:
                    type: string
                    format: uuid
                  maxItems: 50
                  description: Archivos nuevos para esta ronda (`POST /files`, aún no usados).
              required:
                - message
      responses:
        "201":
          description: ronda creada (en la cola de la Task)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      execution_id:
                        type: string
                        format: uuid
                      parent_execution_id:
                        type: string
                        format: uuid
                      status:
                        type: string
                        enum:
                          - queued
                    required:
                      - execution_id
                      - parent_execution_id
                      - status
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: NOT_CONVERSATIONAL / EXECUTOR_NOT_SUPPORTED / EXECUTOR_CHANGED / NOT_FINISHED / SESSION_UNAVAILABLE
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: ENVIRONMENT_REQUIRED / MISSING_SECRETS (details.keys) / INVALID_PARAMETERS / INVALID_INPUT_FILES / COST_LIMIT_REACHED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-executions-id-continue
  /v1/memories:
    get:
      tags:
        - Memorias
      summary: Lista memorias
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Memory"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-memories
    post:
      tags:
        - Memorias
      summary: Crea memoria
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
                  minLength: 1
                workspace_id:
                  type:
                    - string
                    - "null"
                  format: uuid
                activity_id:
                  type:
                    - string
                    - "null"
                  format: uuid
                entity_type:
                  type:
                    - string
                    - "null"
                  minLength: 1
                entity_value:
                  type:
                    - string
                    - "null"
                  minLength: 1
                key:
                  type:
                    - string
                    - "null"
                  minLength: 1
                summary:
                  type:
                    - string
                    - "null"
                status:
                  type:
                    - string
                    - "null"
                external_id:
                  type:
                    - string
                    - "null"
                  minLength: 1
                  maxLength: 255
                custom_metadata:
                  type: object
                  additionalProperties: {}
              required:
                - content
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Memory"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: CONFLICT (external_id duplicado en la organización) / IDEMPOTENCY_KEY_REUSED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — workspace/activity fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-memories
  /v1/memories/{id}:
    get:
      tags:
        - Memorias
      summary: Detalla la memoria
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Memory"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-memories-id
    patch:
      tags:
        - Memorias
      summary: Actualiza memoria
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
                  minLength: 1
                workspace_id:
                  type:
                    - string
                    - "null"
                  format: uuid
                activity_id:
                  type:
                    - string
                    - "null"
                  format: uuid
                entity_type:
                  type:
                    - string
                    - "null"
                  minLength: 1
                entity_value:
                  type:
                    - string
                    - "null"
                  minLength: 1
                key:
                  type:
                    - string
                    - "null"
                  minLength: 1
                summary:
                  type:
                    - string
                    - "null"
                status:
                  type:
                    - string
                    - "null"
                custom_metadata:
                  type: object
                  additionalProperties: {}
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Memory"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — workspace/activity fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-memories-id
    delete:
      tags:
        - Memorias
      summary: Elimina memoria (soft delete)
      description: "Exige el nivel `delete` (o `all`): `write` no elimina."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Memory"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-memories-id
  /v1/environments:
    get:
      tags:
        - Entornos
      summary: Lista entornos
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Environment"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-environments
    post:
      tags:
        - Entornos
      summary: Crea entorno
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                color:
                  type: string
                  pattern: ^#[0-9a-fA-F]{6}$
                branch:
                  type: string
                  minLength: 1
                  default: main
              required:
                - label
                - color
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Environment"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: CONFLICT — ya existe un entorno vivo con este label / IDEMPOTENCY_KEY_REUSED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-environments
  /v1/environments/{id}:
    get:
      tags:
        - Entornos
      summary: Detalla el entorno
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Environment"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-environments-id
    patch:
      tags:
        - Entornos
      summary: Actualiza entorno
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                color:
                  type: string
                  pattern: ^#[0-9a-fA-F]{6}$
                branch:
                  type: string
                  minLength: 1
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Environment"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: CONFLICT — label ya usado / IDEMPOTENCY_KEY_REUSED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-environments-id
    delete:
      tags:
        - Entornos
      summary: Elimina entorno (soft delete)
      description: Rechazado mientras el entorno tenga secrets o programaciones.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Environment"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: "ENVIRONMENT_IN_USE — `details: { secrets, schedules }` / REPO_MANAGED — declarado en el `kadu.yaml`: quítalo de allí"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-environments-id
  /v1/secrets:
    get:
      tags:
        - Secrets
      summary: Lista secrets
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Secret"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-secrets
    post:
      tags:
        - Secrets
      summary: Crea secret
      description: El valor se guarda cifrado y nunca se devuelve.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                environment_id:
                  type: string
                  format: uuid
                workspace_id:
                  type:
                    - string
                    - "null"
                  format: uuid
                key:
                  type: string
                  minLength: 1
                value:
                  type: string
                notes:
                  type:
                    - string
                    - "null"
              required:
                - environment_id
                - key
                - value
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Secret"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — entorno o workspace fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-secrets
  /v1/secrets/{id}:
    get:
      tags:
        - Secrets
      summary: Detalla el secret
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Secret"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-secrets-id
    patch:
      tags:
        - Secrets
      summary: Actualiza secret
      description: "`value` ausente o vacío mantiene el valor guardado."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                environment_id:
                  type: string
                  format: uuid
                workspace_id:
                  type:
                    - string
                    - "null"
                  format: uuid
                key:
                  type: string
                  minLength: 1
                value:
                  type: string
                notes:
                  type:
                    - string
                    - "null"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Secret"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — entorno o workspace fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-secrets-id
    delete:
      tags:
        - Secrets
      summary: Elimina secret (soft delete)
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Secret"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-secrets-id
  /v1/schedules:
    get:
      tags:
        - Programaciones
      summary: Lista programaciones
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Schedule"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-schedules
    post:
      tags:
        - Programaciones
      summary: Programa una Task en un entorno
      description: "Una programación por Task y entorno. La programación no se apila: el lanzamiento se omite si la Task ya tiene una ejecución activa o en cola."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                task_id:
                  type: string
                  format: uuid
                environment_id:
                  type: string
                  format: uuid
                cron:
                  type: string
                  minLength: 1
                timezone:
                  type: string
                  default: UTC
                paused:
                  type: boolean
                  default: false
              required:
                - task_id
                - environment_id
                - cron
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Schedule"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: CONFLICT — la Task ya tiene una programación en el entorno (`details.schedule_id`) / IDEMPOTENCY_KEY_REUSED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: INVALID_CRON / VALIDATION_ERROR — Task o entorno fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-schedules
  /v1/schedules/{id}:
    get:
      tags:
        - Programaciones
      summary: Detalla la programación
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Schedule"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-schedules-id
    patch:
      tags:
        - Programaciones
      summary: Modifica, pausa o reanuda una programación
      description: "`paused: true` mantiene el cron y hace que el dispatcher omita la programación."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                cron:
                  type: string
                  minLength: 1
                timezone:
                  type: string
                paused:
                  type: boolean
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Schedule"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: INVALID_CRON
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-schedules-id
    delete:
      tags:
        - Programaciones
      summary: Cancela la programación (soft delete)
      description: Un nuevo POST para la misma Task y entorno reactiva la programación.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Schedule"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: "REPO_MANAGED — declarado en el `schedules` del frontmatter de la skill: quítalo de allí"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-schedules-id
  /v1/tasks/{id}/endpoint:
    get:
      tags:
        - Tareas
      summary: Endpoint HTTP de lanzamiento de la Task
      description: "Configuración del endpoint público `POST /api/run-task/{task_id}`. Las credenciales nunca se devuelven: solo los flags `*_set`."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/TaskEndpoint"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-tasks-id-endpoint
    put:
      tags:
        - Tareas
      summary: Configura el endpoint HTTP de la Task
      description: "Crea o actualiza. Una credencial omitida mantiene la guardada mientras el tipo de auth no cambie. Evita `auth: params`: el secreto va en la URL y queda en los logs de acceso de proxies y CDNs; prefiere `bearer` o `header`."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                auth:
                  type: string
                  enum:
                    - basic
                    - bearer
                    - header
                    - params
                auth_basic_user:
                  type: string
                auth_basic_password:
                  type: string
                auth_bearer_token:
                  type: string
                auth_header_key:
                  type: string
                auth_header_value:
                  type: string
                auth_param_key:
                  type: string
                auth_param_value:
                  type: string
              required:
                - enabled
                - auth
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/TaskEndpoint"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: INCOMPLETE_AUTH — falta la credencial para el tipo de auth elegido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: put-tasks-id-endpoint
    delete:
      tags:
        - Tareas
      summary: Deshabilita el endpoint HTTP de la Task
      description: "Mantiene la configuración; un PUT con `enabled: true` reactiva."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/TaskEndpoint"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-tasks-id-endpoint
  /v1/tasks/{id}/readiness:
    get:
      tags:
        - Tareas
      summary: Verificación previa del lanzamiento
      description: "Si la Task puede correr en el entorno: entorno válido y valor para todos los secrets exigidos (en el workspace de la Task o globales). Trae también la cola de la Task. El lanzamiento revalida todo."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            format: uuid
          required: false
          name: environment_id
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      ready:
                        type: boolean
                      environment:
                        type:
                          - object
                          - "null"
                        properties:
                          id:
                            type: string
                            format: uuid
                          label:
                            type: string
                          color:
                            type: string
                        required:
                          - id
                          - label
                          - color
                      required_secrets:
                        type: array
                        items:
                          type: string
                      missing_secrets:
                        type: array
                        items:
                          type: string
                      queue:
                        type: object
                        properties:
                          active:
                            type:
                              - object
                              - "null"
                            properties:
                              id:
                                type: string
                                format: uuid
                              status:
                                type: string
                            required:
                              - id
                              - status
                          queued:
                            type: number
                        required:
                          - active
                          - queued
                    required:
                      - ready
                      - environment
                      - required_secrets
                      - missing_secrets
                      - queue
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-tasks-id-readiness
  /v1/files:
    get:
      tags:
        - Archivos
      summary: Lista archivos
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/File"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-files
    post:
      tags:
        - Archivos
      summary: Inicia la carga de un archivo de entrada
      description: "Flujo en tres pasos: (1) este POST crea el archivo `pending` y devuelve `upload_url`; (2) `PUT` de los bytes en `upload_url` con el mismo `Content-Type`; (3) `POST /files/{id}/confirm`. El id va en `input_file_ids` del `POST /tasks/{id}/run` (la Task debe aceptar archivos de entrada). Tamaño máximo: 100 MB."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                task_id:
                  type: string
                  format: uuid
                filename:
                  type: string
                  minLength: 1
                  maxLength: 255
                content_type:
                  type: string
                  default: application/octet-stream
                size_bytes:
                  type: integer
                  minimum: 0
              required:
                - task_id
                - filename
                - size_bytes
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      filename:
                        type: string
                      content_type:
                        type: string
                      status:
                        type: string
                        enum:
                          - pending
                      upload_url:
                        type: string
                      expires_in:
                        type: number
                        description: Vigencia de `upload_url`, en segundos.
                    required:
                      - id
                      - filename
                      - content_type
                      - status
                      - upload_url
                      - expires_in
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: TASK_DOES_NOT_ACCEPT_FILES / VALIDATION_ERROR — Task fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-files
  /v1/files/{id}:
    get:
      tags:
        - Archivos
      summary: Detalla el archivo
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/File"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-files-id
  /v1/files/{id}/confirm:
    post:
      tags:
        - Archivos
      summary: Confirma la carga (pending → uploaded)
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/File"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: CONFLICT — no es un archivo de entrada pendiente / IDEMPOTENCY_KEY_REUSED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-files-id-confirm
  /v1/files/{id}/download:
    get:
      tags:
        - Archivos
      summary: URL temporal de descarga
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      url:
                        type: string
                      expires_in:
                        type: number
                    required:
                      - id
                      - url
                      - expires_in
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: FILE_NOT_UPLOADED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-files-id-download
  /v1/executions/search:
    get:
      tags:
        - Ejecuciones
      summary: Búsqueda de texto en las ejecuciones
      description: "Busca en eventos, todos, logs, resultado y error. Hasta 30 ejecuciones, las más recientes primero, cada una con hasta 3 fragmentos. Solo entran las fuentes que quien llama podría leer directamente: los logs exigen la habilitación `executions_logs.view` de la organización, y en un token de persona el rol necesita `agent.logs.list`, `agent.events.list` y `agent.todos.list` para logs, eventos y todos."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 2
          required: true
          name: q
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                        skill:
                          type: string
                        status:
                          type: string
                        started_at:
                          type: string
                        finished_at:
                          type:
                            - string
                            - "null"
                        workspace_label:
                          type:
                            - string
                            - "null"
                        activity_label:
                          type:
                            - string
                            - "null"
                        task_label:
                          type:
                            - string
                            - "null"
                        matches:
                          type: array
                          items:
                            type: object
                            properties:
                              source:
                                type: string
                                enum:
                                  - event
                                  - result
                                  - logs
                                  - error
                                  - todo
                              snippet:
                                type: string
                            required:
                              - source
                              - snippet
                      required:
                        - id
                        - skill
                        - status
                        - started_at
                        - finished_at
                        - workspace_label
                        - activity_label
                        - task_label
                        - matches
                required:
                  - data
        "400":
          description: VALIDATION_ERROR — `q` con menos de 2 caracteres
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: "RATE_LIMITED — límite propio de la búsqueda: 30 por minuto por token"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-executions-search
  /v1/executions/{id}/logs:
    get:
      tags:
        - Ejecuciones
      summary: Logs de la ejecución
      description: En orden de llegada, hasta 1000 por llamada. Para seguir una ejecución en curso, pasa en `after_id` el último `id` recibido y repite.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type:
              - integer
              - "null"
          required: false
          name: after_id
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: number
                        execution_id:
                          type: string
                          format: uuid
                        occurred_at:
                          type: string
                        level:
                          type: string
                        text:
                          type: string
                      required:
                        - id
                        - execution_id
                        - occurred_at
                        - level
                        - text
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-executions-id-logs
  /v1/executions/{id}/events:
    get:
      tags:
        - Ejecuciones
      summary: Eventos de la ejecución
      description: Por `sequence`, hasta 500 por llamada. Para seguir, pasa en `after_sequence` el último `sequence` recibido y repite.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type:
              - integer
              - "null"
          required: false
          name: after_sequence
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: number
                        execution_id:
                          type: string
                          format: uuid
                        sequence:
                          type: number
                        occurred_at:
                          type: string
                        type:
                          type: string
                        level:
                          type: string
                        step:
                          type:
                            - string
                            - "null"
                        message:
                          type: string
                        payload: {}
                      required:
                        - id
                        - execution_id
                        - sequence
                        - occurred_at
                        - type
                        - level
                        - step
                        - message
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-executions-id-events
  /v1/repository:
    get:
      tags:
        - Repositorio
      summary: Kadu Playbook de la organización
      description: Conectar el repositorio es la instalación de la GitHub App, hecha en la consola (flujo OAuth en el navegador).
      security:
        - bearerAuth: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type:
                          - string
                          - "null"
                      connection:
                        type:
                          - string
                          - "null"
                        enum:
                          - github_app
                          - deploy_key
                          - null
                      skills_count:
                        type: number
                      synced_at:
                        type:
                          - string
                          - "null"
                      sync_error:
                        type:
                          - string
                          - "null"
                    required:
                      - url
                      - connection
                      - skills_count
                      - synced_at
                      - sync_error
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-repository
  /v1/repository/sync:
    post:
      tags:
        - Repositorio
      summary: Sincroniza el Kadu Playbook
      description: Encola la sincronización (el worker clona el repositorio y actualiza el catálogo de Tasks). Sigue `synced_at` y `sync_error` en `GET /repository`.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      responses:
        "202":
          description: accepted
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enqueued:
                        type: boolean
                        enum:
                          - true
                    required:
                      - enqueued
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: NO_PLUGIN_REPO / NO_DEPLOY_KEY
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: QUEUE_UNAVAILABLE / AS_UNAVAILABLE
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-repository-sync
  /v1/usage:
    get:
      tags:
        - Uso
      summary: Uso y costo de las ejecuciones y de las conversaciones
      description: "Agregado por día (en la zona horaria de la organización) × grupo, sumando ejecuciones y turnos de conversación del bot de Slack (origen `slack_chat`, sin workspace/actividad/Task). Por defecto: últimos 30 días; período máximo de 366 días. `group` es el id (tier, workspace, activity, task) o el origen; null = sin valor."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          required: false
          name: from
          in: query
        - schema:
            type: string
            pattern: ^\d{4}-\d{2}-\d{2}$
          required: false
          name: to
          in: query
        - schema:
            type: string
            enum:
              - tier
              - workspace
              - activity
              - task
              - source
          required: false
          name: group_by
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: workspace_id
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: activity_id
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: task_id
          in: query
        - schema:
            type: string
          required: false
          name: source
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      from:
                        type: string
                      to:
                        type: string
                      time_zone:
                        type: string
                      group_by:
                        type: string
                      totals:
                        type: object
                        properties:
                          executions:
                            type: number
                          conversation_turns:
                            type: number
                            description: Turnos de conversación del bot de Slack (origen `slack_chat`).
                          input_tokens:
                            type: number
                          output_tokens:
                            type: number
                          cache_read_tokens:
                            type: number
                          cache_write_tokens:
                            type: number
                          cost_brl:
                            type: number
                            description: Precio en R$ (tokens × precio del tier). Solo con Analytics › Costo habilitado.
                        required:
                          - executions
                          - conversation_turns
                          - input_tokens
                          - output_tokens
                          - cache_read_tokens
                          - cache_write_tokens
                      buckets:
                        type: array
                        items:
                          type: object
                          properties:
                            executions:
                              type: number
                            conversation_turns:
                              type: number
                              description: Turnos de conversación del bot de Slack (origen `slack_chat`).
                            input_tokens:
                              type: number
                            output_tokens:
                              type: number
                            cache_read_tokens:
                              type: number
                            cache_write_tokens:
                              type: number
                            cost_brl:
                              type: number
                              description: Precio en R$ (tokens × precio del tier). Solo con Analytics › Costo habilitado.
                            date:
                              type: string
                            group:
                              type:
                                - string
                                - "null"
                          required:
                            - executions
                            - conversation_turns
                            - input_tokens
                            - output_tokens
                            - cache_read_tokens
                            - cache_write_tokens
                            - date
                            - group
                    required:
                      - from
                      - to
                      - time_zone
                      - group_by
                      - totals
                      - buckets
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE (ver arriba) o FEATURE_NOT_ENABLED — la operación no está habilitada para la organización (el mismo permiso que habilita la pantalla en la consola); `details: { permission }`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-usage
  /v1/organizations/{id}/slack_installations:
    get:
      tags:
        - Organizaciones
      summary: Instalaciones del bot de Slack de la organización
      description: "Workspaces de Slack vinculados a la organización del token. Otra organización: 403."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/SlackInstallation"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-organizations-id-slack-installations
  /v1/organizations/{id}/slack_installations/{installationId}:
    patch:
      tags:
        - Organizaciones
      summary: Configura una instalación de Slack
      description: Dónde responde el bot (`allowed_channel_types`), archivos de salida como enlace o adjunto (`files_mode`, `max_upload_bytes` hasta 100 MB) y detalle en el hilo (`log_detail`).
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            format: uuid
          required: true
          name: installationId
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                allowed_channel_types:
                  type: array
                  items:
                    type: string
                    enum:
                      - im
                      - private_channel
                      - public_channel
                      - mpim
                      - shared_channel
                  minItems: 1
                files_mode:
                  type: string
                  enum:
                    - link
                    - upload
                max_upload_bytes:
                  type: integer
                  exclusiveMinimum: 0
                  maximum: 104857600
                log_detail:
                  type: string
                  enum:
                    - milestones
                    - verbose
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/SlackInstallation"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-organizations-id-slack-installations-installationid
    delete:
      tags:
        - Organizaciones
      summary: Quita una instalación de Slack
      description: Exige el nivel `delete` (o `all`). Revoca el token del bot en Slack y deshace las conexiones de cuenta.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            format: uuid
          required: true
          name: installationId
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      deleted:
                        type: boolean
                    required:
                      - id
                      - deleted
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-organizations-id-slack-installations-installationid
  /v1/executions/{id}/todos:
    get:
      tags:
        - Ejecuciones
      summary: Pendientes (todos) de la ejecución
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Todo"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-executions-id-todos
  /v1/todos/{id}:
    patch:
      tags:
        - Pendientes
      summary: Resuelve pendiente
      description: "La única transición por la API: `status: resolved`."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            pattern: ^\d+$
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                  enum:
                    - resolved
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Todo"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-todos-id
  /v1/webhooks:
    get:
      tags:
        - Webhooks
      summary: Lista webhooks
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Webhook"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-webhooks
    post:
      tags:
        - Webhooks
      summary: Crea webhook
      description: La URL se verifica contra la red interna. `signing_secret` se devuelve solo en esta respuesta (el replay de idempotencia devuelve `null`).
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                workspace_id:
                  type:
                    - string
                    - "null"
                  format: uuid
                url:
                  type: string
                  format: uri
                auth:
                  type: string
                  enum:
                    - basic
                    - bearer
                    - header
                auth_basic_user:
                  type: string
                auth_basic_password:
                  type: string
                auth_bearer_token:
                  type: string
                auth_header_key:
                  type: string
                auth_header_value:
                  type: string
                subscribed_events:
                  type: array
                  items:
                    type: string
                  default: []
                emails:
                  type: array
                  items:
                    type: object
                    properties:
                      address:
                        type: string
                        format: email
                    required:
                      - address
                  default: []
              required:
                - label
                - url
                - auth
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    allOf:
                      - $ref: "#/components/schemas/Webhook"
                      - type: object
                        properties:
                          signing_secret:
                            type:
                              - string
                              - "null"
                        required:
                          - signing_secret
                    description: Los secretos y las credenciales nunca se devuelven.
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: FEATURE_NOT_ENABLED — exige la habilitación `webhooks.create` de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: VALIDATION_ERROR — workspace fuera de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-webhooks
  /v1/webhooks/{id}:
    get:
      tags:
        - Webhooks
      summary: Detalla el webhook
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Webhook"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-webhooks-id
    patch:
      tags:
        - Webhooks
      summary: Actualiza webhook
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                url:
                  type: string
                  format: uri
                subscribed_events:
                  type: array
                  items:
                    type: string
                status:
                  type: string
                  enum:
                    - active
                    - inactive
                emails:
                  type: array
                  items:
                    type: object
                    properties:
                      address:
                        type: string
                        format: email
                    required:
                      - address
                auth_basic_user:
                  type: string
                auth_basic_password:
                  type: string
                auth_bearer_token:
                  type: string
                auth_header_key:
                  type: string
                auth_header_value:
                  type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Webhook"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: FEATURE_NOT_ENABLED — exige la habilitación `webhooks.update` de la organización
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: patch-webhooks-id
    delete:
      tags:
        - Webhooks
      summary: Elimina webhooks (soft delete)
      description: "Exige el nivel `delete` (o `all`): `write` no elimina. Exige la habilitación `webhooks.delete`. Un webhook declarado en el `kadu.yaml` (`repo_managed`) responde 409 REPO_MANAGED: quítalo de allí."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Webhook"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: delete-webhooks-id
  /v1/webhooks/{id}/rotate-secret:
    post:
      tags:
        - Webhooks
      summary: Rota el secreto de firma
      description: "Devuelve el secreto nuevo solo en esta respuesta; el anterior sigue firmando por 24h (el replay de idempotencia devuelve `signing_secret: null`)."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      signing_secret:
                        type:
                          - string
                          - "null"
                      previous_signing_secret_expires_at:
                        type: string
                    required:
                      - id
                      - signing_secret
                      - previous_signing_secret_expires_at
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-webhooks-id-rotate-secret
  /v1/webhook_deliveries:
    get:
      tags:
        - Entregas de webhook
      summary: Entregas de webhook (las 50 más recientes)
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: false
          name: webhook_id
          in: query
        - schema:
            type: string
            enum:
              - pending
              - success
              - failed
          required: false
          name: status
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WebhookDelivery"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "400":
          description: BAD_REQUEST — `status` o `webhook_id` inválido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-webhook-deliveries
  /v1/webhook_deliveries/{id}:
    get:
      tags:
        - Entregas de webhook
      summary: Detalla la entrega de webhook
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WebhookDelivery"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-webhook-deliveries-id
  /v1/webhook_deliveries/{id}/replay:
    post:
      tags:
        - Entregas de webhook
      summary: Reencola la entrega
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      responses:
        "202":
          description: accepted
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      webhook_delivery_id:
                        type: string
                        format: uuid
                      webhook_id:
                        type: string
                        format: uuid
                      system_event_id:
                        type: string
                        format: uuid
                      enqueued:
                        type: boolean
                        enum:
                          - true
                    required:
                      - webhook_delivery_id
                      - webhook_id
                      - system_event_id
                      - enqueued
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: REPLAY_IN_FLIGHT — ya hay un reenvío pendiente de este evento / IDEMPOTENCY_KEY_REUSED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-webhook-deliveries-id-replay
  /v1/operation_approvals:
    get:
      tags:
        - Aprobaciones
      summary: Aprobaciones por enlace de la persona del token
      description: "Operaciones que un asistente solicitó por MCP y que solo se ejecutan después de que la persona las confirma por enlace en la consola. Lista solo las aprobaciones de la persona del token, en la organización del token, las más recientes primero. Solo lectura: Continuar y Cancelar ocurren en la consola. Alcance: `kadu/system_events`."
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            enum:
              - pending
              - approved
              - executed
              - declined
              - failed
              - expired
          required: false
          name: status
          in: query
        - schema:
            type: string
            example: tasks
          required: false
          name: resource
          in: query
        - schema:
            type: string
            description: ISO 8601 (fecha o fecha y hora).
          required: false
          description: ISO 8601 (fecha o fecha y hora).
          name: created_at[gte]
          in: query
        - schema:
            type: string
            description: ISO 8601 (fecha o fecha y hora).
          required: false
          description: ISO 8601 (fecha o fecha y hora).
          name: created_at[lte]
          in: query
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/OperationApproval"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "400":
          description: VALIDATION_ERROR — filtro o cursor inválido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: PERSON_REQUIRED — el token no es de una persona de la organización / INSUFFICIENT_SCOPE
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-operation-approvals
  /v1/operation_approvals/{id}:
    get:
      tags:
        - Aprobaciones
      summary: Detalla una aprobación por enlace
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/OperationApprovalDetail"
                required:
                  - data
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: PERSON_REQUIRED — el token no es de una persona de la organización / INSUFFICIENT_SCOPE
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: NOT_FOUND
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-operation-approvals-id
  /v1/roles:
    get:
      tags:
        - Roles
      summary: Lista roles
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Role"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-roles
    post:
      tags:
        - Roles
      summary: Crea rol
      description: Permisos con el formato `*`, `agent.*`, `agent.<recurso>.*` o `agent.<recurso>.<acción>`. En un token de persona, ninguno puede ir más allá del rol de quien crea.
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 255
            description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          required: false
          description: "Clave opaca (hasta 255 caracteres), válida por 24h en la organización. La misma clave + la misma solicitud devuelve la respuesta original con `X-Idempotent-Replay: true`; la misma clave con un cuerpo distinto → 409 IDEMPOTENCY_KEY_REUSED. Un secreto de un solo uso (`signing_secret` en la creación y en la rotación de webhook) no se guarda: en el replay vuelve `null`."
          name: X-Idempotency-Key
          in: header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                  maxLength: 255
                permissions:
                  type: array
                  items:
                    type: string
                  maxItems: 200
                  default: []
              required:
                - label
      responses:
        "201":
          description: created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Role"
                required:
                  - data
        "400":
          description: VALIDATION_ERROR
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: PERMISSION_ESCALATION — `details.permissions` lista lo que excede tu rol
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: IDEMPOTENCY_KEY_REUSED / IDEMPOTENCY_REQUEST_IN_PROGRESS (o CONFLICT de la ruta)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: post-roles
  /v1/users:
    get:
      tags:
        - Usuarios
      summary: Miembros de la organización (hasta 100)
      security:
        - bearerAuth: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/User"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-users
  /v1/memberships:
    get:
      tags:
        - Vínculos
      summary: Lista vínculos
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: number
            minimum: 1
            maximum: 100
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          required: false
          description: "Campo en snake_case: created_at (predeterminado), updated_at o un campo filtrable."
          name: sort_by
          in: query
        - schema:
            type: string
            enum:
              - asc
              - desc
            description: "Predeterminado: desc."
          required: false
          description: "Predeterminado: desc."
          name: sort_order
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Membership"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-memberships
  /v1/system_events:
    get:
      tags:
        - Eventos de sistema
      summary: Eventos de sistema (los 100 más recientes)
      security:
        - bearerAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: slug
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: workspace_id
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: task_id
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: execution_id
          in: query
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/SystemEvent"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
                required:
                  - data
                  - meta
        "400":
          description: VALIDATION_ERROR — filtro inválido
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: INVALID_TOKEN / INVALID_AUDIENCE / INVALID_ISSUER / TOKEN_EXPIRED / TOKEN_REVOKED / MTLS_REQUIRED
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: "INSUFFICIENT_SCOPE — el token no tiene el nivel de acceso (o el recurso `kadu/…`) que exige la operación; `details: { required, granted }`. USER_PERMISSION_DENIED — el rol de la persona dueña del token no concede la operación; `details: { required }`. NOT_A_MEMBER — la persona no es miembro de la organización. FEATURE_NOT_ENABLED — la operación no está habilitada para la organización; `details: { permission }`. UNKNOWN_ORGANIZATION — el `org` del token no es una organización de Kadu."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: AS_UNAVAILABLE — la verificación del token no está disponible (Authorization Server fuera de línea o configuración ausente). Intenta de nuevo (`Retry-After`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      operationId: get-system-events
webhooks: {}
tags:
  - name: Identidad
    description: Quién está detrás del token.
  - name: Organizaciones
    description: "La organización del token: nombre, zona horaria, tope mensual de costo y `custom_metadata`."
  - name: Workspaces
    description: Dominios de negocio de la organización. Cada workspace es un plugin del Kadu Playbook.
  - name: Actividades
    description: Agrupadores de tareas dentro de un workspace.
  - name: Tareas
    description: "Las skills ejecutables de la organización: registro, lanzamiento, verificación previa y el endpoint HTTP de lanzamiento."
  - name: Ejecuciones
    description: Cada lanzamiento de una tarea, con logs, eventos, pendientes y búsqueda de texto.
  - name: Pendientes
    description: Pendientes creados por las ejecuciones.
  - name: Archivos
    description: Archivos de entrada (adjuntados al lanzamiento) y de salida (publicados por la ejecución).
  - name: Entornos
    description: Entornos de ejecución (Producción, Sandbox…). Cada secret y programación pertenece a uno.
  - name: Secrets
    description: Credenciales entregadas a las ejecuciones. El valor se guarda cifrado y nunca se devuelve.
  - name: Programaciones
    description: Ejecuciones recurrentes de una tarea en un entorno, por expresión cron.
  - name: Memorias
    description: "Memoria de la organización: registros por entidad (`entity_type` + `entity_value`), en el alcance de la organización, de un workspace o de una actividad."
  - name: Webhooks
    description: Notificaciones HTTP firmadas enviadas cuando ocurren eventos.
  - name: Entregas de webhook
    description: Historial y reenvío de las entregas de webhook.
  - name: Aprobaciones
    description: Operaciones solicitadas por un asistente por MCP que esperan la confirmación de la persona por enlace (solo lectura).
  - name: Repositorio
    description: El Kadu Playbook de la organización y su sincronización.
  - name: Uso
    description: Tokens, costo y precio de las ejecuciones.
  - name: Usuarios
    description: Miembros de la organización.
  - name: Vínculos
    description: Vínculos de personas con la organización.
  - name: Roles
    description: Roles y los permisos `agent.*` que conceden.
  - name: Eventos de sistema
    description: Eventos de la organización (los mismos que alimentan los webhooks).
