> For the complete documentation index, see [llms.txt](https://docs.tunnelhub.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tunnelhub.io/produto/from-error-webhook-to-execution-export.md).

# Do webhook de erro à exportação da execução

Este guia mostra como receber uma notificação de falha por webhook e consultar os dados da execução pela API do TunnelHub.

Use esse fluxo quando seu sistema precisa abrir um incidente, armazenar evidências ou encaminhar logs e traces para outra ferramenta de observabilidade.

## Antes de começar

Você precisa de:

* uma notificação do tipo **Webhook** configurada na automação;
* acesso de usuário ao tenant e ao ambiente da execução;
* usuário e senha do TunnelHub;
* o UUID do ambiente, enviado no header `EnvironmentId`.

> O contrato atual usa ID token de usuário. Credenciais técnicas de CI/CD não autorizam os endpoints deste guia. A seção [Autentique as chamadas](#3-autentique-as-chamadas) mostra como obter e renovar esse token.

Todos os exemplos usam HTTPS. A base da API é `https://api.tunnelhub.io/`.

## 1. Receba a notificação de erro

O TunnelHub envia notificações por webhook somente quando a execução termina com falha. O endpoint receptor deve aceitar `POST` com `Content-Type: application/json` e responder rapidamente com um status `2xx`.

Exemplo de payload:

```json
{
  "account": {
    "name": "Conta exemplo",
    "id": "<tenant-id>"
  },
  "environment": {
    "name": "Produção",
    "id": "<environment-id>"
  },
  "package": {
    "name": "Integrações",
    "id": "<package-id>"
  },
  "automation": {
    "name": "Pedidos",
    "id": "<automation-id>"
  },
  "execution": {
    "startedAt": "2026-08-21T10:00:00.000Z",
    "finishedAt": "2026-08-21T10:05:00.000Z",
    "totalSuccess": 95,
    "totalErrors": 5,
    "message": "Falha ao enviar pedidos"
  },
  "url": "https://portal.cliente.example/#/automations/<automation-id>/execution/2026-08/<execution-id>?env=<environment-id>"
}
```

O request também contém o header `TunnelHub-Tenant-Id` com o UUID do tenant.

O header identifica o tenant, mas não é uma assinatura criptográfica. Não o use sozinho para autenticar a origem do evento. Trate a URL de destino do webhook como segredo e processe o evento em uma fila antes de executar chamadas demoradas.

## 2. Identifique a execução

Use os campos abaixo para montar as chamadas à API:

| Dado            | Origem no webhook                                 |
| --------------- | ------------------------------------------------- |
| `automationId`  | `automation.id`                                   |
| `environmentId` | `environment.id`                                  |
| `period`        | trecho da URL entre `/execution/` e o próximo `/` |
| `executionId`   | trecho da URL após `period` e antes de `?env=`    |

No exemplo acima, o `period` é `2026-08` e o `executionId` é `<execution-id>`.

> No contrato atual, `period` e `executionId` não são campos próprios do JSON. Eles precisam ser obtidos da URL. Trate essa extração como dependência do formato atual do link e valide os valores antes de chamar a API.

## 3. Autentique as chamadas

Envie o ID token do usuário no header `Authorization` e o ambiente da execução no header `EnvironmentId`. Use `USER_PASSWORD_AUTH` para obter o token diretamente do Amazon Cognito.

### 3.1. Obtenha os identificadores

Use `environment.id` do webhook para `TUNNELHUB_ENVIRONMENT_ID`. No portal, abra **Conta > Informações da conta** e copie:

* **Grupo de usuários** para `TUNNELHUB_USER_POOL_ID`.
* **App Client ID** para `TUNNELHUB_CLIENT_ID`.

O Grupo de usuários tem o formato `<região>_<pool>`. Por exemplo, `us-east-1_AbCdEf` usa a região `us-east-1`.

```bash
export TUNNELHUB_API_URL='https://api.tunnelhub.io'
export TUNNELHUB_ENVIRONMENT_ID='<environment-id-do-webhook>'
export TUNNELHUB_USER_POOL_ID='<grupo-de-usuarios>'
export TUNNELHUB_CLIENT_ID='<app-client-id>'
export TUNNELHUB_REGION="${TUNNELHUB_USER_POOL_ID%%_*}"
```

O **Grupo de usuários** e o **App Client ID** precisam pertencer ao mesmo pool.

### 3.2. Obtenha o ID token

Leia a senha sem exibi-la e exporte-a somente para a chamada de autenticação atual:

```bash
read -r -s -p 'Senha do TunnelHub: ' TUNNELHUB_PASSWORD
printf '\n'
export TUNNELHUB_PASSWORD
read -r -p 'Usuário ou e-mail do TunnelHub: ' TUNNELHUB_USERNAME
export TUNNELHUB_USERNAME
```

Faça a chamada HTTPS ao endpoint do Cognito. `jq` monta o JSON a partir das variáveis de ambiente para que a senha não apareça nos argumentos do comando ou no histórico do shell.

```bash
AUTH_RESPONSE="$(
  jq -n \
    '{
      AuthFlow: "USER_PASSWORD_AUTH",
      ClientId: env.TUNNELHUB_CLIENT_ID,
      AuthParameters: {
        USERNAME: env.TUNNELHUB_USERNAME,
        PASSWORD: env.TUNNELHUB_PASSWORD
      }
    }' |
  curl --fail-with-body \
    -H 'Content-Type: application/x-amz-json-1.1' \
    -H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
    --data @- \
    "https://cognito-idp.${TUNNELHUB_REGION}.amazonaws.com/"
)"

export TUNNELHUB_ID_TOKEN="$(jq -er '.AuthenticationResult.IdToken' <<< "${AUTH_RESPONSE}")"
export TUNNELHUB_REFRESH_TOKEN="$(jq -er '.AuthenticationResult.RefreshToken' <<< "${AUTH_RESPONSE}")"
export TUNNELHUB_TOKEN_EXPIRES_IN="$(jq -er '.AuthenticationResult.ExpiresIn' <<< "${AUTH_RESPONSE}")"
unset AUTH_RESPONSE TUNNELHUB_PASSWORD
```

Se a resposta contiver `ChallengeName` em vez de `AuthenticationResult`, ela não contém tokens. Resolva o desafio manualmente no Cognito antes de tentar a autenticação novamente. Não use `USER_PASSWORD_AUTH` para usuários autenticados por SAML.

### 3.3. Renove o ID token

Antes de o token expirar, use o refresh token para obter novos tokens. O refresh token permanece o mesmo no fluxo atual.

```bash
REFRESH_RESPONSE="$(
  jq -n \
    '{
      AuthFlow: "REFRESH_TOKEN_AUTH",
      ClientId: env.TUNNELHUB_CLIENT_ID,
      AuthParameters: {
        REFRESH_TOKEN: env.TUNNELHUB_REFRESH_TOKEN
      }
    }' |
  curl --fail-with-body \
    -H 'Content-Type: application/x-amz-json-1.1' \
    -H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
    --data @- \
    "https://cognito-idp.${TUNNELHUB_REGION}.amazonaws.com/"
)"

export TUNNELHUB_ID_TOKEN="$(jq -er '.AuthenticationResult.IdToken' <<< "${REFRESH_RESPONSE}")"
export TUNNELHUB_TOKEN_EXPIRES_IN="$(jq -er '.AuthenticationResult.ExpiresIn' <<< "${REFRESH_RESPONSE}")"
unset REFRESH_RESPONSE
```

Proteja `TUNNELHUB_REFRESH_TOKEN` como uma credencial de longa duração. Não o registre, não o exponha em variáveis de CI abertas e não o inclua em tickets.

### 3.4. Use o token na API

```bash
export AUTOMATION_ID='<automation-id>'
export EXECUTION_ID='<execution-id>'
export PERIOD='2026-08'
```

Não registre o ID token, URLs pré-assinadas de download ou o corpo completo de logs e traces em sistemas que não precisam desses dados.

## 4. Consulte o resumo da execução

Comece pelo detalhe para confirmar automação, ambiente, período, status e totais antes de aprofundar a investigação.

```bash
curl --fail-with-body \
  -H "Authorization: Bearer ${TUNNELHUB_ID_TOKEN}" \
  -H "EnvironmentId: ${TUNNELHUB_ENVIRONMENT_ID}" \
  "${TUNNELHUB_API_URL}/integrations-service/automations/monitoring/${EXECUTION_ID}?automationId=${AUTOMATION_ID}&period=${PERIOD}"
```

Use logs de processamento para investigar registros de negócio e traces para investigar o comportamento técnico da execução.

## 5. Exporte todos os logs de processamento

Para obter todos os logs, solicite a exportação em vez de paginar a consulta de logs.

```bash
curl --fail-with-body \
  -H "Authorization: Bearer ${TUNNELHUB_ID_TOKEN}" \
  -H "EnvironmentId: ${TUNNELHUB_ENVIRONMENT_ID}" \
  "${TUNNELHUB_API_URL}/integrations-service/automations/monitoring/${EXECUTION_ID}/executionLogs/download?automationId=${AUTOMATION_ID}&period=${PERIOD}"
```

Para execuções com menos de 5.000 logs, a resposta contém uma URL imediata:

```json
{
  "status": "ok",
  "url": "<url-pre-assinada-do-arquivo-xlsx>"
}
```

Para volumes maiores, a resposta cria um job assíncrono:

```json
{
  "status": "pending",
  "processingId": "<processing-id>"
}
```

Consulte o job conforme descrito em **Acompanhe uma exportação assíncrona**.

## 6. Exporte todos os traces

O endpoint de leitura de traces é paginado e serve para investigação interativa. Não o use para tentar recuperar a execução completa quando houver muitas páginas.

Para exportar todos os traces, inicie a exportação assíncrona sem filtros:

```bash
curl --fail-with-body \
  -X POST \
  -H "Authorization: Bearer ${TUNNELHUB_ID_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "EnvironmentId: ${TUNNELHUB_ENVIRONMENT_ID}" \
  -d "{\"automationId\":\"${AUTOMATION_ID}\",\"executionId\":\"${EXECUTION_ID}\",\"period\":\"${PERIOD}\",\"format\":\"ndjson\"}" \
  "${TUNNELHUB_API_URL}/integrations-service/automations/monitoring/${EXECUTION_ID}/traces/export"
```

Uma solicitação aceita retorna `202`:

```json
{
  "exportId": "<export-id>",
  "status": "accepted",
  "message": "Exportação iniciada"
}
```

Guarde `exportId` e use-o como o ID do job na próxima etapa. Se já existir uma exportação de traces em andamento para a execução, a API retorna `409` com `EXPORT_ALREADY_IN_PROGRESS`.

> Embora a requisição exija `format` com `csv` ou `ndjson`, o artefato atual é entregue como `traces-<execution-id>.gz`, com o export textual do CloudWatch Logs. Não presuma um CSV ou NDJSON convertido pelo worker atual.

## 7. Acompanhe uma exportação assíncrona

Use `processingId` para logs ou `exportId` para traces no endpoint de background processing:

```bash
curl --fail-with-body \
  -H "Authorization: Bearer ${TUNNELHUB_ID_TOKEN}" \
  -H "EnvironmentId: ${TUNNELHUB_ENVIRONMENT_ID}" \
  "${TUNNELHUB_API_URL}/platform-service/backgroundProcessings/<processing-id-ou-export-id>"
```

Repita a consulta com intervalo progressivo enquanto o status for `PENDING` ou `PROCESSING`.

| Status       | Ação                                                 |
| ------------ | ---------------------------------------------------- |
| `PENDING`    | Aguarde o processamento iniciar.                     |
| `PROCESSING` | Continue aguardando.                                 |
| `FINISHED`   | Baixe a URL pré-assinada presente em `message`.      |
| `FAIL`       | Registre a mensagem de erro e investigue a execução. |

As URLs de download expiram em 24 horas. Baixe e armazene o arquivo em um repositório seguro antes da expiração, quando a política de retenção do cliente permitir.

## Erros comuns

* `401`: o ID token expirou ou não foi enviado.
* `403`: o usuário não tem acesso ao recurso ou ambiente informado.
* `404`: confirme `automationId`, `executionId`, `period` e `EnvironmentId`.
* `409 EXPORT_ALREADY_IN_PROGRESS`: reutilize o job de exportação em andamento em vez de iniciar outro.
* `FAIL` no background processing: a exportação não foi concluída; use o resumo, logs e traces disponíveis para investigar.
* URL de download expirada: solicite uma nova exportação.

## Boas práticas

* responda ao webhook antes de iniciar consultas ou exports;
* deduplique eventos pelo conjunto de automação, ambiente, período e execução;
* valide que os IDs extraídos da URL correspondem aos campos `automation.id` e `environment.id` do payload;
* use o endpoint assíncrono para traces completos, principalmente em execuções com milhares de páginas;
* sanitize logs e traces antes de enviá-los para tickets, chats ou sistemas externos.

Veja também [Notificações](https://docs.tunnelhub.io/produto/pages/occlNL417jAsMpB5ISDq#notificações) e [Monitoramento](/produto/monitoring.md).
