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

# Trabalhando com dados de requisição e resposta

> Mova valores para a requisição de um nó executor e para fora da resposta dele. Declare os mapeamentos, remodele valores em trânsito e confira a requisição montada antes de chamar o serviço.

Um nó executor envia dados para um serviço externo e recebe dados de volta. O serviço dá nome aos campos dele, e seu workflow dá nome aos dele. Os mapeamentos são como você move valores entre os dois. Eles são uma lista de entradas de origem para destino no nó. O Flowker os aplica à requisição antes da chamada e à resposta depois dela.

Você precisa disso sempre que o formato que seu workflow carrega não é o formato que o serviço aceita. Um exemplo é um documento que deve viajar sem pontuação. Outro é um valor que deve ficar sob um objeto aninhado, ou uma pontuação que um nó posterior lê sob um nome curto.

## Antes de começar

***

* Uma configuração de provedor para o serviço, e um nó executor que a referencia. Veja [Referenciar a configuração de provedor a partir de um nó do workflow](https://docs.lerian.studio/pt/products/flowker/integration-guide.md#step-3-reference-the-provider-configuration-from-a-workflow-node).
* Os nomes de campo que o serviço espera. Quando o documento OpenAPI do serviço está no registro, [Derivar o schema de uma operação](https://docs.lerian.studio/pt/reference/products/flowker/derive-openapi-operation-schema.md) retorna `inputSchema` (o corpo da requisição da operação) e `outputSchema` (a resposta de sucesso dela). Os dois dão os nomes de campo que você escreve como destinos e origens de mapeamento.
* Um workflow no status `draft`. Para editar um workflow ativo, [desative-o](https://docs.lerian.studio/pt/reference/products/flowker/deactivate-workflow.md) e [mova-o para draft](https://docs.lerian.studio/pt/reference/products/flowker/move-workflow-to-draft.md), e ative-o de novo depois.

> [!NOTE]
>
> Não envie `executorId` em um nó que chama uma operação de um documento OpenAPI enviado. Esse nó nomeia a operação com `operation_path` e `operation_method`. O Flowker preenche o `executorId` para você, a partir da configuração de provedor para a qual o nó aponta, antes de validar o workflow. Ele faz isso quando você cria o workflow e quando você o atualiza. [Conectando sua própria API](https://docs.lerian.studio/pt/products/flowker/connecting-your-own-api.md) percorre esse caminho inteiro. Os nós desta página nomeiam `http`, o conector HTTP genérico, que de fato precisa de um `executorId` explícito.

## Passo 1: Saiba o que um mapeamento pode ler

***

Um mapeamento de entrada lê do contexto do workflow, um objeto JSON único que cresce conforme a execução avança:

| Caminho | O que ele contém |
| - | - |
| `workflow` | O payload do gatilho: o `inputData` de uma requisição de execução, ou o corpo que uma rota de webhook recebeu. Uma rota de webhook também acrescenta `workflow._webhook` com os metadados da chamada. Veja [Metadados de webhook](https://docs.lerian.studio/pt/products/flowker/integration-guide.md#webhook-metadata). |
| `execution.id` | O identificador da execução. |
| `execution.startedAt` | Quando a execução começou, em UTC. |
| `<nodeId>` | A saída de cada nó executor que terminou, sob o id desse nó. |

Referencie um valor pelo caminho dele a partir de uma dessas chaves de nível superior:

| Origem | O que ela seleciona |
| - | - |
| `workflow.customer.document` | Um campo aninhado do payload do gatilho. |
| `workflow.items[0].sku` | Um elemento de um array. |
| `workflow.items[*].sku` | O mesmo campo em cada elemento, como um array. |
| `workflow` | O payload do gatilho inteiro, como um objeto. |
| `score-transaction.body.score` | Um campo da saída do nó `score-transaction`. |

> [!NOTE]
>
> Um `source` de mapeamento é um caminho simples. Não o envolva em `${...}`. Dentro de um mapeamento o Flowker lê uma string `${...}` como um nome de caminho literal que não seleciona nada.

## Passo 2: Declare o mapeamento de entrada

***

Os mapeamentos de entrada ficam em um array `inputMapping` dentro do objeto `data` do nó executor. Cada entrada move um valor para o corpo da requisição de saída.

| Campo | Tipo | Obrigatório | Descrição |
| - | - | - | - |
| `source` | string | Sim | O caminho no contexto do workflow que será lido. |
| `target` | string | Sim | O caminho no corpo da requisição de saída que será escrito. Um destino com pontos cria o objeto aninhado (`payment.amount` envia `{"payment":{"amount":…}}`). |
| `transformation` | objeto | Não | Uma mudança aplicada ao valor depois que ele chega no destino. Veja o [Passo 4](#step-4-reshape-a-value-on-its-way-through). |
| `required` | booleano | Não | Se o caminho de origem deve existir. O padrão é `false`. Vale para o nó inteiro. Veja abaixo. |

O resultado mapeado é o corpo da requisição. Escreva cada `target` exatamente como o serviço espera recebê-lo: não existe objeto invólucro nem prefixo a acrescentar.

> [accordion] Exemplo: mapear o payload do gatilho para uma verificação antifraude
>
> ```json theme={null}
> {
>   "id": "score-transaction",
>   "type": "executor",
>   "name": "Score transaction",
>   "position": { "x": 200, "y": 0 },
>   "data": {
>     "executorId": "http",
>     "providerConfigId": "019c96a0-0ac0-7de9-9f53-9cf842a2ee5a",
>     "method": "POST",
>     "path": "/score-transaction",
>     "inputMapping": [
>       { "source": "workflow.transactionId", "target": "reference" },
>       { "source": "workflow.amount", "target": "payment.amount" },
>       { "source": "workflow.customer.document", "target": "payment.document" }
>     ]
>   }
> }
> ```
>
> Com um payload de gatilho `{"transactionId":"txn-98765","amount":1500.00,"customer":{"document":"12345678900"}}`, o serviço recebe:
>
> ```json theme={null}
> {
>   "reference": "txn-98765",
>   "payment": { "amount": 1500, "document": "12345678900" }
> }
> ```

### Quando uma origem não seleciona nada

Um caminho de origem ausente do contexto não é um erro. O Flowker escreve o destino mesmo assim, com o valor `null`, e a requisição sai.

Defina `required: true` quando o nó não deve chamar o serviço sem um valor. O Flowker então checa todos os caminhos de origem daquele nó antes de montar a requisição, e falha o passo quando algum deles está ausente. A execução falha e o passo informa `input transformation failed`.

> [!NOTE]
>
> `required` vale para o nó, não para a única entrada que o carrega. Se qualquer entrada do `inputMapping` de um nó define `required: true`, todos os caminhos de origem daquele array devem resolver. Para manter alguns campos opcionais, deixe `required` desligado no nó inteiro.

Dê a cada `target` uma entrada. Quando duas entradas escrevem o mesmo destino, a última vence.

## Passo 3: Decida o que monta o corpo da requisição

***

Um nó tem três fontes para o corpo de uma requisição. Apenas `data.body` é exclusivo: quando está presente, ele é o corpo inteiro. Sem ele, o Flowker compõe o corpo a partir das outras duas fontes, com a sobreposição do mapeamento escrita por cima dos literais de `config`:

**1. data.body**

Um template de corpo explícito vence de forma absoluta. O Flowker resolve as referências `${...}` dele em relação ao contexto do workflow e envia o resultado. Enquanto `data.body` está presente, `inputMapping`, `transforms` e `config` não contribuem em nada para o corpo.

Toda referência `${...}` aqui deve resolver. Uma que não resolve faz o nó falhar com `FLK-0143`, antes de qualquer chamada sair (o oposto de uma origem de mapeamento, que resolve para `null`). Use `data.body` quando um valor ausente deve parar o workflow, e um mapeamento quando a requisição deve sair de qualquer jeito.

**2. inputMapping ou transforms**

Caso contrário, o Flowker monta uma sobreposição a partir de `inputMapping`. Quando `inputMapping` está vazio, ele monta a sobreposição a partir de `transforms`. Os dois são mutuamente exclusivos: um nó com pelo menos uma entrada de `inputMapping` nunca roda os `transforms` dele na entrada.

**3. literais de config**

Valores literais em `data.config` semeiam o corpo. Com uma sobreposição presente, os literais são a base e a sobreposição vence em qualquer chave que os dois definem. Um nó pode, assim, combinar valores fixos com valores mapeados. Sem sobreposição, os literais são o corpo sozinhos.

O transporte nunca vira conteúdo do corpo. Antes que `config` possa semear o corpo, o Flowker remove estes nomes dele: `method`, `path`, `url`, `endpointName`, `query`, `headers`, `auth`, `retry`, `timeout`, `timeout_seconds`, `request_format`, `success_status_codes`, `content_digest`, `allowedHosts` e `allowedPrivateHosts`. Um nó que guarda o transporte em `config` por engano, portanto, não envia nada disso para o destino. Um bloco `auth` colocado ali nunca pode seguir como conteúdo da requisição.

O nó lê o próprio transporte no topo do objeto `data` dele: `path`, `endpointName`, `method`, `headers`, `query`, `auth`, `timeout_seconds`, `retry`, `success_status_codes`, `request_format` e `content_digest`. As listas de hosts permitidos para saída não estão entre eles: você define `allowedHosts` e `allowedPrivateHosts` na configuração de provedor, onde cada uma vale para todos os nós que chamam por meio dela.

> [accordion] Exemplo: valores fixos mais valores mapeados
>
> ```json theme={null}
> {
>   "data": {
>     "executorId": "http",
>     "providerConfigId": "019c96a0-0ac0-7de9-9f53-9cf842a2ee5a",
>     "method": "POST",
>     "path": "/score-transaction",
>     "config": {
>       "channel": "web",
>       "payment": { "currency": "BRL" }
>     },
>     "inputMapping": [
>       { "source": "workflow.transactionId", "target": "reference" },
>       { "source": "workflow.amount", "target": "payment.amount" }
>     ]
>   }
> }
> ```
>
> Os literais e os valores mapeados se fundem, e o aninhamento se funde com o aninhamento:
>
> ```json theme={null}
> {
>   "channel": "web",
>   "reference": "txn-98765",
>   "payment": { "currency": "BRL", "amount": 1500 }
> }
> ```

## Passo 4: Remodele um valor no caminho

***

Quando o serviço precisa de um valor em outra forma, anexe uma `transformation` à entrada de mapeamento. Ela se aplica ao valor depois que ele chega no destino.

| Tipo | O que ela faz | Config |
| - | - | - |
| `remove_characters` | Remove do texto os caracteres indicados. | `characters`: os caracteres a remover. |
| `add_prefix` | Coloca texto na frente do valor. | `prefix`: o texto a acrescentar. |
| `add_suffix` | Coloca texto depois do valor. | `suffix`: o texto a acrescentar. |
| `to_uppercase` | Converte o texto para maiúsculas. | — |
| `to_lowercase` | Converte o texto para minúsculas. | — |

Duas regras para escrevê-las:

* Elas agem sobre texto. Um valor que não é texto chega ao destino sem mudança.
* Os valores `prefix` e `suffix` precisam de pelo menos um caractere cada, e um único espaço conta. O valor `characters` precisa de pelo menos um caractere que não seja espaço, tabulação nem quebra de linha. Um valor que não atende a isso falha o passo em tempo de execução.

> [accordion] Exemplo: normalizar um documento e carimbar uma referência
>
> ```json theme={null}
> {
>   "inputMapping": [
>     {
>       "source": "workflow.customer.document",
>       "target": "payer.document",
>       "transformation": {
>         "type": "remove_characters",
>         "config": { "characters": ".-/" }
>       }
>     },
>     {
>       "source": "workflow.customer.name",
>       "target": "payer.name",
>       "transformation": { "type": "to_uppercase" }
>     },
>     {
>       "source": "workflow.transactionId",
>       "target": "payer.reference",
>       "transformation": {
>         "type": "add_prefix",
>         "config": { "prefix": "BR-" }
>       }
>     }
>   ]
> }
> ```
>
> A partir de `{"customer":{"document":"123.456.789-00","name":"ada lovelace"},"transactionId":"txn-98765"}`, o nó envia:
>
> ```json theme={null}
> {
>   "payer": {
>     "document": "12345678900",
>     "name": "ADA LOVELACE",
>     "reference": "BR-txn-98765"
>   }
> }
> ```

### Transforms de documento inteiro

Para o trabalho que o mapeamento entrada por entrada não expressa (combinar dois campos, escolher o primeiro valor presente, preencher um padrão), declare um array `transforms` no lugar.

O Flowker aceita `shift` (mover ou renomear), `concat` (juntar valores), `coalesce` (primeiro valor presente), `default` (preencher uma chave ausente), `extract` (elevar uma subárvore para a raiz), `delete` (remover uma chave), `timestamp`, `uuid` e `pass`. Os cinco tipos de transformação acima também estão disponíveis aqui. Como operações, eles recebem o caminho de destino na spec como `path`.

> [accordion] Exemplo: um shift e um default no mesmo nó
>
> ```json theme={null}
> {
>   "data": {
>     "executorId": "http",
>     "providerConfigId": "019c96a0-0ac0-7de9-9f53-9cf842a2ee5a",
>     "transforms": [
>       {
>         "operation": "shift",
>         "spec": {
>           "reference": "workflow.transactionId",
>           "payment.amount": "workflow.amount"
>         }
>       },
>       { "operation": "default", "spec": { "channel": "web" } }
>     ]
>   }
> }
> ```
>
> O nó envia:
>
> ```json theme={null}
> {
>   "reference": "txn-98765",
>   "payment": { "amount": 1500 },
>   "channel": "web"
> }
> ```
>
> `shift`, `concat`, `coalesce`, `extract`, `delete` e `timestamp` aceitam `require: true`, que exige que todo caminho nomeado pelo `spec` exista, do mesmo jeito que `required` funciona em uma entrada de mapeamento.

> [!NOTE]
>
> `transforms` roda apenas quando o nó não tem `inputMapping`. Use um ou o outro em um mesmo nó, nunca os dois.

## Passo 5: Leia a resposta de volta

***

Os mapeamentos de saída extraem campos da resposta e os guardam no contexto do workflow sob o id do nó, para que os nós posteriores leiam nomes curtos e estáveis. Declare-os em um array `outputMapping` no `data` do nó, com os mesmos quatro campos de entrada de um mapeamento de entrada.

Um `source` de saída é um caminho dentro do envelope da resposta, não dentro do corpo da resposta:

| Caminho | O que ele contém |
| - | - |
| `status` | O código de status HTTP. |
| `status_text` | A linha de status HTTP, como `200 OK`. |
| `url` | A URL que o Flowker requisitou, com a query string que ele montou. |
| `headers` | Os headers da resposta, como um objeto de chave e valor sob os nomes canônicos deles, como `Content-Type`. Um header que o serviço enviou mais de uma vez chega como um único valor separado por vírgulas. |
| `body` | O corpo da resposta, já interpretado quando a resposta é `application/json`, um tipo cujo nome termina em `+json` ou um tipo XML (`application/xml`, `text/xml` ou um tipo cujo nome termina em `+xml`). |
| `raw_body` | A resposta exatamente como ela chegou, como texto. Presente em uma resposta XML. |
| `body_format` | Definido como `xml` quando um corpo XML foi decodificado. |
| `body_parse_error` | Presente no lugar de `body` quando um corpo XML não pôde ser decodificado, para que o workflow possa ramificar a partir dele. |

Os campos da resposta ficam, portanto, sob `body`:

```json theme={null}
{
  "outputMapping": [
    { "source": "body.score", "target": "score" },
    { "source": "body.decision", "target": "decision" },
    { "source": "status", "target": "httpStatus" }
  ]
}
```

Em um nó com o id `score-transaction`, isso guarda:

```json theme={null}
{ "score": 42, "decision": "review", "httpStatus": 200 }
```

Um mapeamento downstream então lê `score-transaction.score` e `score-transaction.httpStatus`, e um `data.body` downstream lê `${score-transaction.score}`.

Um nó que não declara `outputMapping` guarda o envelope inteiro sob o id dele, e os nós downstream leem o caminho do envelope direto: `score-transaction.body.score`. Acrescente um mapeamento de saída quando você quiser o nome mais curto. Pule isso quando o caminho do envelope já for claro o bastante.

Uma origem de saída que não seleciona nada se comporta como uma de entrada. O Flowker guarda o destino como `null`, a menos que uma entrada daquele nó defina `required: true`.

## Passo 6: Confira o mapeamento antes de chamar o serviço

***

[Pré-visualizar uma requisição de executor](https://docs.lerian.studio/pt/reference/products/flowker/preview-executor-request.md) usa os caminhos de mapeamento, de transformação e de montagem da requisição sem fazer uma chamada de rede ao serviço. Ela não lê o vault nem busca um token de autenticação. A prévia mascara com `***` a credencial que o tipo de autenticação declara onde ela aparece como valor. Qualquer outro valor, inclusive um parâmetro de autenticação livre, pode aparecer como o Flowker o enviaria.

Envie o nó, a configuração de provedor que ele mira e um payload de exemplo. A configuração de provedor vai na própria requisição, então a prévia não precisa de uma configuração de provedor salva:

```json theme={null}
POST /v1/workflows/preview-request

{
  "node": {
    "executorId": "http",
    "method": "POST",
    "path": "/score-transaction",
    "inputMapping": [
      {
        "source": "workflow.customer.document",
        "target": "payer.document",
        "transformation": {
          "type": "remove_characters",
          "config": { "characters": ".-/" }
        }
      },
      {
        "source": "workflow.customer.name",
        "target": "payer.name",
        "transformation": { "type": "to_uppercase" }
      },
      {
        "source": "workflow.transactionId",
        "target": "payer.reference",
        "transformation": {
          "type": "add_prefix",
          "config": { "prefix": "BR-" }
        }
      }
    ]
  },
  "providerConfig": {
    "providerId": "http",
    "config": { "base_url": "https://api.fraudshield.example.com" },
    "allowedHosts": ["api.fraudshield.example.com"]
  },
  "sampleInput": {
    "transactionId": "txn-98765",
    "customer": { "document": "123.456.789-00", "name": "ada lovelace" }
  }
}
```

Seu `sampleInput` vira o payload do gatilho, então as origens do mapeamento o leem como `workflow.*`, exatamente como farão em tempo de execução.

A resposta é a requisição montada:

```json theme={null}
{
  "method": "POST",
  "url": "https://api.fraudshield.example.com/score-transaction",
  "headers": { "Content-Type": "application/json" },
  "body": "{\"payer\":{\"document\":\"12345678900\",\"name\":\"ADA LOVELACE\",\"reference\":\"BR-txn-98765\"}}",
  "curl": "curl -X POST -H 'Content-Type: application/json' --data '{\"payer\":{\"document\":\"12345678900\",\"name\":\"ADA LOVELACE\",\"reference\":\"BR-txn-98765\"}}' 'https://api.fraudshield.example.com/score-transaction'",
  "unresolved": []
}
```

Cada transformação resolveu: a pontuação sumiu do documento, o nome está em maiúsculas e a referência carrega o prefixo dela. Nenhuma chamada chegou ao serviço.

Leia na seguinte ordem:

**1. Confira a URL**

Ela é a URL base da configuração de provedor mais o `path` do nó. Um caminho que você não esperava é um campo do nó a corrigir, não um mapeamento.

**2. Confira o corpo em relação aos nomes de campo que o serviço espera**

Recomenda-se que cada `target` apareça onde o serviço o quer. Um campo carregando `null` é um caminho `source` que não seleciona nada.

**3. Confira `unresolved`**

Ele lista as referências `${...}` nos headers, na query e na URL do nó que a prévia não conseguiu resolver. O Flowker as deixa literais na requisição renderizada. Uma referência não resolvida em `data.body` faz a prévia falhar com `FLK-0143`.

Para conferir também os campos fixos de um nó em relação ao schema do executor do catálogo, chame [Validar a configuração de um nó](https://docs.lerian.studio/pt/reference/products/flowker/validate-executor-config.md). Envie a configuração do nó em `config` e, em `mappedTargets`, os caminhos de destino que seu `inputMapping` fornece. O Flowker conta esses como satisfeitos, então um nó que mapeia um campo obrigatório vindo do gatilho passa na checagem.

## O que dá errado

***

| Sintoma | Causa | Correção |
| - | - | - |
| O serviço recebe um campo definido como `null`. | O caminho `source` está ausente do contexto do workflow. | Compare o caminho com o corpo renderizado de uma prévia. Defina `required: true` no nó quando ele não deve rodar sem o valor. |
| O serviço recebe um objeto aninhado que ele não pediu. | O `target` carrega um prefixo. | Escreva o destino exatamente como o serviço o espera. Um destino `executor.accountId` envia um objeto `executor`. |
| O corpo da requisição está vazio. | O nó não tem `data.body`, não tem mapeamento nem `transforms`, e o `config` dele guarda apenas nomes de transporte. | Acrescente os valores como literais de `config` ou como entradas de mapeamento. |
| Os mapeamentos parecem ser ignorados. | O nó também carrega `data.body`, que é a única fonte de corpo enquanto está presente. | Remova `data.body` para deixar os mapeamentos montarem o corpo. |
| `transforms` parece ser ignorado. | O nó tem pelo menos uma entrada de `inputMapping`. | Remova as entradas de `inputMapping`, ou mova a lógica para dentro delas. |
| Um nó downstream não lê nada. | A referência não nomeia o nó que produz o valor. | Leia `<nodeId>.<target>` em um mapeamento, ou `${<nodeId>.<target>}` em `data.body`. Não existe um namespace compartilhado de nível superior. |
| Um mapeamento de saída guarda `null`. | O `source` omite o prefixo do envelope. | Mapeie `body.score`, não `score`. |

| Código de erro | Quando | O que ele significa |
| - | - | - |
| `FLK-0140` | Criação, atualização ou ativação | O `inputMapping` do nó não forma uma especificação válida (na maioria das vezes, um `transformation.type` desconhecido). |
| `FLK-0141` | Criação, atualização ou ativação | O mesmo, para o `outputMapping` do nó. |
| `FLK-0142` | Criação, atualização ou ativação | O mesmo, para os `transforms` do nó. |
| `FLK-0143` | Tempo de execução | Uma referência `${...}` no `data.body` do nó não resolve em relação ao contexto do workflow. O nó falha sem chamar o serviço. |

Veja a [lista de erros do Flowker](https://docs.lerian.studio/pt/reference/products/flowker/flowker-error-list.md) para todos os códigos.

## O que vem a seguir

***

> [card] [Guia de integração](https://docs.lerian.studio/pt/products/flowker/integration-guide.md)
>
> Crie a configuração de provedor pela qual um nó chama, e defina a autenticação dela.

> [card] [Configurando um gatilho de webhook](https://docs.lerian.studio/pt/products/flowker/configuring-a-webhook-trigger.md)
>
> Escolha o contrato de payload que preenche o namespace `workflow` que seus mapeamentos leem.


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