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

# Carrinho abandonado

> Envie o evento de carrinho abandonado para a Arara, dispare uma mensagem ou uma sequência com espera e pare quando o cliente comprar.

Ao final, sua loja avisa a Arara a cada carrinho abandonado, o cliente recebe uma ou mais mensagens com o link do checkout, e a sequência para sozinha quando ele compra.

A detecção do abandono é do seu lado. A Arara não observa o checkout da loja.

## Antes de começar

* Chave de API na variável `ARARA_API_KEY`. Ver [Autenticação](/api-reference/authentication).
* Número conectado na organização. Ver [Números](/numbers).
* Um template `MARKETING` aprovado para cada mensagem da sequência (o passo 1 cria). Ver [Templates](/concepts/templates).
* Recuperação de receita e automações disponíveis no seu plano. Sem acesso, `/v1/recovery/*` e `/v1/automations` respondem `403 PLAN_FEATURE_LOCKED`.

O contrato completo do endpoint de recuperação (headers, variáveis, motivos de recusa) está em [Recuperação de receita](/recovery). Aqui fica o passo a passo.

## Passo a passo

<Steps>
  <Step title="Crie o template">
    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/templates \
      -H "Authorization: Bearer $ARARA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "carrinho_abandonado_v1",
        "category": "MARKETING",
        "language": "pt_BR",
        "body": "Oi {{1}}, seu carrinho ficou salvo. Quer finalizar a compra?\n\n{{2}}",
        "samples": { "1": "João", "2": "https://meusite.com/checkout/abc" }
      }'
    ```

    A resposta traz o `id` (UUID), usado como `templateId` nos próximos passos. Acompanhe a aprovação com `GET /v1/templates/{id}/status` ou pelo webhook `template.updated`.
  </Step>

  <Step title="Pegue o endpoint de recuperação">
    Cada organização tem um endpoint próprio. Busque pelo [painel](https://app.ararahq.com), em **Recuperação**, ou pela API:

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

    ```json theme={null}
    {
      "code": "ara_rec_...",
      "hmacSecret": "...",
      "active": false,
      "url": "https://.../l/ara_rec_..."
    }
    ```

    Guarde no servidor `ARARA_RECOVERY_URL` como `https://api.ararahq.com/l/{code}` e `ARARA_RECOVERY_SECRET` com o `hmacSecret`. O `hmacSecret` nunca vai para o navegador.
  </Step>

  <Step title="Envie o evento quando o carrinho for abandonado">
    ```typescript theme={null}
    // notify-cart-abandoned.ts
    import { createHmac } from 'node:crypto';

    const TIMEOUT_MS = 10_000;

    interface AbandonedCart {
      id: string;
      customerName: string;
      phone: string; // E.164, ex.: +5511999999999
      totalFormatted: string;
      checkoutUrl: string;
    }

    export async function notifyCartAbandoned(cart: AbandonedCart) {
      const body = JSON.stringify({
        phone: cart.phone,
        name: cart.customerName,
        variables: {
          nome: cart.customerName,
          valor: cart.totalFormatted,
          link: cart.checkoutUrl,
        },
      });

      const signature = createHmac('sha256', process.env.ARARA_RECOVERY_SECRET!)
        .update(body)
        .digest('hex');

      const response = await fetch(process.env.ARARA_RECOVERY_URL!, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Arara-Event': 'cart.abandoned',
          'X-Arara-Idempotency-Key': `cart-${cart.id}`,
          'X-Arara-Signature': `sha256=${signature}`,
        },
        body,
        signal: AbortSignal.timeout(TIMEOUT_MS),
      });

      return response.json(); // { ingestId, status, reason, messageId }
    }
    ```

    * `X-Arara-Event` diz qual evento aconteceu. É ele que liga o evento ao template ou à automação.
    * `X-Arara-Idempotency-Key` vem do id do carrinho. Repetir a chave não envia de novo nem inicia a automação duas vezes.
    * `X-Arara-Signature` é o HMAC do **corpo cru**, sem timestamp. É diferente dos [webhooks que a Arara envia para você](/webhooks).
    * A chave `link` de `variables` vira o destino do botão de smart link do template. As outras preenchem o corpo.

    A resposta é `202`. Os valores de `status` e `reason` estão em [Recuperação de receita](/recovery).
  </Step>

  <Step title="Escolha: uma mensagem ou uma sequência">
    <Tabs>
      <Tab title="Uma mensagem">
        Vincule o template ao evento. O envio sai assim que o evento chega.

        ```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": "0b8f6c1e-7a52-4a1b-9a0e-3f2d6c9e1a44",
            "active": true
          }'
        ```

        `templateId` é o UUID do template, não o nome. As variáveis entram **em ordem alfabética da chave** (`link` fica de fora): com `nome` e `valor`, `{{1}}` recebe `nome` e `{{2}}` recebe `valor`. Para mudar a ordem, use `variableMapping`, explicado em [Recuperação de receita](/recovery).

        Depois, ligue 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 }'
        ```
      </Tab>

      <Tab title="Sequência com espera">
        Uma automação executa passos em ordem para cada contato que entra. Monte no painel, em **Automações**, ou pela API:

        ```bash theme={null}
        curl -X POST https://api.ararahq.com/v1/automations \
          -H "Authorization: Bearer $ARARA_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{
            "name": "Carrinho abandonado",
            "trigger": "cart.abandoned",
            "steps": [
              { "type": "wait", "config": { "minutes": 60 } },
              { "type": "condition", "config": { "tag": "comprou" } },
              { "type": "message", "config": { "templateId": "0b8f6c1e-7a52-4a1b-9a0e-3f2d6c9e1a44", "variables": ["nome", "link"] } },
              { "type": "wait", "config": { "minutes": 1380 } },
              { "type": "condition", "config": { "tag": "comprou" } },
              { "type": "message", "config": { "templateId": "5d2a9b7c-1e44-4f0a-8c3b-6a7e2d1f9b10", "variables": ["nome", "link"] } }
            ]
          }'
        ```

        | Passo (`type`) | `config` | O que faz |
        | - | - | - |
        | `wait` | `{ "minutes": 60 }` | Espera de 1 minuto a 30 dias. |
        | `condition` | `{ "tag": "comprou" }` | Continua **só se o contato ainda não tem** a etiqueta. Se tiver, a sequência para. |
        | `message` | `{ "templateId": "<uuid>", "variables": ["nome", "link"] }` | Envia um template aprovado. `variables` lista as chaves do payload, na ordem de `{{1}}`, `{{2}}`... |
        | `tag` | `{ "tag": "recebeu_lembrete" }` | Aplica uma etiqueta no contato. |

        A automação nasce desligada. Ligue com:

        ```bash theme={null}
        curl -X PUT https://api.ararahq.com/v1/automations/{id}/active \
          -H "Authorization: Bearer $ARARA_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{ "active": true }'
        ```

        A automação ativa roda mesmo com o endpoint de recuperação desligado (`active: false`). O plano define quantas automações ficam ligadas ao mesmo tempo. Mais em [Automações por webhook](/automacoes-webhook).
      </Tab>
    </Tabs>
  </Step>

  <Step title="Pare a sequência quando o cliente comprar">
    Quando o pedido for confirmado, aplique a etiqueta usada no passo `condition`:

    ```bash theme={null}
    curl -X PATCH "https://api.ararahq.com/v1/contacts/%2B5511999999999" \
      -H "Authorization: Bearer $ARARA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "tags": ["comprou"] }'
    ```

    * `tags` **substitui** a lista inteira de etiquetas do contato. Leia as atuais com `GET /v1/contacts/{phone}` e envie a lista completa.
    * O contato precisa existir na organização. Se não existir, a API responde erro.
    * O `+` do telefone vai codificado na URL (`%2B`).
  </Step>

  <Step title="Teste e acompanhe">
    `POST /v1/recovery/events/cart.abandoned/test` processa um payload de exemplo e **envia de verdade** para o telefone cadastrado no seu usuário. O endpoint precisa estar ligado.

    * `GET /v1/recovery/ingests?event=cart.abandoned&status=REJECTED` lista os eventos recebidos com o motivo de recusa. `POST /v1/recovery/ingests/{id}/retry` reprocessa um deles.
    * `GET /v1/recovery/stats?period=LAST_7D` traz os números agregados.
    * O webhook `message.status_updated` traz o status de cada mensagem.
    * Três ou mais falhas ou recusas em 5 minutos geram um alerta no painel.
  </Step>
</Steps>

## Armadilhas

<Warning>
  O evento é entregue para as automações **e** para a recuperação de um passo. Com automação ativa para `cart.abandoned` e também um template vinculado ao evento (ou o template padrão `arara_recovery_cart_abandoned_pt_br`, criado por `POST /v1/recovery/provision-defaults`), o cliente recebe as duas mensagens. Para usar só a automação, desligue o evento com `PUT /v1/recovery/events/cart.abandoned` e `{ "active": false }`. Nesse caso a resposta do `POST` vem `REJECTED` com `EVENT_DISABLED`, mesmo com a automação iniciada.
</Warning>

* **Resposta do cliente não para a sequência.** Para parar quando ele responder, escute o webhook `message.received` e aplique a etiqueta.
* **Opt-out é recusado.** Evento para contato que pediu para sair volta `REJECTED` com `OPTED_OUT`.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Recuperação de receita" icon="rotate-right" href="/recovery">
    Contrato do endpoint e os outros eventos de pagamento.
  </Card>

  <Card title="Shopify" icon="cart-shopping" href="/integracoes/shopify">
    Ligue uma loja Shopify a este fluxo.
  </Card>

  <Card title="Atendimento com vários atendentes" icon="users" href="/recipes/inbox-support">
    Quem atende quando o cliente responde.
  </Card>
</CardGroup>


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