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

# Cobranças (Pix e link de pagamento)

> Envie um cartão de pagamento dentro do WhatsApp, com Pix copia-e-cola ou link de pagamento, dê baixa quando o cliente pagar e use em conversas, templates e automações.

## O que é

Uma cobrança é um **cartão de pagamento nativo do WhatsApp** que chega dentro da conversa: número da cobrança, itens, total e um botão — **Copiar código Pix** ou **Pagar**, conforme o meio que você usar.

<Note>
  **O WhatsApp não processa o pagamento, e a Arara também não.** O Pix copia-e-cola ou o link vêm do seu banco ou PSP, e o dinheiro cai direto na sua conta. A Arara entrega o cartão e, quando você avisa que foi pago, põe o selo de pago nele.
</Note>

## Por que usar

* **O cliente paga sem sair da conversa.** Sem "entra no site", sem PDF de boleto, sem procurar o código no e-mail.
* **O cartão é nativo.** Não é uma mensagem de texto com um código solto: o WhatsApp mostra itens, total e botão de copiar.
* **O código é conferido antes de sair.** Pix cortado ou com caractere trocado é recusado na API, não no app do banco do seu cliente.
* **Fica registrado.** Cada cobrança tem status, contato, origem e data de pagamento, e alimenta o total gasto do contato.

## Como aparece no WhatsApp

À esquerda, a cobrança recém-enviada. À direita, a mesma cobrança depois que **você** deu baixa.

<div style={{ margin: '24px 0' }}>
  <svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Cartão de cobrança com botão Copiar código Pix e, ao lado, o mesmo cartão com o selo de pago" style={{ width: '100%', height: 'auto', color: 'currentColor' }}>
    <g fill="none" stroke="currentColor" strokeWidth="1.5" opacity="0.5">
      <rect x="16" y="16" width="200" height="328" rx="24" />

      <rect x="368" y="16" width="200" height="328" rx="24" />
    </g>

    <g fill="currentColor" opacity="0.35">
      <rect x="94" y="30" width="44" height="5" rx="2.5" />

      <rect x="446" y="30" width="44" height="5" rx="2.5" />
    </g>

    <g>
      <rect x="34" y="66" width="164" height="178" rx="14" fill="currentColor" opacity="0.07" />

      <rect x="34" y="66" width="164" height="178" rx="14" fill="none" stroke="currentColor" strokeWidth="1" opacity="0.25" />

      <text x="48" y="88" fontFamily="Geist, sans-serif" fontSize="9" fill="currentColor" opacity="0.55">Loja Exemplo</text>
      <text x="48" y="104" fontFamily="Geist, sans-serif" fontSize="10.5" fill="currentColor" opacity="0.9">fatura-2026-10-9912</text>

      <line x1="48" y1="114" x2="184" y2="114" stroke="currentColor" strokeWidth="1" opacity="0.2" />

      <text x="48" y="132" fontFamily="Geist, sans-serif" fontSize="9.5" fill="currentColor" opacity="0.75">Fatura out/2026</text>
      <text x="184" y="132" fontFamily="Geist, sans-serif" fontSize="9.5" fill="currentColor" opacity="0.75" textAnchor="end">R$ 59,90</text>     <text x="48" y="156" fontFamily="Geist, sans-serif" fontSize="10.5" fill="currentColor" opacity="0.9">Total</text>     <text x="184" y="156" fontFamily="Geist, sans-serif" fontSize="11.5" fill="currentColor" opacity="0.95" textAnchor="end">R$ 59,90</text>

      <rect x="48" y="172" width="136" height="22" rx="11" fill="#1c99a7" />

      <text x="116" y="187" fontFamily="Geist, sans-serif" fontSize="9.5" fill="#ffffff" textAnchor="middle">Copiar código Pix</text>
      <text x="48" y="214" fontFamily="Geist, sans-serif" fontSize="8.5" fill="currentColor" opacity="0.5">Aguardando pagamento</text>
      <text x="48" y="232" fontFamily="Geist, sans-serif" fontSize="9" fill="currentColor" opacity="0.7">Segue a fatura de outubro.</text>
    </g>

    <g>
      <text x="291" y="168" fontFamily="Geist, sans-serif" fontSize="9.5" fill="currentColor" opacity="0.6" textAnchor="middle">o cliente paga</text>
      <text x="291" y="182" fontFamily="Geist, sans-serif" fontSize="9.5" fill="currentColor" opacity="0.6" textAnchor="middle">no banco dele e</text>
      <text x="291" y="196" fontFamily="Geist, sans-serif" fontSize="9.5" fill="#1c99a7" textAnchor="middle">você dá baixa</text>

      <g stroke="#1c99a7" strokeWidth="1.5" fill="none">
        <line x1="248" y1="216" x2="334" y2="216" />

        <polyline points="324,208 334,216 324,224" />
      </g>
    </g>

    <g>
      <rect x="386" y="66" width="164" height="178" rx="14" fill="currentColor" opacity="0.07" />

      <rect x="386" y="66" width="164" height="178" rx="14" fill="none" stroke="currentColor" strokeWidth="1" opacity="0.25" />

      <text x="400" y="88" fontFamily="Geist, sans-serif" fontSize="9" fill="currentColor" opacity="0.55">Loja Exemplo</text>
      <text x="400" y="104" fontFamily="Geist, sans-serif" fontSize="10.5" fill="currentColor" opacity="0.9">fatura-2026-10-9912</text>

      <line x1="400" y1="114" x2="536" y2="114" stroke="currentColor" strokeWidth="1" opacity="0.2" />

      <text x="400" y="132" fontFamily="Geist, sans-serif" fontSize="9.5" fill="currentColor" opacity="0.75">Fatura out/2026</text>
      <text x="536" y="132" fontFamily="Geist, sans-serif" fontSize="9.5" fill="currentColor" opacity="0.75" textAnchor="end">R$ 59,90</text>     <text x="400" y="156" fontFamily="Geist, sans-serif" fontSize="10.5" fill="currentColor" opacity="0.9">Total</text>     <text x="536" y="156" fontFamily="Geist, sans-serif" fontSize="11.5" fill="currentColor" opacity="0.95" textAnchor="end">R$ 59,90</text>

      <rect x="400" y="172" width="90" height="22" rx="11" fill="none" stroke="#1c99a7" strokeWidth="1.2" />

      <text x="445" y="187" fontFamily="Geist, sans-serif" fontSize="9.5" fill="#1c99a7" textAnchor="middle">Pago</text>

      <polyline points="502,183 508,189 520,175" fill="none" stroke="#1c99a7" strokeWidth="2" strokeLinecap="round" />

      <text x="400" y="214" fontFamily="Geist, sans-serif" fontSize="8.5" fill="currentColor" opacity="0.5">Pagamento confirmado</text>
      <text x="400" y="232" fontFamily="Geist, sans-serif" fontSize="9" fill="currentColor" opacity="0.7">Recebemos o pagamento.</text>
    </g>
  </svg>
</div>

O ciclo tem dois passos e os dois são seus: **enviar a cobrança** e **dar baixa**.

## Como faço

<Steps>
  <Step title="Envie a cobrança na conversa (janela de 24h aberta)">
    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/messages \
      -H "Authorization: Bearer ara_live_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "receiver": "5588999990000",
        "interactive": {
          "type": "charge",
          "body": "Segue a fatura de outubro. É só tocar no botão pra pagar.",
          "charge": {
            "referenceId": "fatura-2026-10-9912",
            "items": [{ "name": "Fatura out/2026", "amountCents": 5990, "quantity": 1 }],
            "pix": {
              "code": "00020126580014br.gov.bcb.pix...6304ABCD",
              "key": "39580525000189",
              "keyType": "CNPJ",
              "merchantName": "Loja Exemplo"
            }
          }
        }
      }'
    ```

    Com link de pagamento, troque o bloco `pix` por:

    ```json theme={null}
    "paymentLink": { "url": "https://pay.seupsp.com/c/abc123" }
    ```

    Valores sempre **em centavos**.

    No dashboard, o mesmo envio sai do link **Cobrar** na caixa de Conversas: você cola o Pix e a tela lê valor, nome de quem recebe e chave do próprio código.

    <Frame caption="Conversas: o painel Cobrar com o Pix colado, o valor lido do código e o total no botão de enviar.">
      <img src="https://mintcdn.com/arara/581xFdBhHj9cwuGo/images/cobrancas-conversa-cobrar.png?fit=max&auto=format&n=581xFdBhHj9cwuGo&q=85&s=2cfe5e2291d98ef1ecffe7434ff1bb48" alt="Painel de nova cobrança na caixa de Conversas do dashboard da Arara" width="354" height="600" data-path="images/cobrancas-conversa-cobrar.png" />
    </Frame>
  </Step>

  <Step title="Dê baixa quando o pagamento cair">
    Quando o seu banco ou PSP confirmar, avise a Arara. O cartão ganha o selo de pago.

    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/messages \
      -H "Authorization: Bearer ara_live_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "receiver": "5588999990000",
        "interactive": {
          "type": "charge_status",
          "body": "Recebemos o pagamento. Obrigado!",
          "chargeStatus": { "referenceId": "fatura-2026-10-9912", "status": "PAID" }
        }
      }'
    ```

    `status` aceita `PAID`, `FAILED` (o pagamento não passou; a cobrança segue em aberto) e `CANCELED`. `description` é opcional, até 120 caracteres.

    Com a conversa fechada, a baixa sai pelo painel (`PUT /v1/charges/{id}/status` por trás): ela é registrada de qualquer jeito, e o cartão no WhatsApp só é atualizado quando a janela de 24h deixa.

    No dashboard, as cobranças em aberto da conversa aparecem com **Marcar como paga** e **Cancelar**.

    <Frame caption="Conversas: as cobranças em aberto do contato, com os botões Marcar como paga e Cancelar.">
      <img src="https://mintcdn.com/arara/581xFdBhHj9cwuGo/images/cobrancas-marcar-como-paga.png?fit=max&auto=format&n=581xFdBhHj9cwuGo&q=85&s=77fd5bcb3a3a97ecb3a4e2bbbd67296e" alt="Lista de cobranças em aberto de um contato, com ações de baixa" width="352" height="288" data-path="images/cobrancas-marcar-como-paga.png" />
    </Frame>
  </Step>

  <Step title="Fora da janela, cobre por template">
    Pra cobrar quem não falou com você nas últimas 24h, crie um template com o botão de cobrança. Ele precisa ser o **único** botão do template.

    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/templates \
      -H "Authorization: Bearer ara_live_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "fatura_pix",
        "category": "UTILITY",
        "language": "pt_BR",
        "body": "Oi {{nome}}, sua fatura de {{mes}} chegou.",
        "buttons": [{ "type": "CHARGE", "text": "Pagar com Pix" }]
      }'
    ```

    Depois de aprovado, envie o template com o mesmo objeto `charge` do envio na conversa:

    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/messages \
      -H "Authorization: Bearer ara_live_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "receiver": "5588999990000",
        "templateName": "fatura_pix",
        "templateVariables": ["Maria", "outubro"],
        "charge": {
          "referenceId": "fatura-2026-10-9912",
          "items": [{ "name": "Fatura out/2026", "amountCents": 5990 }],
          "pix": { "code": "000201...", "key": "39580525000189", "keyType": "CNPJ", "merchantName": "Loja Exemplo" }
        }
      }'
    ```

    Template com botão de cobrança **exige** `charge`; template sem o botão recusa `charge`.
  </Step>
</Steps>

## O que pode dar errado

### A cobrança não muda de estado sozinha

Esse é o ponto que mais gera dúvida, então sem rodeio: **a Arara não sabe que o cliente pagou.** O Pix cai no seu banco, não aqui. Enquanto ninguém avisar, a cobrança fica `PENDING` pra sempre, e o cartão no WhatsApp continua "aguardando pagamento" mesmo com o dinheiro já na sua conta.

Existem dois jeitos de avisar, e você precisa de um deles:

1. **Alguém marca como paga no painel** — ou o seu código manda o `charge_status` por `POST /v1/messages`.
2. **O seu sistema posta no gancho da automação**: um `POST` no link da automação com `{ "referenceId": "...", "status": "paid" }`. É o caminho pra automatizar — o seu backend, ao receber a confirmação do PSP, repassa pro gancho. `status` aceita `paid`, `failed`, `canceled` e `expired`.

A única mudança automática é o vencimento: se você mandou `expiresAt` e o prazo passa sem baixa, a Arara marca `EXPIRED` sozinha. No WhatsApp ela aparece como cancelada, porque o cartão não tem estado de vencido. Sem `expiresAt`, nem isso acontece.

### Um meio de pagamento por cobrança

Ou `pix`, ou `paymentLink`. Mandar os dois é recusado ("por enquanto é um meio de pagamento por cobrança"), e não mandar nenhum também. Não existe cartão com as duas opções.

### O Pix é conferido antes de sair

Erro de cobrança aparece no celular do seu cliente, então a API recusa cedo, com `422` e a frase do problema:

* **Código que não é Pix copia-e-cola**, ou **cortado**: todo BR Code termina em `6304` + um dígito verificador (CRC16). A Arara recalcula.
* **Caractere trocado**: o CRC não fecha e o envio é recusado com "copie de novo do banco".
* **Total diferente do valor dentro do Pix**: se o código fixa valor e ele não bate com o total dos itens, o envio é recusado. Sem isso, o cartão mostraria um número e o banco cobraria outro. Pix sem valor fixo (dinâmico) passa.
* **`referenceId` repetido**, total zerado ou negativo, item sem nome, valor ou quantidade não positivos, vencimento a menos de 5 minutos, link sem `https`.

Na conversa, a cobrança só é registrada depois que o provedor aceita o envio: envio que falha não queima o `referenceId`. **Com template é diferente**: o template vai pra fila, então a cobrança é registrada já no enfileiramento. Se o envio falhar depois, aquele `referenceId` ficou usado — reenvie com outro.

### Cobrança encerrada não volta atrás

Cobrança `PAID`, `CANCELED` ou `EXPIRED` não aceita outro status. Reenviar o mesmo status é permitido (é o caso do cartão que precisa alcançar uma baixa que entrou pelo gancho), qualquer outro é recusado. `FAILED` não encerra: a cobrança segue em aberto.

A baixa por mensagem (`charge_status`) é mensagem de sessão, então depende da janela de 24h. Como pagamento costuma ser confirmado em minutos, na prática ela está aberta — e quando não está, o caminho é o `PUT`.

<Warning>
  Campanhas ainda não enviam cobrança por contato. Um template de cobrança escolhido numa campanha é recusado na criação. Use a API ou uma automação.
</Warning>

## Em automações

Num passo de mensagem com template de cobrança, você diz de onde vem cada dado. Cada campo aceita texto fixo ou `{{variavel}}` do evento que dispara a automação:

```json theme={null}
{
  "templateId": "…",
  "variables": ["nome"],
  "charge": {
    "referenceId": "pedido-{{order_id}}",
    "description": "{{product}}",
    "amountCents": "{{amount_cents}}",
    "pixCode": "{{pix_code}}",
    "pixKey": "39580525000189",
    "pixKeyType": "CNPJ",
    "merchantName": "Loja Exemplo"
  }
}
```

Pra link de pagamento, use `"paymentLink": "{{payment_url}}"` no lugar dos campos de Pix. O seu sistema gera o Pix ou o link e manda no evento (`payment.failed`, `cart.abandoned` ou webhook próprio); a automação monta e envia a cobrança. As mesmas conferências do envio pela API valem aqui.

### Saber se pagou dentro da automação

O caminho recomendado é o [link da automação](/automacoes-webhook): o seu sistema manda a cobrança pronta num `POST`, a automação envia e para no passo `wait_payment`, e um segundo `POST` no mesmo link avisa `paid`. A execução segue por `paid` ou `unpaid`, sem mapear `{{variaveis}}`.

Os gatilhos `charge.paid` e `charge.expired` iniciam uma automação quando qualquer cobrança da conta chega nesse status.

## Referência

### Campos da cobrança

| Campo                                          | Regra                                                                                                                               |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `body`                                         | Obrigatório, até 1024 caracteres.                                                                                                   |
| `charge.referenceId`                           | Seu número da cobrança. Até 60 caracteres: letras, números, `.`, `-` e `_`. **Único por organização**: é com ele que você dá baixa. |
| `charge.items`                                 | De 1 a 10. `name` até 60 caracteres, `amountCents` e `quantity` positivos. `id` opcional (seu SKU).                                 |
| `charge.shippingCents`, `charge.discountCents` | Opcionais, não negativos. O total do cartão é itens + frete − desconto.                                                             |
| `charge.expiresAt`                             | Opcional, epoch em segundos, pelo menos 5 minutos à frente.                                                                         |
| `charge.pix`                                   | `code` (copia-e-cola), `key`, `keyType` (`CPF`, `CNPJ`, `EMAIL`, `PHONE` ou `EVP`) e `merchantName`.                                |
| `charge.paymentLink`                           | `url` em `https`.                                                                                                                   |

### Cobrança e contato

Toda cobrança fica ligada ao contato do telefone. Quando ela é paga, o contato tem o total gasto, o número de compras e a última compra atualizados.

### Consultar

<Note>
  Enviar cobrança e dar baixa por mensagem passam por `POST /v1/messages`, que aceita API key. Já os caminhos `/v1/charges/**` — lista, detalhe, resumo e baixa direta — respondem hoje só à sessão do painel: com `ara_live_...` a resposta é 403. Pra acompanhar status no seu backend, use os eventos `charge.*` do webhook.
</Note>

```bash theme={null}
GET /v1/charges?page=0&size=20&status=PENDING
```

| Filtro         | Valores                                               |
| -------------- | ----------------------------------------------------- |
| `status`       | `PENDING`, `PAID`, `FAILED`, `CANCELED` ou `EXPIRED`. |
| `source`       | `CONVERSATION`, `TEMPLATE`, `AUTOMATION` ou `HOOK`.   |
| `contactId`    | Só as cobranças de um contato.                        |
| `receiver`     | Só as cobranças de um telefone.                       |
| `q`            | Busca por texto.                                      |
| `page`, `size` | Paginação.                                            |

Devolve `{ data, pagination }`. Cada item:

```json theme={null}
{
  "id": "3f1c9a20-5b7d-4e8a-9c11-2d4e6f8a0b12",
  "referenceId": "pedido-1042",
  "description": "Plano mensal",
  "totalCents": 5990,
  "method": "PIX",
  "status": "PAID",
  "source": "HOOK",
  "contact": { "id": "a1b2c3d4-...", "name": "Ana", "phone": "5588999990000" },
  "customerNumber": "5588999990000",
  "automationId": "0e4f3c1e-...",
  "automationName": "Cobrança do plano mensal",
  "runId": "7c1d2e90-...",
  "createdAt": "2026-09-20T14:02:11Z",
  "statusUpdatedAt": "2026-09-20T14:09:40Z",
  "paidAt": "2026-09-20T14:09:40Z",
  "expiresAt": "2026-09-21T12:00:00Z"
}
```

`method` é `PIX` ou `PAYMENT_LINK`. `contact` pode vir `null`; `automationId`, `automationName` e `runId` só vêm preenchidos quando a cobrança saiu de uma automação. O código Pix e o link **não são guardados** pela Arara.

| Endpoint                          | O que devolve                                                                                                                                                             |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /v1/charges/{id}`            | Uma cobrança.                                                                                                                                                             |
| `GET /v1/charges?contactId={id}`  | As cobranças de um contato.                                                                                                                                               |
| `PUT /v1/charges/{id}/status`     | Dá baixa direto: `{ "status": "PAID" \| "CANCELED" \| "FAILED" }`. Funciona com a conversa fechada; `cardUpdated` na resposta diz se o cartão no WhatsApp foi atualizado. |
| `GET /v1/charges/summary?days=30` | O resumo do período.                                                                                                                                                      |

```json theme={null}
{
  "pendingCount": 12,
  "pendingCents": 71880,
  "paidCount": 48,
  "paidCents": 287520,
  "expiredCount": 5,
  "conversionRate": 0.74
}
```

Pra receber cada mudança de status no seu backend, use os eventos [`charge.*`](/webhooks/events#cobranças).

<Frame caption="Cobranças: a lista com os filtros de status e origem, mostrando cobranças em aberto, pagas e vencidas.">
  <img src="https://mintcdn.com/arara/581xFdBhHj9cwuGo/images/cobrancas-lista.png?fit=max&auto=format&n=581xFdBhHj9cwuGo&q=85&s=89159be9148b5576085460e7447328b8" alt="Lista de cobranças no dashboard da Arara, com filtros por status e origem" width="790" height="745" data-path="images/cobrancas-lista.png" />
</Frame>
