> ## 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](/pt/products/flowker/integration-guide#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](/pt/reference/products/flowker/derive-openapi-operation-schema) 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`. Um workflow ativo fica travado, então use [Mover workflow para draft](/pt/reference/products/flowker/move-workflow-to-draft) antes de editar um nó, 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](/pt/products/flowker/connecting-your-own-api) 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.
</Note>

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

***

Todo mapeamento 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](/pt/products/flowker/integration-guide#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ó 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 `${...}`. As chaves pertencem aos campos de template do nó (`body`, `headers`, `query`, `path`), e dentro de um mapeamento o Flowker lê uma string `${...}` como um nome de caminho literal que não seleciona nada.
</Note>

## 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 title="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.00, "document": "12345678900" }
  }
  ```
</Accordion>

### 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 para com `FLK-0504` 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.
</Note>

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`:

<Steps>
  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>
</Steps>

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`, `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` e `request_format`. 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 title="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.00 }
  }
  ```
</Accordion>

<h2 id="step-4-reshape-a-value-on-its-way-through">
  Passo 4: Remodele um valor no caminho
</h2>

***

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

Esses cinco são o conjunto inteiro. Um `type` fora dele falha quando você salva o workflow, com `FLK-0140`.

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 com `FLK-0504`.

<Accordion title="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"
    }
  }
  ```
</Accordion>

### 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. Cada operação lê o contexto do workflow inteiro e escreve a sobreposição inteira.

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 title="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.00 },
    "channel": "web"
  }
  ```

  Uma operação pode definir `require: true` para exigir que todo caminho nomeado pelo `spec` dela exista, do mesmo jeito que `required` funciona em uma entrada de mapeamento.
</Accordion>

<Note>
  `transforms` roda apenas quando o nó não tem `inputMapping`. Use um ou o outro em um mesmo nó, nunca os dois.
</Note>

## 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` 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 }
```

Os nós downstream então leem `${score-transaction.score}` e `${score-transaction.httpStatus}`.

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](/pt/reference/products/flowker/preview-executor-request) 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. Ela mascara os valores secretos fornecidos e usa o catálogo do Flowker para resolver o provedor e o executor. Nenhuma credencial aparece em lugar nenhum do que ela retorna, inclusive no `curl`.

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 nem de uma leitura do vault. O catálogo do lado do servidor ainda deve resolver o provedor e o executor:

```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:

<Steps>
  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="Confira `unresolved`">
    Ele lista as referências `${...}` nos campos de template do nó que seu payload de exemplo não resolveu. O Flowker as deixa literais na requisição renderizada. Um array vazio significa que cada referência encontrou um valor.
  </Step>
</Steps>

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ó](/pt/reference/products/flowker/validate-executor-config). 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>}`. 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` fora dos cinco tipos aceitos.                                                                               |
| `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.                                                                                         |
| `FLK-0504`     | Tempo de execução                | O nó falhou. A mensagem do passo nomeia o estágio: `input transformation failed` para uma origem obrigatória ausente ou uma transformação que não pôde rodar, `output transformation failed` para o lado da resposta. |

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

## O que vem a seguir

***

<CardGroup cols={2}>
  <Card title="Guia de integração" icon="plug" href="/pt/products/flowker/integration-guide">
    Crie a configuração de provedor pela qual um nó chama, e defina a autenticação dela.
  </Card>

  <Card title="Configurando um gatilho de webhook" icon="webhook" href="/pt/products/flowker/configuring-a-webhook-trigger">
    Escolha o contrato de payload que preenche o namespace `workflow` que seus mapeamentos leem.
  </Card>
</CardGroup>
