> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ararahq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Recuperação de receita

> Receba eventos de carrinho abandonado, pagamento recusado, Pix gerado e boleto a vencer da sua plataforma e dispare automaticamente um template no WhatsApp com link de retorno rastreável.

Referência da recuperação de receita: contrato do endpoint, eventos, assinatura e respostas. Para o passo a passo, veja a receita [Recuperar carrinho abandonado](/recipes/abandoned-cart).

Sua plataforma envia o evento para um endpoint único da sua organização, e a Arara dispara o template vinculado àquele evento para o telefone do cliente, com um botão de retorno rastreável.

<Note>
  A recuperação de receita depende do plano: os endpoints `/v1/recovery/*` respondem `403 PLAN_FEATURE_LOCKED` quando o plano não inclui o recurso. O número de automações ativas também é limitado pelo plano.
</Note>

## Eventos

| Evento (`X-Arara-Event`) | Template padrão | Categoria |
| - | - | - |
| `cart.abandoned` | `arara_recovery_cart_abandoned_pt_br` | MARKETING |
| `payment.failed` | `arara_recovery_payment_failed_pt_br` | UTILITY |
| `pix.created` | `arara_recovery_pix_created_pt_br` | UTILITY |
| `boleto.due` | `arara_recovery_boleto_due_pt_br` | UTILITY |

Qualquer outro nome de evento é aceito se houver uma automação escutando ele. Sem automação e sem template, o ingest termina com `UNKNOWN_EVENT`.

## Como funciona

```
1. Sua plataforma faz POST no endpoint     (header X-Arara-Event: cart.abandoned)
   ↓
2. Arara valida endpoint ativo e assinatura (se enviada)
   ↓
3. Normaliza o telefone e checa opt-out
   ↓
4. Resolve o template do evento             (vinculado por você ou o padrão provisionado)
   ↓
5. Envia o template aprovado               (variables.link vira o destino do botão)
   ↓
6. Registra o ingest                        (SENT, REJECTED ou FAILED, com motivo)
```

## Setup

<Steps>
  <Step title="Pegue o endpoint da sua organização">
    ```bash theme={null}
    curl https://api.ararahq.com/v1/recovery/endpoint \
      -H "Authorization: Bearer $ARARA_API_KEY"
    ```

    Responde `{ code, hmacSecret, active, url }`. O endpoint nasce com `active: false`. Os eventos da sua plataforma vão para `https://api.ararahq.com/l/{code}`.
  </Step>

  <Step title="Provisione os templates padrão (opcional)">
    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/recovery/provision-defaults \
      -H "Authorization: Bearer $ARARA_API_KEY"
    ```

    Cria os 4 templates da tabela acima na sua conta e vincula cada um ao seu evento. Responde `{ data: [{ event, templateName, status, error }] }`. Os templates precisam ser aprovados pela Meta antes do primeiro envio.
  </Step>

  <Step title="Ou vincule um template seu a um evento">
    ```bash theme={null}
    curl -X PUT https://api.ararahq.com/v1/recovery/events/cart.abandoned \
      -H "Authorization: Bearer $ARARA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "templateId": "3f1c2a9e-5b7d-4e8a-9c0f-1a2b3c4d5e6f",
        "active": true,
        "variableMapping": { "nome": "1", "produto": "2", "valor": "3" }
      }'
    ```

    `templateId` é o UUID do template. A seção **Variáveis**, abaixo, explica o `variableMapping`.
  </Step>

  <Step title="Ative o endpoint">
    ```bash theme={null}
    curl -X PATCH https://api.ararahq.com/v1/recovery/endpoint \
      -H "Authorization: Bearer $ARARA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "active": true }'
    ```

    Esse interruptor vale para recuperação de um passo (evento para template). Com ele desligado, o evento só é aproveitado por [automações](/automacoes-webhook) ativas que escutam aquele evento; sem nenhuma, a resposta vem `REJECTED` com `reason: NO_ACTIVE_AUTOMATION`.
  </Step>
</Steps>

## Enviando um evento

```bash theme={null}
curl -X POST "https://api.ararahq.com/l/ara_rec_xxx" \
  -H "Content-Type: application/json" \
  -H "X-Arara-Event: cart.abandoned" \
  -H "X-Arara-Idempotency-Key: cart-98765" \
  -H "X-Arara-Signature: sha256=<hex>" \
  -d '{
    "phone": "+5511999999999",
    "name": "João Silva",
    "variables": {
      "nome": "João",
      "produto": "a Camiseta Linho",
      "valor": "R$ 189,90",
      "link": "https://minhaloja.com.br/checkout/98765"
    }
  }'
```

Não precisa de chave de API: o endpoint é identificado pelo `code`.

<Warning>
  O campo `url` devolvido por `GET /v1/recovery/endpoint` aponta para `ararahq.com/l/{code}`, que só aceita `GET` (redirecionamento de links). Envie o `POST` do evento para `https://api.ararahq.com/l/{code}`.
</Warning>

| Header | Obrigatório | Descrição |
| - | - | - |
| `X-Arara-Event` | Sim | Nome do evento. Sem ele, `400 RECOVERY_EVENT_INVALID` |
| `X-Arara-Idempotency-Key` | Não | Repetir a chave devolve o ingest original, sem novo envio |
| `X-Arara-Signature` | Não | HMAC-SHA256 do corpo bruto, em hex, com o `hmacSecret`. O prefixo `sha256=` é opcional |

A resposta é `202` com `{ ingestId, status, reason, messageId }`.

### Assinatura

A assinatura do endpoint de recuperação é calculada **só sobre o corpo bruto** (sem timestamp). Se o header vier e não bater, a resposta é `401 RECOVERY_HMAC_INVALID`. Envie sempre: é o que impede terceiros de disparar mensagens com o seu código.

```javascript theme={null}
import crypto from 'node:crypto';

const rawBody = JSON.stringify(payload);
const signature = 'sha256=' + crypto
  .createHmac('sha256', process.env.ARARA_RECOVERY_SECRET)
  .update(rawBody)
  .digest('hex');

await fetch(`https://api.ararahq.com/l/${recoveryCode}`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Arara-Event': 'cart.abandoned',
    'X-Arara-Idempotency-Key': `cart-${cartId}`,
    'X-Arara-Signature': signature,
  },
  body: rawBody,
});
```

Envie exatamente a string assinada como corpo. Vazou o segredo? `POST /v1/recovery/endpoint/regenerate` gera novo `code` e novo `hmacSecret` (a URL antiga para de funcionar).

<Note>
  Os webhooks que a Arara envia para você usam outro esquema (HMAC de `{timestamp}.{rawBody}`). Ver [Webhooks](/webhooks).
</Note>

### Variáveis

* `variables.link` não entra no corpo do template: vira o destino do botão de link do template, encurtado e rastreado.
* As demais chaves de `variables` são enviadas como variáveis do template **na ordem alfabética das chaves**.
* `variableMapping` renomeia chaves antes dessa ordenação. Pra controlar a ordem, mapeie cada chave para `"1"`, `"2"`, `"3"` na ordem em que aparecem no template (até 9 variáveis).

### Motivos de rejeição

| `reason` | Significado |
| - | - |
| `INVALID_PHONE` | Telefone ausente ou inválido |
| `OPTED_OUT` | O número pediu para não receber mensagens |
| `EVENT_DISABLED` | O evento está vinculado com `active: false` |
| `NO_TEMPLATE` | Nenhum template vinculado nem provisionado para esse evento |
| `UNKNOWN_EVENT` | Evento fora da lista e sem automação escutando |
| `TEMPLATE_NOT_APPROVED` | O template ainda não foi aprovado |

Excesso de eventos por organização responde `429 RECOVERY_RATE_LIMITED` com `Retry-After`.

## Configs, ingests e métricas

```bash theme={null}
# Configs por evento
curl https://api.ararahq.com/v1/recovery/events \
  -H "Authorization: Bearer $ARARA_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "eventType": "cart.abandoned",
      "templateId": "3f1c2a9e-5b7d-4e8a-9c0f-1a2b3c4d5e6f",
      "templateName": "arara_recovery_cart_abandoned_pt_br",
      "active": true,
      "lastTriggeredAt": "2026-09-14T18:22:10Z",
      "templateStatus": "APPROVED",
      "rejectionReason": null
    }
  ]
}
```

```bash theme={null}
# Eventos recebidos (paginado, filtros opcionais event e status)
curl "https://api.ararahq.com/v1/recovery/ingests?page=0&size=20&event=cart.abandoned&status=FAILED" \
  -H "Authorization: Bearer $ARARA_API_KEY"

# Reprocessar um ingest
curl -X POST https://api.ararahq.com/v1/recovery/ingests/ara_ing_xxx/retry \
  -H "Authorization: Bearer $ARARA_API_KEY"

# Métricas
curl "https://api.ararahq.com/v1/recovery/stats?period=LAST_30D" \
  -H "Authorization: Bearer $ARARA_API_KEY"
```

* `ingests` responde `{ content, totalPages, totalElements }`, com `id`, `eventType`, `phone`, `status`, `rejectReason` e `receivedAt` por item.
* `stats` aceita `period` = `TODAY` (default), `YESTERDAY`, `LAST_7D` ou `LAST_30D` e responde `{ period, valueRecovered, valueRecoveredDelta, byEvent }`. O valor recuperado vem das conversões que você reporta (ver [Atribuição de conversão](/smart-links/attribution)).

## Testando sem evento real

```bash theme={null}
curl -X POST https://api.ararahq.com/v1/recovery/events/cart.abandoned/test \
  -H "Authorization: Bearer $ARARA_API_KEY"
```

Processa um payload de exemplo como se viesse da sua plataforma e **envia de verdade** para o telefone cadastrado no seu usuário. O endpoint precisa estar ativo e o template aprovado.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Receita: recuperar carrinho" icon="cart-shopping" href="/recipes/abandoned-cart">
    Fluxo de carrinho abandonado de ponta a ponta.
  </Card>

  <Card title="Atribuição" icon="bullseye" href="/smart-links/attribution">
    Reporte a venda para medir o valor recuperado.
  </Card>
</CardGroup>


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