Guia — Bot WhatsApp via API
Integre seu bot existente
Para merchants que já têm WhatsApp + bot próprios. A Bumcash entrega os dados (saldo do cliente, rede de aceitação, configuração do merchant) via API REST; seu bot continua falando pelo seu canal. Sem conexão WhatsApp pelo lado da Bumcash.
Se você quer que a Bumcash cuide do canal, veja a integração WhatsApp gerenciada (caminho separado).
Modelo mental — leia antes dos curls
A integração tem dois identificadores assimétricos:
| Dimensão | CPF | Telefone |
|---|---|---|
| Validação | Validado na ativação | Sem validação automática |
| Imutabilidade | Permanente | Muda; operadoras reciclam após ~90d |
| Papel | Identifica o cliente | Canal de comunicação |
O bot recebe telefone do WhatsApp. Quando consulta a API por telefone, a resposta é uma de três:
| Estado | Significado | Ação do bot |
|---|---|---|
| verified | Caller tem vínculo + telefone atestado nos últimos 12 meses. | Use os dados retornados normalmente. |
| stale | Vínculo existe mas o telefone foi atestado há mais de 12 meses. | Peça CPF e chame POST /customers/{cpf}/confirm-phone. |
| indistinguishable | Telefone não existe na sua base OU pertence a outro merchant (resposta bit-a-bit idêntica). | Peça CPF e use lookup por CPF / register. |
Por CPF a resposta é mais informativa (três estados claros: linked, exists_not_linked, not_exists) porque CPF não é enumerável da mesma forma.
Pré-requisitos
- CNPJ aprovado pela equipe Bumcash (status approved no portal).
- Termos de Uso aceitos no portal.
- Pelo menos uma location ativa.
- Chave Merchant (bmc_test_mch_… para sandbox, bmc_live_mch_… para produção) com customers:query e customers:register — ou chave Partner (ptr_) se você integra os lojistas; veja a seção Chaves Partner abaixo.
Demais permissões (payments:create, recurring:bill_payment, etc.) conforme o bot evoluir para fechar transações — não são necessárias para consultas.
URL base
https://api-v2.bumcash.com.br/v1Passo 1
Descobrir sua própria configuração
Antes do primeiro inbound, descubra as taxas do seu merchant para que o bot possa responder "se você comprar R$ 100, ganha R$ X em bumcash" sem chutar.
/v1/locations/meperm: mch_ onlycurl https://api-v2.bumcash.com.br/v1/locations/me \
-H "Authorization: Bearer bmc_test_mch_xxxxxxxxxxxxxxxxxx"{
"merchant": {
"org_id": "org_xyz",
"name": "Pizzaria do John",
"company_type": "retail",
"approved": true
},
"locations": [
{
"id": "loc_f1b2",
"name": "Matriz",
"pos_cashback_rate": 30,
"coin_acceptance_rate": 30,
"recurrency_conversion_rate": 100,
"credit_expiration_days": 29,
"billing_cycle": "monthly",
"address": { "city": "São Paulo", "state": "SP" }
}
]
}Cache esse retorno no seu bot. As taxas mudam raramente — atualizar uma vez por dia é suficiente.
Passo 2
Identificar o cliente do inbound
Cliente mandou "saldo" pelo WhatsApp. O bot sabe o telefone do remetente. Antes de personalizar a resposta, consulte:
/v1/customers/lookupperm: customers:querycurl 'https://api-v2.bumcash.com.br/v1/customers/lookup?phone=%2B5511987654321' \
-H "Authorization: Bearer bmc_test_mch_xxxxxxxxxxxxxxxxxx"Rate limit: 100 req/min por chave (bucket customers.lookup). 429 vem com header Retry-After.
2.1 — Cliente vinculado e telefone atualizado
{
"by": "phone",
"exists": true,
"linked_to_caller": true,
"phone_confidence": "verified",
"customer": {
"id": "cust_a1b2c3",
"status": "active",
"registered_at_caller": "2026-04-10T14:00:00.000Z",
"activated_at_caller": "2026-05-02T09:12:00.000Z",
"external_reference_id": "john_subscription_42",
"phone": "+5511987654321"
}
}Bot pode prosseguir — consultar saldo, exibir histórico, etc.
2.2 — Vinculado mas telefone está stale (>12 meses)
{
"by": "phone",
"exists": true,
"linked_to_caller": true,
"phone_confidence": "stale",
"requires_phone_refresh": true,
"customer": { "id": "cust_a1b2c3", "status": "active" }
}Bot deve pedir CPF ao cliente, depois chamar POST /customers/{cpf}/confirm-phone (Passo 4).
2.3 — Não distinguível (anti-enumeration)
{
"by": "phone",
"exists": null,
"linked_to_caller": false,
"requires_cpf_confirmation": true
}Pode ser:
- • Telefone novo (lead potencial)
- • Telefone de cliente de outro merchant
- • Telefone reciclado pela operadora
Passo 3
Consultar o saldo
Com phone_confidence: "verified" (ou após confirmar via CPF):
/v1/customers/:phone/balanceperm: customers:querycurl 'https://api-v2.bumcash.com.br/v1/customers/+5511987654321/balance' \
-H "Authorization: Bearer bmc_test_mch_xxxxxxxxxxxxxxxxxx"{
"customer_id": "cust_a1b2c3",
"balance": 5045,
"balance_brl": "50,45",
"tier": { "name": "Ouro", "consecutive_payments": 8 },
"expiration": {
"expiring_within_7_days": 0,
"expiring_within_30_days": 5045,
"next_expiration_at": "2026-06-19T00:00:00.000Z",
"next_expiration_amount": 5045
}
}Use balance (centavos) ou balance_brl (string formatada) na resposta do bot. Se expiring_within_7_days > 0, considere alertar o cliente que o saldo está prestes a expirar.
Rate limit: 60 req/min por chave (bucket customers.balance).
| HTTP | error.code | Causa | O que fazer |
|---|---|---|---|
| 403 | phone_verification_stale | Vínculo existe mas o telefone está stale. | Use confirm-phone (Passo 4). |
| 404 | customer_not_linked_by_phone | Telefone não tem vínculo OU não existe (resposta indistinguível). | Peça o CPF. |
| 404 | customer_not_linked | Lookup por CPF resultou em "existe mas não é seu cliente". | Use customers/register antes. |
Passo 4
Renovar atestado do telefone após coletar CPF
Quando o lookup retornou stale ou indistinguishable, o bot pediu o CPF ao cliente. Para reatar o vínculo e desbloquear consultas por telefone:
/v1/customers/:cpf/confirm-phoneperm: customers:registercurl -X POST 'https://api-v2.bumcash.com.br/v1/customers/12345678909/confirm-phone' \
-H "Authorization: Bearer bmc_test_mch_xxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"phone": "+5511987654321",
"idempotency_key": "renovar_john_2026-05-21"
}'{
"customer_id": "cust_a1b2c3",
"phone": "+5511987654321",
"phone_verified_at": "2026-05-21T15:30:00.000Z"
}Rate limit: 60 req/min por chave (bucket customers.confirm_phone).
| HTTP | error.code | Causa | O que fazer |
|---|---|---|---|
| 404 | customer_not_found | CPF não existe OU existe mas você não tem vínculo (mesma proteção anti-enumeration). | Confira o CPF com o cliente. |
| 409 | phone_conflict | O telefone já está atrelado a outro cliente seu. | Confirme o número com o cliente. |
| 400 | invalid_cpf | CPF não passa na validação de dígito verificador. | Reconfirme com o cliente. |
Passo 5
"Onde posso usar?" — descoberta da rede
Cliente perguntou pela rede de aceitação. Use coordenadas (se o bot tiver) ou apenas cidade:
/v1/network/locationsperm: —curl 'https://api-v2.bumcash.com.br/v1/network/locations?near=-23.5505,-46.6333&radius_km=5&limit=10' \
-H "Authorization: Bearer bmc_test_mch_xxxxxxxxxxxxxxxxxx"curl 'https://api-v2.bumcash.com.br/v1/network/locations?city=S%C3%A3o%20Paulo&state=SP&limit=10' \
-H "Authorization: Bearer bmc_test_mch_xxxxxxxxxxxxxxxxxx"{
"data": [
{
"id": "loc_f1b2",
"name": "Pizzaria do John",
"category": "alimentacao",
"address": {
"street": "Rua das Flores",
"number": "123",
"neighborhood": "Vila Mariana",
"city": "São Paulo",
"state": "SP",
"zipCode": "04101-000"
},
"phone": "+551155554444",
"coin_acceptance_rate": 30,
"operating_hours": { "mon": { "open": "11:00", "close": "23:00" } },
"logo_url": "https://cdn.bumcash.com.br/logos/location/loc_f1b2/v3.webp",
"distance_km": 1.4
}
],
"has_more": true,
"cursor": null
}Cada item traz logo_url — o logo da loja, com fallback para o logo do lojista (null quando nenhum foi enviado). Use direto no cabeçalho do template ou no card da lista.
Para montar templates de WhatsApp (lista interativa, carrossel), passe compact=true: os mesmos dados, mas com address e operating_hours achatados em strings (address, hours) — cada campo mapeia direto numa variável de template:
curl 'https://api-v2.bumcash.com.br/v1/network/locations?near=-23.5505,-46.6333&radius_km=5&limit=10&compact=true' \
-H "Authorization: Bearer bmc_test_mch_xxxxxxxxxxxxxxxxxx"{
"data": [
{
"id": "loc_f1b2",
"name": "Pizzaria do John",
"category": "alimentacao",
"address": "Rua das Flores, 123, Vila Mariana, São Paulo/SP",
"phone": "+551155554444",
"hours": "11:00-23:00",
"coin_acceptance_rate": 30,
"logo_url": "https://cdn.bumcash.com.br/logos/location/loc_f1b2/v3.webp",
"distance_km": 1.4
}
],
"has_more": true,
"cursor": null
}hours é o horário de hoje (fuso de São Paulo) — null quando a loja não abre hoje. A agenda completa por dia continua na versão não-compacta (operating_hours).
No modo geo, paginação se faz aumentando o radius_km (máx 50); não há cursor. No modo lista (sem near), use cursor + has_more normalmente. Recurrency é excluída por default (sem balcão).
Chaves Partner — bot para os clientes dos seus lojistas
Todo este guia também funciona com chave Partner (bmc_test_ptr_… / bmc_live_ptr_…): um integrador pode operar o bot em nome dos lojistas que atende. Os quatro endpoints de cliente (lookup, balance, confirm-phone, register) aceitam ptr_ com as mesmas permissões (customers:query / customers:register, já inclusas no conjunto padrão da chave Partner), os mesmos três estados e a mesma anti-enumeration. Três diferenças:
- • Vínculo: sua chave enxerga os clientes registrados/ativados nas locations que você integra (vinculadas ao seu
org_idde integrador), ou com transação nessas locations nos últimos 12 meses. Clientes de lojistas fora da sua carteira aparecem comonot linked/indistinguishable, igual para qualquer outro caller. - • Register: chaves Partner devem identificar o lojista alvo com
cnpjOUlocation_id(exatamente um) — chaves Merchant não enviam nenhum dos dois. A atribuição do cliente vai para o lojista (não para o integrador). - • Configuração: em vez de
GET /locations/me(que responde 403wrong_scopeparaptr_), useGET /v1/locations/lookup?cnpj=…para as taxas de uma location específica.
curl 'https://api-v2.bumcash.com.br/v1/customers/lookup?phone=%2B5511987654321' \
-H "Authorization: Bearer bmc_test_ptr_xxxxxxxxxxxxxxxxxx"
curl 'https://api-v2.bumcash.com.br/v1/locations/lookup?cnpj=11222333000181' \
-H "Authorization: Bearer bmc_test_ptr_xxxxxxxxxxxxxxxxxx"Fluxo recomendado de bot
inbound ──▶ GET /customers/lookup?phone=...
│
├─▶ verified ─────────▶ atendimento personalizado (saldo, histórico, …)
│
├─▶ stale ────────────▶ "Para sua segurança, me passa seu CPF?"
│ └─▶ POST /customers/{cpf}/confirm-phone
│
└─▶ indistinguishable ▶ "Olá! Você é cliente Bumcash? Me passa seu CPF."
├─ já é cliente seu: POST /customers/{cpf}/confirm-phone
└─ ainda não: POST /customers/registerArmazene (phone, cpf, customer_id) no banco do bot após cada confirmação. Próximas conversas pelo mesmo telefone vão direto ao caminho verified.
Erros que você vai encontrar
| HTTP | error.code | Causa | O que fazer |
|---|---|---|---|
| 400 | invalid_identifier | Lookup sem cpf nem phone, ou com ambos. | Envie exatamente um. |
| 400 | invalid_cpf | CPF não passa no dígito verificador. | Reconfirme com o cliente. |
| 403 | phone_verification_stale | Telefone vinculado mas atestado há mais de 12 meses. | Peça CPF, chame confirm-phone. |
| 403 | wrong_scope | Chave Partner em /locations/me, ou chave Merchant em /locations/lookup. | Merchant: use /locations/me. Partner: use /locations/lookup?cnpj=. |
| 404 | customer_not_linked_by_phone | Telefone não tem vínculo OU não existe (anti-enumeration). | Peça CPF. |
| 409 | phone_conflict | Telefone já atrelado a outro cliente seu. | Reconfirme com o cliente. |
| 429 | rate_limit_exceeded | Excedeu o bucket por minuto. | Respeite o header Retry-After. |
Veja a referência completa em códigos de erro.
Privacidade & compliance
- Nunca logue CPF ou telefone em claro do seu lado se puder evitar. A Bumcash não os retorna em audit logs (apenas hashes sha256), e seu lado deveria seguir a mesma política.
- Cross-merchant: você nunca verá dados que indiquem que um cliente tem relação com outro merchant. Se uma consulta por CPF retorna
linked_to_caller: false, os campos sensíveis (id,phone,external_reference_id) vêm omitidos. - Resposta indistinguível: respostas
indistinguishable_by_phoneecustomer_not_linked_by_phonesão deliberadamente idênticas para "número de outro merchant" e "número desconhecido". Aceite isso como propriedade do sistema — não tente diferenciar. - LGPD (Lei 13.709): tratamento de dados de clientes está coberto pela execução de contrato + interesse legítimo (programa de fidelidade). Mantenha um propósito declarado para coletar telefone e respeite pedidos de exclusão pelo seu canal.
Próximos passos
- Pagamentos / cashback: combine este guia com a trilha do seu modelo de negócio — veja Recorrência, Varejo PDV ou Híbrido.
- Eventos em tempo real: webhooks de
customer.activated,cashback.granted, etc. Hoje exigem chave Partner — merchant-direct webhooks estão no roadmap. - Monitoramento: a Bumcash mantém audit log estruturado de toda chamada bot-via-API com hash sha256 do identificador. Sinais de enumeração (>80%
not_linkedem 1h) disparam alerta — ajuste a UX do bot para não bater 100/min cegamente.