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

# Guía de integración

> Conecta servicios externos a Flowker a través de configuraciones de provider. Configura autenticación, mapea campos y ejecuta workflows con integraciones reales.

Flowker llama a servicios externos (como motores anti-fraude, procesadores de pago y providers KYC) a través de configuraciones de provider. Una configuración de provider es tu conexión a una instancia activa de un servicio externo.

En esta guía, explorarás el catálogo, crearás una configuración de provider, la referenciarás desde un node de workflow, mapearás campos entre tus datos y el servicio, y entenderás cómo Flowker reintenta y protege esas llamadas.

## Paso 1: Explorar el catálogo

***

El catálogo es un registro de solo lectura de los providers, executors del catálogo y triggers que vienen con Flowker. Los descubres; nunca los creas.

<Steps>
  <Step title="Listar providers disponibles">
    Llama al endpoint [Listar providers del catálogo](/es/reference/flowker/list-catalog-providers) para ver los tipos de servicio a los que Flowker se conecta. El catálogo siempre incluye el conector HTTP genérico. Los proveedores nativos, como `ledger` (Midaz) y `tracer`, se generan a partir de especificaciones OpenAPI publicadas y aparecen solo cuando el registro de esquemas nativos está configurado y la generación se completa correctamente.
  </Step>

  <Step title="Listar executors del catálogo disponibles">
    Llama al endpoint [Listar executors del catálogo](/es/reference/flowker/list-catalog-executors) para ver las operaciones que un node de workflow puede invocar. Usa [Listar executors por provider](/es/reference/flowker/list-executors-by-provider) para acotar la lista a un solo provider.
  </Step>

  <Step title="Listar triggers disponibles">
    Llama al endpoint [Listar triggers del catálogo](/es/reference/flowker/list-catalog-triggers) para ver los tipos de trigger integrados: webhooks y schedules. La API de ejecutar un workflow inicia un workflow, pero no es un trigger del catálogo.
  </Step>

  <Step title="Elige lo que necesitas">
    Anota el `providerId` y el id del executor del catálogo que coinciden con tu integración. Usas el primero en el [Paso 2](#paso-2-crear-una-configuración-de-provider) y el segundo en el [Paso 3](#paso-3-referenciar-la-configuración-de-provider-desde-un-node-de-workflow).
  </Step>
</Steps>

<Tip>
  Piensa en el catálogo como un menú: muestra a qué puede llamar Flowker. Las configuraciones de provider son tus pedidos específicos — la URL base, las credenciales y los ajustes para cada instancia de servicio que usas.
</Tip>

## Paso 2: Crear una configuración de provider

***

Llama a [`POST /v1/provider-configurations`](/es/reference/flowker/create-provider-configuration) para definir tu conexión a una instancia de un servicio externo.

| Campo                 | Obligatorio    | Descripción                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| --------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                | Sí             | Un nombre para esta conexión, de 1 a 100 caracteres.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `kind`                | No             | Qué tipo de conexión es esta. Omítelo, o envía `catalog`, para una conexión a un provider del catálogo — el caso que cubre esta guía. Envía `external_openapi` para una conexión a un documento OpenAPI que subiste; consulta [Conectar tu propia API](/es/flowker/connecting-your-own-api). Eliges el kind al crear la configuración.                                                                                                                                                                                     |
| `providerId`          | Para `catalog` | El provider del catálogo del que esta conexión es una instancia, como `ledger` o `http`. Una configuración de kind `external_openapi` puede omitirlo, y una lectura de ella devuelve el id reservado `external.openapi`.                                                                                                                                                                                                                                                                                                   |
| `config`              | Sí             | Los detalles de conexión de esa instancia, como la URL base y las credenciales de autenticación. Flowker valida este mapa contra el JSON Schema del provider en el catálogo y devuelve `422` cuando no coincide. El valor secreto dentro del bloque `auth` se guarda en tu backend de secretos, no en el documento de configuración; todo lo demás del mapa se almacena junto con la configuración.                                                                                                                        |
| `allowedHosts`        | Para `http`    | Los hosts públicos que esta configuración puede llamar. El conector HTTP genérico (`providerId: "http"`) exige al menos una entrada, y la lista vacía se rechaza con `FLK-0323`. Los providers nativos aceptan una lista vacía. Una entrada con punto inicial coincide con subdominios — `.kyc-provider.io` coincide con `api.kyc-provider.io`. Solo nombres de host: sin literales IP, comodines ni puertos. El host de `config.base_url` debe estar cubierto por la lista; si no, la creación se rechaza con `FLK-0320`. |
| `allowedPrivateHosts` | No             | Hosts privados nombrados que tu equipo de operaciones permite alcanzar a esta configuración. Las direcciones de metadatos de nube y link-local siguen bloqueadas.                                                                                                                                                                                                                                                                                                                                                          |
| `schemaBindings`      | No             | Los esquemas XSD u OpenAPI vinculados a esta configuración, cada uno con una restricción opcional a operaciones OpenAPI específicas.                                                                                                                                                                                                                                                                                                                                                                                       |
| `description`         | No             | Texto libre, hasta 500 caracteres.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `metadata`            | No             | Tus propios pares clave-valor.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |

<Note>
  Un `providerId` es un identificador del catálogo, y no siempre coincide con el nombre del producto. Midaz está registrado como `ledger`. Toma siempre el valor de [Listar providers del catálogo](/es/reference/flowker/list-catalog-providers) en lugar de deducirlo del nombre del producto.
</Note>

<Warning>
  El `providerId` de la configuración y el `executorId` del node que la usa deben pertenecer al mismo provider del catálogo. El conector HTTP genérico usa `http` en ambos. Un workflow que combina una configuración de un provider con un executor de otro se rechaza con `FLK-0151`.
</Warning>

El ejemplo de abajo construye la conexión que esta guía usa de aquí en adelante: un servicio de puntuación de fraude alcanzado por el conector HTTP genérico.

<Accordion title="Ejemplo de solicitud">
  ```json theme={null}
  POST /v1/provider-configurations

  {
    "name": "FraudShield Production",
    "description": "Servicio de puntuación de fraude en producción",
    "providerId": "http",
    "config": {
      "base_url": "https://api.fraudshield.example.com",
      "auth": {
        "type": "api_key",
        "config": {
          "key": "sk-prod-xxx",
          "header_name": "X-API-Key",
          "location": "header"
        }
      }
    },
    "allowedHosts": ["api.fraudshield.example.com"],
    "metadata": {
      "environment": "production"
    }
  }
  ```

  La respuesta devuelve el `id` de la nueva configuración. Guárdalo — el [Paso 3](#paso-3-referenciar-la-configuración-de-provider-desde-un-node-de-workflow) y el [Paso 4](#paso-4-ejecutar-el-workflow) lo ponen en el `providerConfigId` del node que llama al servicio.
</Accordion>

### Autenticación

El bloque `config.auth` contiene la autenticación que el servicio externo exige, como un par `{ type, config }`. Usa el método que tu servicio espera.

| Tipo                      | Descripción                                                                      | Campos de config                                                                                           |
| ------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `none`                    | Sin autenticación.                                                               | —                                                                                                          |
| `api_key`                 | API key en header o query.                                                       | `key`, `header_name`, `location`, `query_param_name`, `prefix`                                             |
| `bearer`                  | Token bearer en el header Authorization.                                         | `token`                                                                                                    |
| `basic`                   | Usuario y contraseña (Base64).                                                   | `username`, `password`                                                                                     |
| `oidc_client_credentials` | Flujo OAuth 2.0 client credentials con gestión automática de tokens.             | `issuer_url`, `client_id`, `client_secret`, `scopes`                                                       |
| `oidc_user`               | Flujo OAuth 2.0 resource owner password.                                         | `issuer_url`, `client_id`, `username`, `password`, `client_secret`, `scopes`                               |
| `oauth2_token_endpoint`   | OAuth 2.0 client credentials contra un token endpoint (sin descubrimiento OIDC). | `token_url`, `client_id`, `client_secret`, `scopes`                                                        |
| `hmac`                    | Firma cada solicitud con un secreto HMAC compartido.                             | `secret`, `algorithm`, `encoding`, `header_name`, `signature_prefix`, `signing_string`, `timestamp_header` |

Los campos secretos de `config.auth` se almacenan fuera del documento de configuración persistido. Una lectura autorizada de la configuración del proveedor puede resolver esos valores desde el vault y devolverlos sin máscara; los campos que no se resuelven permanecen enmascarados. Otorga el acceso de lectura en consecuencia.

Cualquier otra cosa que pongas en el documento de configuración — un header, por ejemplo — se almacena junto con la configuración, y una lectura puede devolverla. Pon cada credencial en `config.auth`.

Para rotar un secreto, envía el nuevo valor en una actualización. Para conservar el actual, omite el campo o envíalo en blanco: esto funciona mientras `auth.type` no cambie. Una actualización que cambia `auth.type` debe llevar un valor para cada secreto que el nuevo tipo exige y el anterior no exigía; si falta, Flowker la rechaza con `FLK-0952`. Un cambio entre dos tipos que usan el mismo secreto, como de `oidc_user` a `oidc_client_credentials`, no necesita ese valor otra vez.

<Tip>
  Para integraciones OAuth 2.0, usa `oidc_client_credentials`. Flowker gestiona la obtención y renovación de tokens automáticamente.
</Tip>

<Accordion title="Ejemplo — OIDC client credentials">
  ```json theme={null}
  {
    "auth": {
      "type": "oidc_client_credentials",
      "config": {
        "issuer_url": "https://auth.fraudshield.com/realms/fraudshield",
        "client_id": "flowker-integration",
        "client_secret": "secret-value",
        "scopes": ["transactions:read", "transactions:score"]
      }
    }
  }
  ```
</Accordion>

### Habilitar y deshabilitar

Las configuraciones de provider tienen dos estados: `active` (en uso) y `disabled` (temporalmente offline). Se crean con estado `active`. Usa [Deshabilitar configuración de provider](/es/reference/flowker/disable-provider-configuration) para sacar una conexión de servicio y [Habilitar configuración de provider](/es/reference/flowker/enable-provider-configuration) para devolverla.

Consulta la [API de Configuraciones de provider](/es/reference/flowker/list-provider-configurations) para la referencia completa.

## Paso 3: Referenciar la configuración de provider desde un node de workflow

***

Cada node executor lleva un `providerConfigId` — el identificador de la configuración de provider a través de la cual llama. Flowker rechaza un workflow cuyo node executor no tiene `providerConfigId`, y rechaza un valor que no sea un UUID. En tiempo de ejecución, construye cada solicitud saliente con la URL base de esa configuración de provider más el path del node, y el node falla si la configuración de provider no está `active`.

Estos son los campos que un node executor define en su objeto `data` cuando llama a través del conector HTTP genérico:

| Campo                                              | Obligatorio | Descripción                                                                                                                                                                                                                                   |
| -------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `executorId`                                       | Sí          | El executor del catálogo que este node invoca, tomado del [Paso 1](#paso-1-explorar-el-catálogo). Flowker rechaza el workflow cuando el id no está en el catálogo. Un node que llama a un documento OpenAPI subido lo omite — mira más abajo. |
| `providerConfigId`                                 | Sí          | El UUID de la configuración de provider a través de la cual llama este node.                                                                                                                                                                  |
| `path`                                             | No          | El path de la solicitud, añadido a la URL base de la configuración de provider. El host de destino es siempre esa URL base — un node no puede indicar una URL absoluta.                                                                       |
| `endpointName`                                     | No          | El mismo segmento de la solicitud, indicado por nombre, que se usa cuando el node no define `path`. Un node que lleva ambos envía `path`.                                                                                                     |
| `method`                                           | No          | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD` u `OPTIONS`. Por defecto, `POST`.                                                                                                                                                             |
| `headers`                                          | No          | Headers de la solicitud, combinados sobre los que define la configuración de provider. Un header del node gana sobre un header del mismo nombre en la configuración de provider.                                                              |
| `query`                                            | No          | Parámetros de consulta añadidos a la URL.                                                                                                                                                                                                     |
| `auth`                                             | No          | Un bloque de autenticación `{type, config}` para este node, con la misma forma que usa la configuración de provider. Cuando está presente, tiene precedencia sobre la autenticación de la configuración de provider.                          |
| `body`                                             | No          | Un cuerpo de solicitud explícito, resuelto contra el contexto del workflow. Cuando se define, es la única fuente del cuerpo — los mapeos de campos no se le aplican.                                                                          |
| `config`                                           | No          | Valores literales fijos que alimentan el cuerpo de la solicitud. Consulta [Mapeo de campos y transformación de datos](#mapeo-de-campos-y-transformación-de-datos).                                                                            |
| `inputMapping`, `outputMapping`, `transforms`      | No          | Mapeos de campos y transformaciones. Consulta [Mapeo de campos y transformación de datos](#mapeo-de-campos-y-transformación-de-datos).                                                                                                        |
| `timeout_seconds`, `retry`, `success_status_codes` | No          | Ajustes de resiliencia por node. Consulta [Reintentos y circuit breaker](#reintentos-y-circuit-breaker).                                                                                                                                      |
| `request_format`                                   | No          | Cómo Flowker serializa el cuerpo de la solicitud: `json` (el valor por defecto), `xml_converted` o `xml_passthrough`. `xml_converted` además exige `root_element`.                                                                            |

Un node que llama a una operación de un documento OpenAPI subido la nombra con `operation_path` y `operation_method` en lugar de un `executorId`. Flowker rellena el `executorId` por ti a partir de la configuración de provider a la que apunta el node. [Conectar tu propia API](/es/flowker/connecting-your-own-api) recorre todo ese camino.

### Validar la configuración de un node antes de guardarlo

Llama al endpoint [Validar una configuración de node](/es/reference/flowker/validate-executor-config) (`POST /v1/catalog/executors/{id}/validate`) para comprobar la configuración de un node contra el JSON Schema del executor del catálogo.

Esto ejecuta **solo la validación de JSON Schema** — verifica que tu objeto de configuración corresponde a la estructura que el executor del catálogo espera (campos obligatorios, tipos, formatos). No llama al servicio externo, así que la primera ida y vuelta real ocurre cuando un workflow ejecuta el node.

Pasa `mappedTargets` para nombrar los campos que tu node aporta mediante un `inputMapping` en lugar de un valor fijo. Esos campos cuentan como satisfechos, así que un node que mapea un campo obligatorio desde el trigger valida antes de guardarlo.

## Mapeo de campos y transformación de datos

***

Cuando los datos del workflow no coinciden con el formato que espera un servicio externo — o cuando un servicio devuelve datos en una forma que el siguiente paso no puede consumir — usa mapeos de campos y transformaciones para cubrir esa brecha.

Los mapeos de campos y transformaciones se definen dentro del objeto `data` de los nodes executor. Flowker aplica los mapeos de entrada antes de llamar al servicio externo, y los mapeos de salida después de recibir la respuesta.

Un `target` de entrada es una ruta en el cuerpo de la solicitud saliente, escrita exactamente como el servicio externo la espera: no hay objeto envoltorio ni prefijo que añadir. Un `source` de salida es una ruta dentro del envelope de respuesta, así que los campos de la respuesta quedan bajo `body`.

<Accordion title="Ejemplo rápido — mapear campos del workflow a un node executor">
  ```json theme={null}
  {
    "id": "executor-balance",
    "type": "executor",
    "name": "Check Balance",
    "data": {
      "executorId": "http",
      "providerConfigId": "a1b2c3d4-e5f6-4789-a012-345678901234",
      "path": "/accounts/balance",
      "inputMapping": [
        { "source": "workflow.customerId", "target": "accountId" },
        { "source": "workflow.amount", "target": "minimumBalance" }
      ],
      "outputMapping": [
        { "source": "body.currentBalance", "target": "balance" },
        { "source": "body.accountStatus", "target": "status" }
      ]
    }
  }
  ```

  Los nodes siguientes leen la salida mapeada bajo el ID de este node: `${executor-balance.balance}`.
</Accordion>

Para integraciones complejas, también puedes adjuntar transformaciones a entradas individuales de mapeo (por ejemplo, quitar caracteres, añadir prefijos, cambiar el case) y definir operaciones Kazaam para transformaciones avanzadas de JSON a JSON.

[Trabajar con los datos de la solicitud y de la respuesta](/es/flowker/working-with-request-and-response-data) recorre todo el camino: declarar los mapeos, elegir qué arma el cuerpo de la solicitud, ajustar los valores en tránsito, leer la respuesta de vuelta y revisar la solicitud armada antes de llamar al servicio.

## Paso 4: Ejecutar el workflow

***

Referencia la configuración de provider en un node de workflow de tipo `executor`.

El ejemplo a continuación crea un workflow de validación de pagos sobre la conexión FraudShield del [Paso 2](#paso-2-crear-una-configuración-de-provider). Cuando llega un pago, Flowker llama al servicio de verificación de fraude, evalúa el score de riesgo y aprueba o rechaza el pago según el resultado.

El workflow tiene cinco nodes: un **trigger** webhook que recibe el pago, un node **executor** que llama al servicio de verificación de fraude, un node **conditional** que evalúa el score, y dos nodes **action** para los resultados de aprobación y rechazo. Los edges los conectan en secuencia, con el node condicional bifurcando hacia uno u otro camino según el umbral del score.

Usa el endpoint [Crear workflow](/es/reference/flowker/create-workflow) para definir el workflow, luego [Actívalo](/es/reference/flowker/activate-workflow) y finalmente [Ejecútalo](/es/reference/flowker/execute-workflow).

<AccordionGroup>
  <Accordion title="Ejemplo — Crear un workflow de validación de pagos">
    ```json theme={null}
    POST /v1/workflows

    {
      "name": "payment-validation",
      "description": "Valida un pago antes de procesarlo.",
      "nodes": [
        {
          "id": "trigger-payment",
          "type": "trigger",
          "name": "Payment received",
          "position": { "x": 0, "y": 0 },
          "data": {
            "triggerType": "webhook",
            "path": "payments/received",
            "method": "POST",
            "input_contract": "open",
            "format": "json"
          }
        },
        {
          "id": "check-fraud",
          "type": "executor",
          "name": "Fraud check",
          "position": { "x": 200, "y": 0 },
          "data": {
            "executorId": "http",
            "providerConfigId": "019c96a0-0ac0-7de9-9f53-9cf842a2ee5a",
            "path": "/score-transaction",
            "method": "POST"
          }
        },
        {
          "id": "evaluate-score",
          "type": "conditional",
          "name": "Score evaluation",
          "position": { "x": 400, "y": 0 },
          "data": {
            "condition": "check-fraud.body.score < 80"
          }
        },
        {
          "id": "approve",
          "type": "action",
          "name": "Approve payment",
          "position": { "x": 600, "y": -100 },
          "data": {
            "actionType": "set_output",
            "output": { "decision": "approved" }
          }
        },
        {
          "id": "reject",
          "type": "action",
          "name": "Reject payment",
          "position": { "x": 600, "y": 100 },
          "data": {
            "actionType": "set_output",
            "output": { "decision": "rejected" }
          }
        }
      ],
      "edges": [
        { "id": "e1", "source": "trigger-payment", "target": "check-fraud" },
        { "id": "e2", "source": "check-fraud", "target": "evaluate-score" },
        { "id": "e3", "source": "evaluate-score", "target": "approve", "sourceHandle": "true" },
        { "id": "e4", "source": "evaluate-score", "target": "reject", "sourceHandle": "false" }
      ]
    }
    ```

    El node `check-fraud` nombra `http` — el conector HTTP genérico del catálogo — y la configuración FraudShield creada en el Paso 2, que contiene la URL base y las credenciales. Ambos lados nombran el mismo provider, así que el workflow se guarda. Flowker envía la solicitud a `https://api.fraudshield.example.com/score-transaction`.

    El node no declara ningún `outputMapping`, así que su salida conserva la forma del envelope de respuesta. Por eso el score está en `check-fraud.body.score`, que es lo que lee la condición de `evaluate-score`. Añade un `outputMapping` cuando prefieras un nombre más plano — consulta [Mapeo de campos y transformación de datos](#mapeo-de-campos-y-transformación-de-datos).
  </Accordion>

  <Accordion title="Ejemplo — Ejecutar el workflow">
    ```json theme={null}
    POST /v1/workflows/{workflowId}/executions
    Idempotency-Key: {unique-uuid}

    {
      "inputData": {
        "transactionId": "txn-98765",
        "amount": 1500.00,
        "currency": "BRL",
        "customerId": "cust-12345"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Disparar workflows

***

Las ejecuciones de workflows se disparan a través del endpoint [Ejecutar workflow](/es/reference/flowker/execute-workflow):

```
POST /v1/workflows/:workflowId/executions
```

El cuerpo de la solicitud contiene el `inputData` de la ejecución. Todos los campos están disponibles para los nodes siguientes a través del namespace `workflow` — por ejemplo, `workflow.transactionId` o `workflow.amount`. Las salidas de los nodes están disponibles a través del ID del node — por ejemplo, `check-fraud.body.score` para un node que no declara ningún `outputMapping`.

### Idempotencia

Cada solicitud de ejecución debe incluir un header `Idempotency-Key`. Las solicitudes sin él se rechazan con `400 Bad Request` (error `FLK-0509`). Genera un UUID nuevo para cada ejecución, y reutiliza la misma clave solo cuando reintentes la solicitud idéntica.

## Triggers de webhook

***

Los webhooks son la forma principal en que los sistemas externos disparan workflows de Flowker. En lugar de que tu sistema llame directamente a la API de ejecuciones, registras un path de webhook en un workflow y los servicios externos envían solicitudes HTTP a ese path.

### Cómo funciona

1. Agrega un node trigger de tipo `webhook` a tu workflow con un `path`, un `method` y un `input_contract` en su `data`.
2. Cuando el workflow se activa, Flowker registra el path en su registro de webhooks.
3. Los sistemas externos envían solicitudes a [`POST /v1/webhooks/{path}`](/es/reference/flowker/trigger-webhook) (o el método que configuraste).
4. Flowker resuelve el path al workflow correspondiente y lo ejecuta.

### Definir un node trigger de webhook

El trigger de webhook es un node con `type: "trigger"` y `triggerType: "webhook"` en su `data`, más un `path`, un `method` y un `input_contract`. [Configurar un trigger de webhook](/es/flowker/configuring-a-webhook-trigger) cubre cada campo, los tres modos de `input_contract` y lo que exige cada uno, y trae un node de ejemplo para cada modo.

La configuración del trigger es un contrato cerrado. Guardar un workflow cuyo trigger de webhook omite `path`, `method` o `input_contract`, olvida un campo que su modo `input_contract` exige, nombra el id de esquema o un campo de operación de otro modo, o lleva una clave o un valor que el esquema no acepta falla con `FLK-0934`. El esquema también declara los campos opcionales `response_mode` y `response_view` — consulta [Modo de respuesta síncrona](#modo-de-respuesta-síncrona).

### Proteger un webhook

La entrega de webhooks usa la misma autenticación que el resto de la API. Con Access Manager habilitado (`PLUGIN_AUTH_ENABLED=true`), cada solicitud a `/v1/webhooks/*` debe llevar un token Bearer (JWT OIDC), y quien llama debe tener el permiso `execute` sobre el recurso `webhooks`. Las solicitudes sin un token válido se rechazan con `401 Unauthorized`.

Otorga ese permiso a una identidad máquina-a-máquina para cada sistema al que permitas llamar a tus webhooks, y gestiona la concesión en Access Manager. Esto mantiene el acceso a webhooks bajo el mismo modelo de roles y políticas que la gestión de workflows, en lugar de una credencial adjunta al path.

### Metadatos del webhook

Flowker inyecta automáticamente un objeto `_webhook` en el `inputData` de la ejecución con metadatos sobre la solicitud entrante:

| Campo                | Descripción                                                                                                                                                                                                                                                   |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `_webhook.method`    | Método HTTP usado (p. ej., `POST`).                                                                                                                                                                                                                           |
| `_webhook.path`      | El path de webhook resuelto.                                                                                                                                                                                                                                  |
| `_webhook.headers`   | Headers de la solicitud, filtrados por una lista segura (`Content-Type`, `Accept`, `User-Agent`, `X-Request-Id`, `X-Forwarded-For`, `Idempotency-Key`). Todos los demás headers se descartan.                                                                 |
| `_webhook.query`     | Conserva los nombres de los parámetros de consulta recibidos. Conserva los valores solo de `customerId`, `page`, `cursor`, `limit`, `offset` y `sortOrder` (sin distinguir mayúsculas de minúsculas); todos los demás valores se almacenan como `[redacted]`. |
| `_webhook.remote_ip` | Dirección IP de quien llama.                                                                                                                                                                                                                                  |

Estos metadatos están disponibles para todos los nodes del workflow a través del namespace `workflow._webhook`.

### Notas importantes

* Cada combinación de path + método de webhook solo puede ser registrada por un workflow activo. Activar un segundo workflow con el mismo path falla con un error de conflicto.
* Los paths de webhook admiten segmentos anidados (p. ej., `payments/stripe/received`).
* El tamaño máximo del cuerpo de la solicitud es 1 MB.
* Desactivar un workflow desregistra automáticamente sus rutas de webhook.

Consulta la referencia de API [Disparar un webhook](/es/reference/flowker/trigger-webhook) para la documentación completa del endpoint.

### Modo de respuesta síncrona

Por defecto, un trigger de webhook responde con un recibo `202` en cuanto la ejecución arranca (el modo async) — quien llama debe consultar el estado de la ejecución por separado. Define `response_mode` como `"sync"` en el `data` del node trigger para que Flowker mantenga la conexión HTTP abierta y devuelva el resultado de la ejecución directamente en la respuesta:

| Campo           | Tipo   | Obligatorio | Descripción                                                                                                                                                                                                       |
| --------------- | ------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `response_mode` | string | No          | `"async"` (por defecto) devuelve un recibo `202` de inmediato. `"sync"` bloquea (hasta un límite interno) hasta que la ejecución alcanza un estado terminal y devuelve el resultado en el cuerpo de la respuesta. |
| `response_view` | string | No          | Da forma al cuerpo de la respuesta sync. Solo tiene sentido cuando `response_mode` es `"sync"`. Consulta la tabla siguiente. Por defecto, `"full"`.                                                               |

Si la ejecución no alcanza un estado terminal antes de que expire el límite interno de espera, Flowker recae en el mismo recibo `202` (con un header `Location` apuntando al endpoint de resultados) que habría devuelto el modo async.

`response_view` selecciona la forma del cuerpo de la respuesta sync:

| Valor                | Descripción                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `full` (por defecto) | El volcado completo de la ejecución — `executionId`, `workflowId`, `status`, `stepResults`, `finalOutput` — la misma forma que obtendrías del endpoint de resultados de ejecución.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `final_output`       | Solo el mapa `finalOutput` de la ejecución, sin envoltorio.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `receipt`            | El recibo de ejecución reducido (`executionId`, `workflowId`, `status`, `startedAt`) — la misma forma que devuelve el camino async.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `passthrough`        | Da forma a la respuesta según el **tipo de node del paso terminal (el último ejecutado)**. Para un ejecutor terminal que capturó una respuesta del proveedor, devuelve el estado del proveedor (incluidos los `4xx`) y el `Content-Type`. Retransmite como máximo 8 KiB del cuerpo capturado; los cuerpos más largos se truncan. Los cuerpos JSON se decodifican y se serializan de nuevo antes de capturarse, por lo que no se garantiza una retransmisión byte a byte. Si el paso terminal es una acción `set_output` con una salida configurada, la respuesta es la salida de negocio de ese node, respetando su override `responseStatusCode`. Si no se cumple ninguno (sin respuesta del provider capturada — circuito abierto, timeout, fallo antes del envío — y sin salida terminal), recae en el envelope completo con HTTP `200` para que quien llama obtenga igualmente un resultado con sentido. |

El `finalOutput` de una ejecución fallida (en las vistas `full` o `final_output`) lleva siempre `status: "failed"` y `errorMessage`, y `errorClass` cuando Flowker pudo clasificar el fallo — nunca un `{}` vacío. Sin un override `responseStatusCode` (ver abajo), el estado HTTP sync se mantiene en `200` para `full`/`final_output`/`receipt` (informa de la salud del transporte, no del resultado de negocio). Un `responseStatusCode` válido en el node `set_output` terminal sobrescribe ese estado para esas tres vistas.

Un node action con `actionType: "set_output"` puede llevar un `responseStatusCode` opcional (entero, `200`–`599`) para sobrescribir el estado HTTP que devuelve una respuesta de webhook `sync`. Un valor fuera de rango o no entero se rechaza al guardar (`FLK-0122`). Para `passthrough`, el override se aplica solo cuando el propio node `set_output` es el paso terminal — el estado retransmitido de un executor terminal siempre gana, y el fallback sin respuesta siempre usa un `200` simple para que un override nunca enmascare un fallo.

La detección de passthrough es estricta: solo cuenta el paso terminal. Un `set_output` terminal después de un executor toma la forma de su propia salida — Flowker nunca retrocede a la respuesta de un executor anterior. En una ejecución fallida, el paso que detiene el flujo es el paso terminal, así que un `4xx` del provider que detuvo el workflow se retransmite como el `4xx` real.

Los valores en la salida de un node `set_output` admiten referencias `${...}` resueltas contra el contexto del workflow — incluyendo `${workflow.<campo>}` (payload del trigger), `${execution.id}`, `${execution.startedAt}` y `${execution.now}` (marcado en el momento de la interpolación). Una referencia `${...}` que no se pueda resolver hace fallar el paso (fail-closed).

## Manejo de errores

***

Si un node falla, la ejecución se detiene y se marca como `failed`.

No hay fallback automático. Después de agotar los reintentos, la ejecución falla.

Los resultados de ejecución informan el `status` de la ejecución y `stepResults`. Un paso fallido proporciona `stepNumber`, `nodeId`, `status` y `errorMessage`, con `statusCode` y `errorClass` cuando están disponibles; `output` es opcional. No garantices un `errorCode`, incluidos `FLK-0504` o `FLK-0507`, en cada payload de resultados de ejecución.

## Reintentos y circuit breaker

***

Flowker incluye resiliencia integrada para las llamadas de executor.

### Reintentos

Cuando una llamada de executor falla con un error transitorio — un error de red, un timeout en el intento, cualquier estado `5xx`, o los estados `408` o `429` — Flowker reintenta automáticamente. El comportamiento de reintento se configura por node, en el `data` del node executor:

| Ajuste                  | Por defecto                                | Límites                       | Descripción                                                                                                                    |
| ----------------------- | ------------------------------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `timeout_seconds`       | 30                                         | 1–300                         | Timeout por solicitud.                                                                                                         |
| `retry.max_attempts`    | 3 (1 para `POST` y `PATCH` sin configurar) | 1–10 aceptados; 1–5 efectivos | Acepta `1`–`10` en el esquema del node, pero Flowker limita la cantidad efectiva de intentos en tiempo de ejecución a `1`–`5`. |
| `retry.backoff_seconds` | 1                                          | 1–60                          | Techo del primer backoff; cada espera es un valor aleatorio entre cero y el techo, que se duplica por intento.                 |
| `success_status_codes`  | `[200, 201, 202, 204]`                     | 100–599                       | Códigos de estado HTTP tratados como éxito.                                                                                    |

Los reintentos solo aplican cuando la operación es segura de repetir. Por defecto, las llamadas `POST` y `PATCH` se tratan como no idempotentes y **no** se reintentan (un solo intento), mientras que `GET`, `PUT`, `DELETE` y otros verbos reintentan normalmente. Un `retry.max_attempts` mayor que `1` activa los reintentos en ese node sea cual sea el método. Un `retry.max_attempts` de `1` no es una activación — define un solo intento.

**Los errores no reintentables** se reducen a un solo intento sin importar la configuración: circuit breaker abierto, contexto cancelado, errores de configuración, fallos al resolver secretos, un cuerpo de solicitud por encima del tope de tamaño configurado, un cuerpo de respuesta del provider por encima del mismo tope, y respuestas `4xx` no transitorias del provider (cualquier `4xx` excepto `408` y `429`).

El reintento aplica por ejecución de node. Si todos los intentos fallan, el paso se marca como fallido y la ejecución se detiene.

### Circuit breaker

Flowker usa un circuit breaker para proteger a los servicios externos de ser saturados por llamadas fallidas repetidas:

| Parámetro               | Valor                                                                    |
| ----------------------- | ------------------------------------------------------------------------ |
| Umbral de fallos        | 20 fallos consecutivos abren el circuito (configurable en el despliegue) |
| Timeout de recuperación | 30 segundos antes de volver a intentar (estado half-open)                |
| Solicitudes half-open   | 1 solicitud permitida para probar si el servicio se recuperó             |

Los errores `4xx` de cliente/autenticación del provider **no** abren el circuito: son problema de quien llama, no una señal de que el provider esté caído. Solo los fallos de transporte y los `5xx` cuentan para el umbral.

Cuando el circuito está abierto, las llamadas de executor fallan de inmediato con `FLK-0507` en lugar de alcanzar el servicio externo. Esto evita fallos en cascada y da tiempo al servicio externo para recuperarse.

<Frame caption="Transiciones de estado del circuit breaker">
  <img src="https://mintcdn.com/lerian-49cb71fc/Mmb3JaVhlcaSV8yn/images/es/d2/flowker-circuit-breaker.svg?fit=max&auto=format&n=Mmb3JaVhlcaSV8yn&q=85&s=d0751673c6034526c43e334dfc337a91" alt="Estados del circuit breaker" width="1045" height="394" data-path="images/es/d2/flowker-circuit-breaker.svg" />
</Frame>

El circuito comienza en el estado **Closed**, donde todas las solicitudes pasan normalmente. Al alcanzar el umbral de fallos, transita a **Open**, bloqueando todas las solicitudes de inmediato. Después de 30 segundos, pasa a **Half-Open** y permite una solicitud de prueba. Si esa solicitud tiene éxito, el circuito vuelve a Closed. Si falla, el circuito se reabre por otro ciclo de 30 segundos.

<Warning>
  El circuit breaker opera por configuración de provider, acotado a tu tenant. Los fallos contra una conexión no afectan a otra, y un tenant no puede abrir el circuito de otro. Los umbrales del circuit breaker (número de fallos, timeout de recuperación) son valores por defecto globales configurados en el despliegue — no se pueden personalizar por conexión en esta versión.
</Warning>

## Registro de configuraciones de executor

***

Flowker mantiene un registro de configuraciones de executor. El registro expone cuatro operaciones:

| Operación  | Endpoint                                                                           |
| ---------- | ---------------------------------------------------------------------------------- |
| Listar     | [`GET /v1/executors`](/es/reference/flowker/list-executor-configurations)          |
| Obtener    | [`GET /v1/executors/{id}`](/es/reference/flowker/get-executor-configuration)       |
| Actualizar | [`PATCH /v1/executors/{id}`](/es/reference/flowker/update-executor-configuration)  |
| Eliminar   | [`DELETE /v1/executors/{id}`](/es/reference/flowker/delete-executor-configuration) |

Cada registro lleva un `status`, que la API informa en cada respuesta:

| Estado         | Descripción                                    |
| -------------- | ---------------------------------------------- |
| `unconfigured` | El registro aún no tiene detalles de conexión. |
| `configured`   | El registro lleva detalles de conexión.        |
| `tested`       | El registro fue verificado.                    |
| `active`       | El registro está en servicio.                  |
| `disabled`     | El registro está fuera de servicio.            |

`PATCH` acepta `name`, `baseUrl`, `endpoints` y `authentication`, más los opcionales `description` y `metadata`. No acepta `status`, pero la operación de listado acepta `status` como filtro de consulta. La actualización aplica a registros en estado `unconfigured` o `configured`; la eliminación aplica a registros en estado `unconfigured`, `configured` o `disabled`. Ninguna operación en esta versión mueve un registro a `tested`, `active` o `disabled`; la tabla lista esos valores porque las respuestas los informan y el filtro de listado los acepta.

## Qué sigue

***

<CardGroup cols={2}>
  <Card title="Conceptos fundamentales" icon="diagram-project" href="/es/flowker/flowker-concepts">
    Comprende workflows, nodes, edges y ejecuciones.
  </Card>

  <Card title="API de Configuraciones de provider" icon="code" href="/es/reference/flowker/list-provider-configurations">
    Explora la API de configuraciones de provider.
  </Card>
</CardGroup>
