> ## 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 os dados da requisição e da resposta

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

Um node executor envia dados a um serviço externo e recebe dados de volta. O serviço nomeia os campos dele e o seu workflow nomeia os dele. Os mapeamentos são a forma de mover valores entre os dois: uma lista de entradas origem-para-destino no node, aplicadas à requisição antes da chamada e à resposta depois dela.

Você precisa deles quando o formato que o seu workflow carrega não é o que o serviço aceita: um documento que precisa viajar sem pontuação, um valor que pertence a um objeto aninhado, um score que um node seguinte lê com um nome curto.

## Antes de começar

***

* Uma configuração de provider para o serviço e um node executor que a referencie. Veja [Referenciar a configuração de provider a partir de um node de workflow](/pt/flowker/integration-guide#passo-3-referenciar-a-configuração-de-provider-a-partir-de-um-node-de-workflow).
* Os nomes dos campos que o serviço espera. Quando o documento OpenAPI do serviço está no registro, [Derivar o schema de uma operação](/pt/reference/flowker/derive-openapi-operation-schema) devolve `inputSchema` — o corpo da requisição da operação — e `outputSchema` — a resposta de sucesso dela. Os dois trazem os nomes de campo que você escreve como target e como source dos seus mapeamentos.
* Um workflow em estado `draft`. Um workflow ativo fica bloqueado, então use [Mover o workflow para draft](/pt/reference/flowker/move-workflow-to-draft) antes de editar um node e ative-o de novo depois.

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

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

***

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

| Caminho               | O que contém                                                                                                                                                                                                                                                                            |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workflow`            | O payload do trigger: o `inputData` de uma requisição de execução, ou o corpo que uma rota de webhook recebeu. Uma rota de webhook acrescenta também `workflow._webhook` com os metadados da chamada — veja [Metadados do webhook](/pt/flowker/integration-guide#metadados-do-webhook). |
| `execution.id`        | O identificador da execução.                                                                                                                                                                                                                                                            |
| `execution.startedAt` | O momento em que a execução começou, em UTC.                                                                                                                                                                                                                                            |
| `<nodeId>`            | A saída de cada node já concluído, sob o ID daquele node.                                                                                                                                                                                                                               |

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

| Source                         | O que seleciona                                |
| ------------------------------ | ---------------------------------------------- |
| `workflow.customer.document`   | Um campo aninhado do payload do trigger.       |
| `workflow.items[0].sku`        | Um elemento de um array.                       |
| `workflow.items[*].sku`        | O mesmo campo em cada elemento, como array.    |
| `workflow`                     | Todo o payload do trigger como objeto.         |
| `score-transaction.body.score` | Um campo da saída do node `score-transaction`. |

<Note>
  O `source` de um mapeamento é um caminho simples. Não o envolva em `${...}`: as chaves pertencem aos campos de template do node (`body`, `headers`, `query`, `path`), e dentro de um mapeamento uma string `${...}` é lida 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 node 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 do contexto do workflow que é lido.                                                                                                            |
| `target`         | string  | Sim         | O caminho do corpo da requisição de saída que é escrito. Um target com pontos cria o objeto aninhado: `payment.amount` envia `{"payment":{"amount":…}}`. |
| `transformation` | object  | Não         | Uma mudança aplicada ao valor depois que ele chega ao target. Veja o [Passo 4](#passo-4-ajuste-um-valor-em-trânsito).                                    |
| `required`       | boolean | Não         | Se o caminho de origem precisa existir. O padrão é `false`. Vale para o node inteiro — veja abaixo.                                                      |

O resultado do mapeamento **é** o corpo da requisição. Escreva cada `target` exatamente como o serviço espera recebê-lo: não existe objeto envolvente nem prefixo a acrescentar.

<Accordion title="Exemplo — mapear o payload do trigger para uma verificação de fraude">
  ```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 trigger de `{"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 um source não seleciona nada

Um caminho de origem ausente do contexto não é um erro. O target é escrito de todo modo, com o valor `null`, e a requisição sai.

Use `required: true` quando o node não puder chamar o serviço sem um valor. O Flowker então confere cada caminho de origem daquele node antes de montar a requisição e falha o passo quando algum está ausente: a execução para com `FLK-0504` e o passo informa `input transformation failed`.

<Note>
  `required` vale para o node, não só para a entrada que o carrega. Se alguma entrada do `inputMapping` de um node marca `required: true`, cada caminho de origem daquele array precisa resolver. Para manter alguns campos opcionais, deixe `required` de fora no node inteiro.
</Note>

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

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

***

Um node tem três formas de produzir um corpo de requisição. O Flowker as confere em uma ordem fixa e para na primeira que estiver presente:

<Steps>
  <Step title="data.body">
    Um template de corpo explícito vence por completo. O Flowker resolve as referências `${...}` dele contra o contexto do workflow e envia o resultado. Enquanto `data.body` está presente, `inputMapping`, `transforms` e `config` não contribuem nada para o corpo.

    Cada referência `${...}` aqui precisa resolver. Uma que não resolve falha o node com `FLK-0143`, antes de qualquer chamada — o oposto de um source de mapeamento, que resolve como `null`. Use `data.body` quando um valor ausente precisa parar o workflow, e um mapeamento quando a requisição precisa sair de todo modo.
  </Step>

  <Step title="inputMapping ou transforms">
    Caso contrário, o Flowker monta uma camada a partir de `inputMapping`. Quando `inputMapping` está vazio, ele monta a camada a partir de `transforms`. Os dois são mutuamente exclusivos: um node com pelo menos uma entrada em `inputMapping` nunca executa os `transforms` dele sobre a entrada.
  </Step>

  <Step title="Literais de config">
    Os valores literais de `data.config` semeiam o corpo. Com uma camada presente, os literais são a base e a camada vence em qualquer chave que os dois definam, então um mesmo node pode combinar valores fixos com valores mapeados. Sem camada, os literais são o corpo por conta própria.
  </Step>
</Steps>

O transporte nunca faz parte do corpo da requisição. Antes que `config` possa semear o corpo, o Flowker remove de lá estes nomes: `method`, `path`, `url`, `endpointName`, `query`, `headers`, `auth`, `retry`, `timeout`, `timeout_seconds`, `request_format`, `success_status_codes`, `allowedHosts` e `allowedPrivateHosts`. Por isso um node que guarda transporte em `config` por engano não envia nada disso ao destino, e um bloco `auth` colocado lá nunca pode viajar como conteúdo da requisição.

O node lê o próprio transporte no nível superior do objeto `data` dele: `path`, `endpointName`, `method`, `headers`, `query`, `auth`, `timeout_seconds`, `retry`, `success_status_codes` e `request_format`. As listas de hosts permitidos de saída não estão entre eles: `allowedHosts` e `allowedPrivateHosts` são definidos na configuração de provider, e cada uma vale para todos os nodes que chamam através dela.

<Accordion title="Exemplo — valores fixos junto com 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 combinam, e o aninhamento se combina com o aninhamento:

  ```json theme={null}
  {
    "channel": "web",
    "reference": "txn-98765",
    "payment": { "currency": "BRL", "amount": 1500.00 }
  }
  ```
</Accordion>

## Passo 4: Ajuste um valor em trânsito

***

Quando o serviço precisa de um valor em outro formato, acrescente uma `transformation` à entrada do mapeamento. Ela se aplica ao valor depois que ele chega ao target.

| Tipo                | O que faz                                | Config                                  |
| ------------------- | ---------------------------------------- | --------------------------------------- |
| `remove_characters` | Remove do texto os caracteres indicados. | `characters` — os caracteres removidos. |
| `add_prefix`        | Coloca texto antes do valor.             | `prefix` — o texto acrescentado.        |
| `add_suffix`        | Coloca texto depois do valor.            | `suffix` — o texto acrescentado.        |
| `to_uppercase`      | Converte o texto para maiúsculas.        | —                                       |
| `to_lowercase`      | Converte o texto para minúsculas.        | —                                       |

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

Duas regras para escrevê-las:

* Elas atuam sobre texto. Um valor que não é texto chega ao target sem mudança.
* `prefix` e `suffix` precisam de pelo menos um caractere cada um, e um único espaço conta. `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 marcar 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 node envia:

  ```json theme={null}
  {
    "payer": {
      "document": "12345678900",
      "name": "ADA LOVELACE",
      "reference": "BR-txn-98765"
    }
  }
  ```
</Accordion>

### Transformações sobre o documento inteiro

Para o trabalho que o mapeamento entrada por entrada não expressa — combinar dois campos, escolher o primeiro valor presente, preencher um valor padrão — declare um array `transforms`. Cada operação lê todo o contexto do workflow e escreve a camada inteira.

O Flowker aceita `shift` (mover ou renomear), `concat` (juntar valores), `coalesce` (primeiro valor presente), `default` (preencher uma chave ausente), `extract` (subir 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 node">
  ```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 node envia:

  ```json theme={null}
  {
    "reference": "txn-98765",
    "payment": { "amount": 1500.00 },
    "channel": "web"
  }
  ```

  Uma operação pode marcar `require: true` para exigir que exista cada caminho que a `spec` dela nomeia, do mesmo modo que `required` funciona em uma entrada de mapeamento.
</Accordion>

<Note>
  `transforms` só é executado quando o node não tem `inputMapping`. Use um ou outro em um mesmo node, 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 node, para que os nodes seguintes leiam nomes curtos e estáveis. Declare-os em um array `outputMapping` dentro do `data` do node, com os mesmos quatro campos de entrada de um mapeamento de entrada.

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

| Caminho            | O que 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 pediu, com a query string que ele montou.                                                                                                                                            |
| `headers`          | Os cabeçalhos da resposta, como objeto chave-valor sob os nomes canônicos deles, como `Content-Type`. Um cabeçalho que o serviço enviou mais de uma vez chega como um único valor separado por vírgulas. |
| `body`             | O corpo da resposta, 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`      | Vale `xml` quando um corpo XML foi decodificado.                                                                                                                                                         |
| `body_parse_error` | Aparece no lugar de `body` quando um corpo XML não pôde ser decodificado, para que o workflow possa ramificar diante disso.                                                                              |

Por isso os campos da resposta ficam sob `body`:

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

Em um node cujo ID é `score-transaction`, isso guarda:

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

Os nodes seguintes leem então `${score-transaction.score}` e `${score-transaction.httpStatus}`.

Um node que não declara `outputMapping` guarda o envelope inteiro sob o ID dele, e os nodes seguintes leem o caminho do envelope diretamente: `${score-transaction.body.score}`. Acrescente um mapeamento de saída quando quiser o nome curto; dispense-o quando o caminho do envelope já for claro.

Um source de saída que não seleciona nada se comporta como um de entrada: o target é guardado como `null`, a não ser que uma entrada daquele node marque `required: true`.

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

***

[Pré-visualizar a requisição de um executor](/pt/reference/flowker/preview-executor-request) monta a requisição que um node enviaria e a devolve para você. Ela executa a mesma montagem de mapeamentos, transformações e autenticação que uma execução real executa, e nunca abre uma conexão com o serviço, então você pode iterar sobre um mapeamento sem que uma única chamada saia do seu ambiente. Nenhuma credencial aparece no que ela devolve, nem mesmo no `curl`.

Envie o node, a configuração de provider que ele mira e um payload de amostra. A configuração de provider vai na própria requisição, então a pré-visualização não depende de nada além do que você envia:

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

O seu `sampleInput` se torna o payload do trigger, então os source 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: o documento perdeu a pontuação, o nome está em maiúsculas e a referência carrega o prefixo dela — e nenhuma chamada chegou ao serviço.

Leia a resposta nesta ordem:

<Steps>
  <Step title="Confira a URL">
    Ela é a URL base da configuração de provider mais o `path` do node. Um caminho que você não esperava é um campo do node a corrigir, não um mapeamento.
  </Step>

  <Step title="Confira o corpo contra os nomes de campo que o serviço espera">
    Cada `target` precisa aparecer onde o serviço o quer. Um campo com `null` é um caminho `source` que não seleciona nada.
  </Step>

  <Step title="Confira `unresolved`">
    Ele lista as referências `${...}` dos campos de template do node que o seu payload de amostra não resolveu. Elas ficam literais na requisição montada. Um array vazio significa que cada referência encontrou um valor.
  </Step>
</Steps>

Para conferir também os campos fixos de um node contra o schema do executor do catálogo, chame [Validar a configuração de um node](/pt/reference/flowker/validate-executor-config) com a configuração do node em `config` e, em `mappedTargets`, os caminhos de target que o seu `inputMapping` fornece. O Flowker os conta como satisfeitos, então um node que mapeia um campo obrigatório a partir do trigger passa na conferência.

## O que pode dar errado

***

| Sintoma                                            | Causa                                                                                                          | Solução                                                                                                                                |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| O serviço recebe um campo com valor `null`.        | O caminho `source` está ausente do contexto do workflow.                                                       | Compare o caminho com o corpo montado de uma pré-visualização. Marque `required: true` no node quando ele não puder rodar sem o valor. |
| O serviço recebe um objeto aninhado que não pediu. | O `target` carrega um prefixo.                                                                                 | Escreva o target exatamente como o serviço espera. Um target `executor.accountId` envia um objeto `executor`.                          |
| O corpo da requisição está vazio.                  | O node não tem `data.body`, nem mapeamento, nem `transforms`, e o `config` dele guarda só nomes de transporte. | Acrescente os valores como literais de `config` ou como entradas de mapeamento.                                                        |
| Os mapeamentos parecem ser ignorados.              | O node carrega também `data.body`, que é a única fonte do corpo enquanto está presente.                        | Remova `data.body` para que os mapeamentos montem o corpo.                                                                             |
| `transforms` parece ser ignorado.                  | O node tem pelo menos uma entrada em `inputMapping`.                                                           | Remova as entradas de `inputMapping`, ou mova a lógica para elas.                                                                      |
| Um node seguinte não lê nada.                      | A referência não nomeia o node 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 significa                                                                                                                                                                                                                |
| -------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `FLK-0140`     | Ao criar, atualizar ou ativar | O `inputMapping` do node não forma uma spec válida — na maioria das vezes, um `transformation.type` fora dos cinco tipos aceitos.                                                                                              |
| `FLK-0141`     | Ao criar, atualizar ou ativar | O mesmo, para o `outputMapping` do node.                                                                                                                                                                                       |
| `FLK-0142`     | Ao criar, atualizar ou ativar | O mesmo, para os `transforms` do node.                                                                                                                                                                                         |
| `FLK-0143`     | Em execução                   | Uma referência `${...}` do `data.body` do node não resolve contra o contexto do workflow. O node falha sem chamar o serviço.                                                                                                   |
| `FLK-0504`     | Em execução                   | O node falhou. A mensagem do passo nomeia a etapa: `input transformation failed` para um source obrigatório ausente ou uma transformação que não pôde ser executada, e `output transformation failed` para o lado da resposta. |

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

## Próximos passos

***

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

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