> ## 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.

# Guia de integração

> Conecte serviços externos ao Flowker por configurações de provedor. Configure a autenticação, mapeie campos e rode workflows contra integrações reais.

O Flowker chama serviços externos (como motores de fraude, processadores de pagamento e provedores de KYC) por configurações de provedor. Uma configuração de provedor é a sua conexão com uma instância viva de um serviço externo.

Neste guia, você explora o catálogo, cria uma configuração de provedor e a referencia a partir de um nó de workflow. Depois você mapeia campos entre os seus dados e o serviço, e aprende como o Flowker repete e protege essas chamadas.

## Passo 1: Explore o catálogo

***

O catálogo é o registro dos provedores, executores de catálogo e gatilhos que vêm com o Flowker.

**1. Liste os provedores disponíveis**

Chame o endpoint [Listar provedores do catálogo](https://docs.lerian.studio/pt/reference/products/flowker/list-catalog-providers.md) para ver os tipos de serviço aos quais o Flowker se conecta. O catálogo sempre inclui o conector HTTP genérico. Provedores nativos como `ledger` (Midaz), `crm`, `fees`, `identity`, `tracer` e `pix-jd` são sintetizados a partir de especificações OpenAPI publicadas e só aparecem quando o schema registry nativo está configurado e a síntese tem sucesso.

**2. Liste os executores de catálogo disponíveis**

Chame o endpoint [Listar executores do catálogo](https://docs.lerian.studio/pt/reference/products/flowker/list-catalog-executors.md) para ver as operações que um nó de workflow pode invocar. Use [Listar executores por provedor](https://docs.lerian.studio/pt/reference/products/flowker/list-executors-by-provider.md) para estreitar a lista a um provedor.

**3. Liste os gatilhos disponíveis**

Chame o endpoint [Listar gatilhos do catálogo](https://docs.lerian.studio/pt/reference/products/flowker/list-catalog-triggers.md) para ver os tipos de gatilho nativos: webhooks e agendamentos. A API de executar workflow começa um workflow, mas não é um gatilho de catálogo.

**4. Escolha o que você precisa**

Anote o `providerId` e o id do executor de catálogo que combinam com a sua integração. Você usa o primeiro no [Passo 2](#step-2-create-a-provider-configuration) e o segundo no [Passo 3](#step-3-reference-the-provider-configuration-from-a-workflow-node).

> [!TIP]
>
> O catálogo mostra o que o Flowker pode chamar. As configurações de provedor guardam a URL base, as credenciais e as configurações de cada instância de serviço que você usa.

## Passo 2: Crie uma configuração de provedor

***

Chame [`POST /v1/provider-configurations`](https://docs.lerian.studio/pt/reference/products/flowker/create-provider-configuration) para definir a sua conexão com uma instância de um serviço externo.

| Campo | Obrigatório | Descrição |
| - | - | - |
| `name` | Sim | Um nome para esta conexão, de 1 a 100 caracteres. |
| `kind` | Não | Que tipo de conexão é esta. Omita-o, ou envie `catalog`, para uma conexão com um provedor de catálogo (o caso que este guia cobre). Envie `external_openapi` para uma conexão com um documento OpenAPI que você subiu; veja [Como conectar sua própria API](https://docs.lerian.studio/pt/products/flowker/connecting-your-own-api.md). Você escolhe o tipo quando cria a configuração. |
| `providerId` | Para `catalog` | O provedor de catálogo do qual esta conexão é uma instância, como `ledger` ou `http`. Uma configuração do tipo `external_openapi` pode omiti-lo, e uma leitura dela devolve o id reservado `external.openapi`. |
| `config` | Sim | Os detalhes de conexão daquela instância, como a URL base e as credenciais de autenticação. O Flowker valida este mapa contra o JSON Schema do provedor vindo do catálogo e devolve `422` quando ele não combina. |
| `allowedHosts` | Para `http` | Os hosts públicos que esta configuração pode chamar. O conector HTTP genérico (`providerId: "http"`) exige pelo menos uma entrada, e uma lista vazia é rejeitada com `FLK-0323`. Provedores nativos aceitam uma lista vazia. Uma entrada com ponto inicial combina com subdomínios: `.kyc-provider.io` combina com `api.kyc-provider.io`. Apenas nomes de host: sem IPs literais, curingas ou portas. O host em `config.base_url` deve estar coberto pela lista, senão a criação é rejeitada com `FLK-0320`. |
| `allowedPrivateHosts` | Não | Hosts privados nomeados que a Lerian permite que esta configuração alcance. Você não pode defini-la: uma requisição do seu tenant que define uma lista não vazia responde `FLK-0317`. Os endereços de metadados de nuvem e de link-local continuam bloqueados. |
| `protected` | Não | `true` torna a configuração exclusiva de pessoas. Você a define só na criação. Veja [Quem pode executar e alterar um workflow](#who-may-run-and-change-a-workflow). |
| `schemaBindings` | Não | Os esquemas XSD ou OpenAPI vinculados a esta configuração, cada um com uma restrição opcional a operações OpenAPI específicas. |
| `description` | Não | Texto livre, de até 500 caracteres. |
| `metadata` | Não | Seus próprios pares de chave e valor. |

> [!NOTE]
>
> Um `providerId` é um identificador de catálogo, e nem sempre combina com o nome do produto. O catálogo registra o Midaz como `ledger`. Pegue sempre o valor em [Listar provedores do catálogo](https://docs.lerian.studio/pt/reference/products/flowker/list-catalog-providers.md) em vez de adivinhá-lo pelo nome do produto.

> [!WARNING]
>
> O `providerId` na configuração e o `executorId` no nó que a usa devem pertencer ao mesmo provedor de catálogo. O conector HTTP genérico usa `http` nos dois. O Flowker rejeita um workflow que junta uma configuração de um provedor com um executor de outro, com `FLK-0151`.

O exemplo abaixo monta a conexão que este guia usa daqui em diante: um serviço de pontuação de fraude alcançado pelo conector HTTP genérico.

> [accordion] Exemplo de requisição
>
> ```json theme={null}
> POST /v1/provider-configurations
>
> {
>   "name": "FraudShield Production",
>   "description": "Production fraud scoring service",
>   "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"
>   }
> }
> ```
>
> A resposta devolve o `id` da nova configuração. Guarde-o. O [Passo 3](#step-3-reference-the-provider-configuration-from-a-workflow-node) e o [Passo 4](#step-4-run-the-workflow) o colocam no `providerConfigId` do nó que chama o serviço.

### Autenticação

O bloco `config.auth` guarda a autenticação que o serviço externo exige, como um par `{ type, config }`. Use o método que o seu serviço espera.

| Tipo | Descrição | Campos de config |
| - | - | - |
| `none` | Sem autenticação. | — |
| `api_key` | API key no header ou na query. | `key`, `header_name`, `location`, `query_param_name`, `prefix` |
| `bearer` | Bearer token no header Authorization. | `token` |
| `basic` | Username e senha (Base64). | `username`, `password` |
| `oidc_client_credentials` | Fluxo OAuth 2.0 de client credentials com gestão automática de token. | `issuer_url`, `client_id`, `client_secret`, `scopes` |
| `oidc_user` | Fluxo OAuth 2.0 de senha do dono do recurso. | `issuer_url`, `client_id`, `username`, `password`, `client_secret`, `scopes` |
| `oauth2_token_endpoint` | Client credentials OAuth 2.0 contra um token endpoint (sem descoberta OIDC). | `token_url`, `client_id`, `client_secret`, `scopes` |
| `hmac` | Assina cada requisição com um secret HMAC compartilhado. | `secret`, `algorithm`, `encoding`, `header_name`, `signature_prefix`, `signing_string`, `timestamp_header` |
| `lerian_token_endpoint` | Client ID e secret de uma aplicação que você cria, para os provedores Midaz ledger, CRM, Fees, Identity e Pix JD. | `client_id`, `client_secret` |

Uma leitura nunca retorna a credencial que o tipo de autenticação declara. Guarde credenciais apenas nos campos que o tipo de autenticação declara.

Os provedores `ledger`, `crm`, `fees`, `identity` e `pix-jd` chamam os seus próprios produtos Lerian com uma aplicação que você cria. O `config` deles guarda só `organization_id`, `ledger_id` e um bloco `auth` do tipo `lerian_token_endpoint` com o `client_id` e o `client_secret` dessa aplicação. Sem o bloco, criar e atualizar respondem `FLK-0948`, e uma execução em uma configuração sem ele falha o nó com `FLK-0948`. Qualquer outra chave em `config` responde `FLK-0293`. O host vem do deployment, então um `base_url` em `config` é ignorado. Para alterar uma configuração existente, envie uma atualização cujo `config` guarde `organization_id`, `ledger_id` e o bloco `auth`, porque `config` substitui o mapa guardado. A configuração mantém o ID dela, então os workflows que a nomeiam não precisam de edição.

Para trocar um secret, envie o novo valor em uma atualização. Para manter o atual, omita o campo ou envie-o em branco. Isso vale enquanto `auth.type` continuar o mesmo e a atualização deixar `base_url`, `auth.config.token_url`, `auth.config.issuer_url`, `openapi_schema_id` e `allowedHosts` como estão. Uma atualização que muda um deles em uma configuração que guarda um secret precisa levar de novo todos os valores de secret. Caso contrário, o Flowker a rejeita com `FLK-0962` e não grava nada. Uma atualização que muda `auth.type` precisa levar um valor para cada secret que o novo tipo exige e o anterior não exigia. Caso contrário, o Flowker a rejeita com `FLK-0952`. Uma troca entre dois tipos que usam o mesmo secret, como `oidc_user` para `oidc_client_credentials`, não precisa desse valor de novo.

> [!TIP]
>
> Para integrações OAuth 2.0, use `oidc_client_credentials`. O Flowker cuida da obtenção e da renovação de token automaticamente.

> [accordion] Exemplo: client credentials OIDC
>
> ```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"]
>     }
>   }
> }
> ```

### Como habilitar e desabilitar

Configurações de provedor têm dois status: `active` (em uso) e `disabled` (temporariamente fora). Uma nova configuração de provedor começa no status `active`. Use [Desabilitar configuração de provedor](https://docs.lerian.studio/pt/reference/products/flowker/disable-provider-configuration.md) para tirar uma conexão de serviço e [Habilitar configuração de provedor](https://docs.lerian.studio/pt/reference/products/flowker/enable-provider-configuration.md) para trazê-la de volta.

Veja a [API de configurações de provedor](https://docs.lerian.studio/pt/reference/products/flowker/list-provider-configurations.md) para a referência completa.

## Passo 3: Referencie a configuração de provedor a partir de um nó de workflow

***

Cada nó executor carrega um `providerConfigId`, o identificador da configuração de provedor pela qual ele chama. O Flowker rejeita um workflow cujo nó executor não tem `providerConfigId`, e rejeita um valor que não é um UUID. Em tempo de execução, ele monta cada requisição de saída com a URL base daquela configuração de provedor mais o caminho no nó. O nó falha se a configuração de provedor não estiver `active`.

Estes são os campos que um nó executor define no seu objeto `data` quando chama pelo conector HTTP genérico:

| Campo | Obrigatório | Descrição |
| - | - | - |
| `executorId` | Sim | O executor de catálogo que este nó invoca, tirado do [Passo 1](#step-1-explore-the-catalog). O Flowker rejeita o workflow quando o id não está no catálogo. Um nó que chama um documento OpenAPI que você subiu o omite (veja abaixo). |
| `providerConfigId` | Sim | O UUID da configuração de provedor pela qual este nó chama. |
| `path` | Não | O caminho da requisição anexado à URL base da configuração de provedor. O host de destino é sempre aquela URL base. Um nó não pode informar uma URL absoluta. |
| `endpointName` | Não | Usado como caminho da requisição quando o nó não define `path`. Um nó que carrega os dois envia `path`. |
| `method` | Não | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD` ou `OPTIONS`. O padrão é `POST`. |
| `headers` | Não | Headers da requisição, mesclados sobre os que a configuração de provedor define. Um header do nó vence um header de mesmo nome da configuração de provedor. |
| `query` | Não | Parâmetros de query anexados à URL. |
| `auth` | Não | Um bloco de autenticação `{type, config}` para este nó, no mesmo formato que a configuração de provedor usa. Quando presente, ele tem precedência sobre a autenticação na configuração de provedor. |
| `body` | Não | Um corpo de requisição explícito, resolvido contra o contexto do workflow. Quando definido, ele é a única fonte de corpo. Os mapeamentos de campo não se aplicam a ele. |
| `content_digest` | Não | Uma trava SHA-256 para o corpo montado da requisição. Defina um digest hexadecimal de 64 caracteres, ou um valor resolvido a partir do contexto do workflow. O Flowker faz o hash dos bytes finais depois de montar o corpo e envia a requisição apenas quando eles combinam. |
| `config` | Não | Valores literais fixos que alimentam o corpo da requisição. Veja [Mapeamento de campos e transformação de dados](#field-mapping-and-data-transformation). |
| `inputMapping`, `outputMapping`, `transforms` | Não | Mapeamentos de campo e transformações. Veja [Mapeamento de campos e transformação de dados](#field-mapping-and-data-transformation). |
| `timeout_seconds`, `retry`, `success_status_codes` | Não | Configurações de resiliência por nó. Veja [Novas tentativas e circuit breaker](#retry-and-circuit-breaker). |
| `request_format` | Não | Um objeto cujo `type` define como o Flowker serializa o corpo da requisição: `json` (o padrão), `xml_converted` ou `xml_passthrough`. `xml_converted` também exige `root_element`. |

Um nó que chama uma operação de um documento OpenAPI que você subiu a nomeia com `operation_path` e `operation_method` em vez de um `executorId`. O Flowker preenche o `executorId` para você a partir da configuração de provedor para a qual o nó aponta. [Como conectar sua própria API](https://docs.lerian.studio/pt/products/flowker/connecting-your-own-api.md) percorre esse caminho inteiro.

### Valide a configuração de um nó antes de salvar

Chame o endpoint [Validar a configuração de um nó](https://docs.lerian.studio/pt/reference/products/flowker/validate-executor-config.md) (`POST /v1/catalog/executors/{id}/validate`) para conferir a configuração de um nó contra o JSON Schema do executor de catálogo.

Isso faz **apenas a validação de JSON Schema**. Confere se o seu objeto de configuração combina com a estrutura que o executor de catálogo espera (campos obrigatórios, tipos, formatos). Não chama o serviço externo, então a primeira ida e volta real acontece quando um workflow roda o nó.

Passe `mappedTargets` para nomear os campos que o seu nó fornece por um `inputMapping` em vez de um valor fixo. Esses campos contam como satisfeitos, então um nó que mapeia um campo obrigatório vindo do gatilho valida antes de você salvá-lo.

## Mapeamento de campos e transformação de dados

***

Use mapeamentos de campo e transformações quando os dados do workflow não combinam com o formato que um serviço externo espera. Use-os também quando um serviço devolve dados em um formato que a próxima etapa não consome.

Você define os mapeamentos de campo e as transformações dentro do objeto `data` dos nós executores. O Flowker aplica os mapeamentos de entrada antes de chamar o serviço externo, e os mapeamentos de saída depois de receber a resposta.

Um `target` de entrada é um caminho no corpo da requisição de saída, escrito exatamente como o serviço externo espera. Não há objeto envolvente nem prefixo a acrescentar. Um `source` de saída é um caminho dentro do envelope da resposta, então os campos da resposta ficam sob `body`.

> [accordion] Exemplo rápido: mapear campos de workflow para um nó 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" }
>     ]
>   }
> }
> ```
>
> Os nós seguintes leem a saída mapeada sob o ID deste nó: `${executor-balance.balance}`.

Para integrações complexas, você também pode anexar transformações a entradas individuais de mapeamento (por exemplo, remover caracteres, adicionar prefixos, mudar a caixa). Você pode definir operações Kazaam para transformações avançadas de JSON para JSON.

[Trabalhar com dados de requisição e de resposta](https://docs.lerian.studio/pt/products/flowker/working-with-request-and-response-data.md) percorre o caminho inteiro. Cobre como declarar os mapeamentos, escolher o que monta o corpo da requisição e remodelar valores em trânsito. Cobre também como ler a resposta de volta e conferir a requisição montada antes de chamar o serviço.

## Passo 4: Rode o workflow

***

Referencie a configuração de provedor em um nó de workflow do tipo `executor`.

O exemplo abaixo cria um workflow de validação de pagamento em cima da conexão FraudShield do [Passo 2](#step-2-create-a-provider-configuration). Quando um pagamento chega, o Flowker chama o serviço de checagem de fraude, avalia a pontuação de risco e aprova ou rejeita o pagamento conforme o resultado.

O workflow tem cinco nós. Um **gatilho** de webhook recebe o pagamento, e um nó **executor** chama o serviço de checagem de fraude. Um nó **condicional** avalia a pontuação, e há dois nós de **ação** para os resultados de aprovar e rejeitar. Arestas os conectam em sequência, com o nó condicional ramificando para um caminho ou outro conforme o limiar da pontuação.

Use o endpoint [Criar workflow](https://docs.lerian.studio/pt/reference/products/flowker/create-workflow.md) para definir o workflow, depois [Ative](https://docs.lerian.studio/pt/reference/products/flowker/activate-workflow.md) e por fim [Execute](https://docs.lerian.studio/pt/reference/products/flowker/execute-workflow.md).

> [accordion] Exemplo: criar um workflow de validação de pagamento
>
> ```json theme={null}
> POST /v1/workflows
>
> {
>   "name": "payment-validation",
>   "description": "Validates a payment before processing.",
>   "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",
>         "inputMapping": [
>           { "source": "workflow.transactionId", "target": "transactionId" },
>           { "source": "workflow.amount", "target": "amount" }
>         ]
>       }
>     },
>     {
>       "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" }
>   ]
> }
> ```
>
> O nó `check-fraud` nomeia `http`, o conector HTTP genérico do catálogo. Ele também nomeia a configuração FraudShield do Passo 2, que guarda a URL base e as credenciais. Os dois lados nomeiam o mesmo provedor, então o workflow salva. O Flowker envia a requisição para `https://api.fraudshield.example.com/score-transaction`.
>
> O nó não declara `outputMapping`, então a saída dele mantém o formato do envelope da resposta. A pontuação fica então em `check-fraud.body.score`, que é o que a condição `evaluate-score` lê. Adicione um `outputMapping` quando você preferir um nome mais raso. Veja [Mapeamento de campos e transformação de dados](#field-mapping-and-data-transformation).

> [accordion] Exemplo: executar o 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"
>   }
> }
> ```

## Como disparar workflows

***

Você dispara execuções de workflow pelo endpoint [Executar workflow](https://docs.lerian.studio/pt/reference/products/flowker/execute-workflow.md):

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

O corpo da requisição contém o `inputData` da execução. Todos os campos ficam disponíveis para os nós seguintes pelo namespace `workflow` (por exemplo, `workflow.transactionId` ou `workflow.amount`). As saídas dos nós ficam disponíveis pelo ID do nó (por exemplo, `check-fraud.body.score` para um nó que não declara `outputMapping`).

### Idempotência

Toda requisição Execute workflow precisa incluir um header `Idempotency-Key`. Uma requisição sem ele falha com `400 Bad Request` (erro `FLK-0509`). Gere um UUID novo para cada nova execução e reutilize a mesma chave só ao repetir a requisição idêntica. Uma nova tentativa no mesmo workflow devolve a primeira execução enquanto ela existir: o Flowker pode apagar uma execução finalizada só de leitura depois da [janela de retenção](https://docs.lerian.studio/pt/reference/products/flowker/get-execution-retention.md), e a mesma chave então inicia uma nova execução. Uma chave que você já usou em um workflow diferente responde `409` com `FLK-0511` e não devolve nada dessa execução.

Um workflow com vários triggers começa no trigger indicado por `triggerNodeId` no corpo da requisição. Sem ele, ou com um nó que não é um dos triggers do workflow, a chamada responde `422` com `FLK-0515`. Um workflow com um só trigger não precisa de nome. Uma rota de webhook ou um trigger de agendamento inicia a execução no próprio nó de trigger.

## Gatilhos de webhook

***

Webhooks são a principal forma de sistemas externos dispararem workflows do Flowker. Em vez de o seu sistema chamar a API de execuções diretamente, você registra um caminho de webhook em um workflow. Os serviços externos então enviam requisições HTTP para esse caminho.

### Como funciona

1. Adicione um nó de gatilho do tipo `webhook` ao seu workflow com um `path` e um `method` no seu `data`. Defina `input_contract` explicitamente em nós novos quando você precisa de validação `open`, `xsd` ou `openapi`.
2. Quando você ativa o workflow, o Flowker registra o caminho no seu registro de webhooks.
3. Sistemas externos enviam requisições para [`POST /v1/webhooks/{path}`](https://docs.lerian.studio/pt/reference/products/flowker/trigger-webhook) (ou o método que você configurou).
4. O Flowker resolve o caminho para o workflow correspondente e o executa.

### Como definir um nó de gatilho de webhook

O gatilho de webhook é um nó com `type: "trigger"` e `triggerType: "webhook"` no seu `data`, mais um `path`, um `method` e um `input_contract` opcional. [Como configurar um gatilho de webhook](https://docs.lerian.studio/pt/products/flowker/configuring-a-webhook-trigger.md) cobre cada campo, os três modos de `input_contract` e o que cada um exige, e traz um nó resolvido para cada modo.

A configuração do gatilho segue um contrato fechado. Salvar um workflow falha com `FLK-0934` quando o gatilho de webhook dele omite `path` ou `method`, ou deixa de fora um campo que o modo de `input_contract` escolhido exige. Também falha quando o gatilho nomeia o id de schema ou o campo de operação de outro modo. Falha também quando o gatilho carrega uma chave ou um valor que o schema não aceita. Um nome em `accepted_headers` que não é um nome de header válido, repete outro nome ou está na lista de bloqueio falha com `FLK-0957`.

O schema também declara os campos opcionais `response_mode`, `response_view` e `accepted_headers`. Veja [Como configurar um gatilho de webhook](https://docs.lerian.studio/pt/products/flowker/configuring-a-webhook-trigger.md).

### Como proteger um webhook

Com `PLUGIN_AUTH_ENABLED=true`, as requisições a `/v1/webhooks/*` exigem um token Bearer e a permissão `execute` no recurso `webhooks`. Os deployments em produção exigem a autenticação do plugin.

Conceda essa permissão a uma identidade máquina a máquina para cada sistema que você deixa chamar os seus webhooks, e gerencie a concessão no Access Manager. Isso mantém o acesso ao webhook sob o mesmo modelo de papéis e políticas da gestão de workflows, em vez de uma credencial presa ao caminho.

### Quem pode executar e alterar um workflow

Um workflow que move dinheiro não deve ficar aberto a todo sistema que alcança o webhook dele. Duas configurações o restringem.

**`allowedCallers` restringe quem executa o workflow.** É uma lista de até 50 chamadores, cada um `{"kind": "application", "id": "<client ID>"}` ou `{"kind": "user", "id": "<user ID>"}`. Uma lista vazia deixa qualquer chamador com a permissão `execute` executá-lo. Com lista, um chamador fora dela que solicita uma nova execução recebe `403 FLK-0519`, e nenhuma execução é criada. Uma lista inválida responde `422 FLK-0194`. Na atualização, uma requisição que omite o campo mantém a lista, e `[]` a limpa. Um gatilho de agendamento e um gatilho do Streaming Hub não trazem chamador, então nunca executam um workflow que tem lista. Só uma pessoa escreve a lista, e uma aplicação que envia o campo recebe `403 FLK-0365`. Para mudar a lista de um workflow ativo, desative-o, mova-o para rascunho, edite-o e ative-o de novo. Enquanto ele está desativado, os chamadores recebem recusa.

**Uma configuração de provedor protegida restringe quem a altera.** Envie `protected: true` ao criar a configuração. Não dá para defini-lo depois. Só uma pessoa pode criar, atualizar, habilitar, desabilitar ou excluir uma configuração protegida. Uma aplicação que tenta recebe `403 FLK-0365`.

Uma etapa em uma configuração de provedor que foi excluída tem o mesmo efeito que uma etapa em uma configuração protegida: só uma pessoa pode atualizar, clonar, mover para rascunho, ativar, desativar ou excluir esse workflow.

Um workflow com um passo em um provedor protegido também é protegido:

* Só uma pessoa pode criá-lo, atualizá-lo, cloná-lo, movê-lo para rascunho, ativá-lo, desativá-lo ou excluí-lo. Uma aplicação recebe `403 FLK-0365`.
* Ativá-lo com `allowedCallers` vazio responde `422 FLK-0366`.
* Ele usa só provedores protegidos. Misturá-los com não protegidos responde `422 FLK-0367`.

### Metadados do webhook

O Flowker injeta automaticamente um objeto `_webhook` no `inputData` da execução com metadados sobre a requisição que chegou:

| Campo | Descrição |
| - | - |
| `_webhook.method` | Método HTTP usado (por exemplo, `POST`). |
| `_webhook.path` | O caminho da requisição depois do prefixo de rota que recebeu a chamada (`/v1/webhooks/`, ou `/v1/hub/webhooks/` para o ingresso do Streaming Hub), como recebido. |
| `_webhook.headers` | Headers da requisição, filtrados por uma lista de permissão segura (`Content-Type`, `Accept`, `User-Agent`, `X-Request-Id`, `X-Forwarded-For`, `Idempotency-Key`) mais os `accepted_headers` opcionais deste gatilho e, para uma rota `openapi`, os parâmetros de header da operação dela. A lista de bloqueio fixa barra `Authorization`, `Proxy-Authorization`, `Cookie`, `Set-Cookie`, `X-API-Key`, `X-Auth-Token` e `X-Webhook-Signature`. Outros headers admitidos são persistidos literalmente; nunca admita nomes que carregam secrets, como `X-Amz-Security-Token`. |
| `_webhook.query` | Preserva os nomes dos parâmetros de query recebidos. Preserva os valores apenas de `customerId`, `page`, `cursor`, `limit`, `offset` e `sortOrder` (sem diferenciar maiúsculas); todo outro valor é guardado como `[redacted]`. |
| `_webhook.remote_ip` | Endereço IP de quem chamou. |

Esses metadados ficam disponíveis para todos os nós do workflow pelo namespace `workflow._webhook`.

### Regras de caminho e tamanho do corpo

* Ativar um workflow cujo caminho e método de webhook outro workflow ativo já ocupa falha com `FLK-0360`.
* Caminhos de webhook aceitam segmentos aninhados (por exemplo, `payments/stripe/received`).
* O tamanho máximo do corpo da requisição é 1 MB.

Veja a referência da API [Disparar um webhook](https://docs.lerian.studio/pt/reference/products/flowker/trigger-webhook.md) para a documentação completa do endpoint.

### Modo de resposta síncrona

Por padrão, um gatilho de webhook responde com um recibo `202` assim que a execução começa (o modo assíncrono). Quem chama deve consultar o status da execução em separado. Defina `response_mode` como `"sync"` no `data` do nó de gatilho para que o Flowker mantenha a conexão HTTP aberta e devolva o resultado da execução direto na resposta:

| Campo | Tipo | Obrigatório | Descrição |
| - | - | - | - |
| `response_mode` | string | Não | `"async"` (o padrão) devolve um recibo `202` na hora. `"sync"` bloqueia (até um limite interno) até a execução chegar a um estado terminal e devolve o resultado no corpo da resposta. |
| `response_view` | string | Não | Dá forma ao corpo da resposta síncrona. Faz sentido apenas quando `response_mode` é `"sync"`. Veja a tabela abaixo. O padrão é `"full"`. |

Se a execução não chega a um estado terminal antes de o limite interno de espera se esgotar, o Flowker recorre ao recibo `202` do modo assíncrono, exceto na view `passthrough`, onde responde `504` com o envelope e a execução continua. Uma execução parada numa espera mantém o `202`. Esse recibo carrega um header `Location` apontando para o endpoint de resultados.

`response_view` escolhe o formato do corpo da resposta síncrona:

| Valor | Descrição |
| - | - |
| `full` (o padrão) | O dump completo da execução (`executionId`, `workflowId`, `status`, `stepResults`, `finalOutput`), no mesmo formato que você buscaria no endpoint de resultados da execução. |
| `final_output` | Apenas o mapa `finalOutput` da execução, sem envelope em volta. |
| `receipt` | O recibo enxuto da execução (`executionId`, `workflowId`, `status`, `startedAt`), no mesmo formato que o caminho assíncrono devolve. |
| `passthrough` | Dá forma à resposta pelo tipo de nó da etapa terminal (a última executada). Para um executor terminal que capturou uma resposta de provedor, devolve o status do provedor (inclusive `4xx`) e o `Content-Type`. Repassa no máximo 8 KiB do corpo capturado; corpos maiores são truncados. Corpos JSON são decodificados e reserializados antes da captura, então o repasse byte a byte não é garantido. Se a etapa terminal é uma ação `set_output` com uma saída configurada, a resposta é a saída de negócio daquele nó, respeitando o override de `responseStatusCode` dele. Quando a execução falhou e a última etapa não capturou resposta de provedor, a resposta é o envelope `full` com HTTP `502`, mesmo que um nó `set_output` anterior tenha definido um `responseStatusCode`. |

O `finalOutput` de uma execução que falhou na visão `final_output` carrega `status: "failed"` e `errorMessage`, e `errorClass` quando o Flowker conseguiu classificar a falha, nunca um `{}` vazio. Sem um override de `responseStatusCode` (veja abaixo), o status HTTP síncrono continua `200` para `full`/`final_output`/`receipt` (ele reporta a saúde do transporte, não o resultado de negócio). Um `responseStatusCode` válido em um nó `set_output` que roda sobrepõe esse status nessas três visões.

Um nó de ação com `actionType: "set_output"` pode carregar um `responseStatusCode` opcional (inteiro, `200`–`599`) para sobrepor o status HTTP que uma resposta de webhook `sync` devolve. Um valor fora do intervalo ou não inteiro falha na hora de salvar (`FLK-0122`). Para `passthrough`, o status de provedor repassado por um executor terminal vence o override.

Um `set_output` terminal depois de um executor dá forma à resposta como a saída dele mesmo. O Flowker nunca volta atrás para a resposta de um executor anterior. Em uma execução que falhou, a etapa que parou é a etapa terminal, então o Flowker repassa um `4xx` de provedor que parou o workflow como o `4xx` real.

Os valores na saída de um nó `set_output` aceitam referências `${...}` resolvidas contra o contexto do workflow, incluindo `${workflow.<field>}` (payload do gatilho), `${execution.id}`, `${execution.startedAt}` e `${execution.now}` (carimbado no momento da interpolação). Uma referência `${...}` que não resolve faz a etapa falhar (fail-closed).

## Tratamento de erros

***

Se um nó falha, a execução para e o status dela vira `failed`.

Não existe fallback automático. Depois que as novas tentativas acabam, a execução falha.

Os resultados da execução reportam o `status` da execução e os `stepResults`. Uma etapa que falhou fornece `stepNumber`, `nodeId`, `status` e `errorMessage`, com `statusCode` e `errorClass` quando disponíveis. O campo `output` é opcional.

## Novas tentativas e circuit breaker

***

O Flowker inclui resiliência nativa para chamadas de executor.

### Novas tentativas

Quando uma chamada de executor falha com um erro transitório (um erro de rede, um timeout na tentativa, qualquer status `5xx`, ou status `408` ou `429`), o Flowker tenta de novo automaticamente. O comportamento de nova tentativa é configurável por nó, no `data` do nó executor:

| Configuração | Padrão | Limites | Descrição |
| - | - | - | - |
| `timeout_seconds` | 30 | 1–300 | Timeout por requisição. |
| `retry.max_attempts` | 3 (1 para `POST` e `PATCH` sem configuração) | 1–10 aceitos; 1–5 efetivos | Aceita `1`–`10` no schema do nó, mas o Flowker limita a contagem efetiva de tentativas em runtime a `1`–`5`. |
| `retry.backoff_seconds` | 1 | 1–60 | Primeiro teto de backoff; cada espera é um valor aleatório entre zero e o teto, que dobra a cada tentativa. |
| `success_status_codes` | `[200, 201, 202, 204]` | 100–599 | Códigos de status HTTP tratados como sucesso. |

As novas tentativas valem apenas quando a operação é segura de repetir. Por padrão, o Flowker trata chamadas `POST` e `PATCH` como não idempotentes e **não** as repete (uma única tentativa), enquanto `GET`, `PUT`, `DELETE` e outros verbos são repetidos normalmente. Um `retry.max_attempts` maior que `1` faz aquele nó aderir às novas tentativas seja qual for o método. Um `retry.max_attempts` de `1` não é uma adesão. Ele define uma única tentativa.

**Erros que não permitem nova tentativa** vão direto para uma única tentativa, seja qual for a configuração. Entre eles estão circuit breaker aberto, contexto cancelado e falhas ao resolver secrets. Incluem também um corpo de requisição acima do limite de tamanho configurado, um corpo de resposta de provedor acima do mesmo limite e respostas `4xx` de provedor que não são transitórias. Isso significa qualquer `4xx` exceto `408` e `429`.

A nova tentativa vale por execução de nó. Se todas as tentativas falham, a etapa falha e a execução para.

### Circuit breaker

O Flowker usa um circuit breaker para que chamadas que falham repetidamente não sobrecarreguem serviços externos:

| Parâmetro | Valor |
| - | - |
| Limiar de falhas | 20 falhas consecutivas abrem o circuito |
| Timeout de recuperação | 30 segundos antes de tentar de novo (estado half-open) |
| Requisições em half-open | 1 requisição permitida para testar se o serviço se recuperou |

Uma resposta `4xx` do provedor **não** conta para o limiar, exceto `408` e `429`: ela reflete a requisição, não a saúde do provedor.

Uma resposta `5xx` do provedor conta, mesmo quando o provedor a envia de propósito para um resultado de negócio. Exemplo: um plugin Pix que responde `500` para o remetente reenviar um crédito que ele estacionou. Dê ao workflow que repassa essas respostas uma configuração de provedor própria. O circuito dele abre sozinho, e as suas outras chamadas ao mesmo provedor continuam passando.

Quando o circuito está aberto, as chamadas de executor falham na hora com `FLK-0507` em vez de alcançar o serviço externo. Isso evita falhas em cascata e dá tempo ao serviço externo para se recuperar.

![Estados do circuit breaker](https://mintcdn.com/lerian-49cb71fc/vdBt8wfgjsNRO1rf/images/pt/d2/flowker-circuit-breaker.svg?fit=max\&auto=format\&n=vdBt8wfgjsNRO1rf\&q=85\&s=6750ad5ecddebf530bb7417b1be042cf)

Transições de estado do circuit breaker

O circuito começa no estado **Closed**, onde todas as requisições passam normalmente. Depois que o circuito alcança o limiar de falhas, ele passa para **Open** e bloqueia todas as requisições na hora. Depois de 30 segundos, ele vai para **Half-Open** e permite uma requisição de teste. Se essa requisição funciona, o circuito volta para Closed. Se falha, o circuito reabre por outro ciclo de 30 segundos.

> [!WARNING]
>
> O circuit breaker opera por configuração de provedor, no escopo do seu tenant. Falhas contra uma conexão não afetam outra, e um tenant não pode abrir o circuito de outro. Os limiares do circuit breaker (contagem de falhas, timeout de recuperação) são padrões globais do deploy. Você não pode personalizá-los por conexão.

## O que vem a seguir

***

> [card] [Conceitos centrais](https://docs.lerian.studio/pt/products/flowker/flowker-concepts.md)
>
> Entenda workflows, nós, arestas e execuções.

> [card] [API de configurações de provedor](https://docs.lerian.studio/pt/reference/products/flowker/list-provider-configurations.md)
>
> Explore a API de configuração de provedor.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.