Skip to main content

Números extras e On Demand

Compre um número extra de WhatsApp pela API pública com uma chave de escopo do tenant. A precificação segue o modelo On Demand: você paga um preço mensal por número conectado (definido por tenant pela equipe da Pilot Status) e obtém mensagens ilimitadas em cada número.
Aba de cartão salvo na página de Planos

A aba Cartão em Planos — salve um cartão uma vez e números extras comprados via API são cobrados automaticamente (On Demand).

A cobrança roda sobre uma carteira pré-paga: primeiro os créditos, depois o cartão salvo para o que os créditos não cobrirem. Os créditos podem ser recarregados por cartão ou PIX.
Chaves de escopo de número recebem 403 — use a chave de escopo do tenant (painel Profile → API).

GET /v1/subscription/extra-numbers — Prévia (dry-run)

Retorna o custo e se a compra converte o plano. proratedTotal é o que você paga agora; monthlyTotalBRL é o que passa a ser cobrado a cada ciclo:
Você só paga pelos dias que faltam no ciclo. A primeira cobrança é proporcional: proratedUnitPrice = unitPriceMonthly × (remainingDays / totalDaysInCycle). No exemplo acima falta metade do ciclo, então são 2 números × R$14,95 = R$29,90 agora, e R$59,80/mês a partir do próximo ciclo.
fundingSource diz como a cobrança será coberta — credits, card, credits+card ou none. Quando é none, canFund vem false e o POST devolve uma checkoutUrl em vez de cobrar.

POST /v1/subscription/extra-numbers — Comprar

Comportamento:
  • Conversão Free → On Demand. Se você está no plano Free, comprar um número extra move você para o On Demand: seu número atual (antes gratuito, limitado a 200 mensagens) se torna um número pago e ilimitado e o novo número também é cobrado. Portanto, comprar 1 extra estando no Free cobra você por 2 números. Como isso altera o que você paga, o POST retorna 409 CONFIRMATION_REQUIRED (com a prévia) a menos que você envie confirm: true.
  • Já no On Demand / pago. Comprar incrementa sua contagem de números; as mensagens permanecem ilimitadas.
  • Pagamento. O custo proporcional sai primeiro da sua carteira pré-paga e o que sobrar vai no cartão salvo (painel Plans → Cartão). Sem nenhum dos dois, a resposta é { "success": true, "charged": false, "checkoutUrl": "https://…" } — abra-a para pagar o valor proporcional; o cartão usado ali fica salvo para a cobrança recorrente. Após o pagamento, o slot é desbloqueado (webhook) e você pode criar o número com POST /v1/numbers.
  • A recorrência mensal sai da carteira, não de uma assinatura à parte. A cada ciclo, paidExtraNumbers × preço unitário é debitado dos créditos, com o cartão salvo como reserva. Recarregue com POST /v1/billing/checkout (wallet_topup), que aceita PIX — dá para rodar On Demand só com créditos de PIX, sem nunca salvar um cartão.
Mantenha créditos ou um cartão salvo disponíveis. Se a cobrança de um ciclo não puder ser paga, você tem 2 dias para adicionar créditos ou atualizar o cartão antes que seus números parem de enviar (o recebimento continua). Adicionar saldo reativa na hora.

Quando o pagamento não passa

POST /v1/subscription/extra-numbers distingue três falhas, e elas não dividem a mesma solução. Decida pelo code, nunca pelo status HTTP: duas das três são 402. Todos esses corpos trazem proratedTotal e currency, então dá para mostrar o valor que foi tentado. O INSUFFICIENT_FUNDS traz também walletReason (NO_CARD ou INSUFFICIENT_CREDITS).
Nos três casos o número extra não foi adicionado. Seu paidExtraNumbers continua igual e nenhum slot foi liberado — toda escrita acontece depois de uma cobrança bem-sucedida.
502 PAYMENT_PROVIDER_ERROR não quer dizer “nada foi cobrado”. Quer dizer que a requisição ao processador falhou ou que a resposta dele se perdeu — a cobrança pode ter se concluído do lado dele sem que a gente ficasse sabendo. A contagem não mudou, então repetir às cegas pode pagar duas vezes. Confira o extrato primeiro.

O campo declineCode

O PAYMENT_FAILED às vezes traz declineCode. Quando vem, é o próprio código de recusa da bandeira, literal (insufficient_funds, expired_card, card_not_supported, …) — pode ser mostrado ao titular do cartão ou usado para decidir. ⚠️ A ausência dele não diz nada. Um PAYMENT_FAILED sem declineCode é um pagamento que não passou por um motivo que não conseguimos atribuir ao cartão — um rate limit na requisição, uma chave de integração expirada, um payment intent que ficou num estado diferente de sucesso. Não inventamos um código para preencher o campo. Portanto:
  • Decida pelo code: "PAYMENT_FAILED". Ele está sempre presente e sempre significa a mesma coisa.
  • Use o declineCode só para refinar a mensagem quando ele existir.
  • Nunca leia “sem declineCode” como “não foi recusa” — e nunca como “o cartão está bom”.
O declineCode nunca aparece no INSUFFICIENT_FUNDS nem no PAYMENT_PROVIDER_ERROR. Nenhum dos dois é recusa de cartão.

A capacidade paga é um direito de 30 dias

Ao comprar números extras, essa capacidade é sua durante todo o ciclo de 30 dias. Duas consequências:
  • Deletar um número não reduz sua capacidade paga. DELETE /v1/numbers/<id> libera o slot para você reconectar outro número no mesmo ciclo — sua contagem paga e sua cobrança seguem iguais até o fim do ciclo.
  • Reduzir a capacidade é uma ação explícita e agendada. Você decide baixar a quantidade de slots pagos; a mudança vale no próximo ciclo, quando a cobrança cai para o novo valor. Nada é estornado do ciclo em andamento.

No Pay As You Go funciona diferente

No Pay As You Go não existe capacidade para comprar de volta nem para agendar redução — você paga pelos números que tem conectados:
  • O número é cobrado quando passa a ser utilizável, prorata pelos dias restantes do ciclo. Para número não-oficial isso é a primeira conexão; para número oficial (Meta), é quando o Embedded Signup é concluído.
  • O slot que você pagou vale pelo ciclo. Deletar um número e conectar outro no lugar não cobra de novo.
  • O ciclo seguinte cobra só o que continuar conectado. Nada se acumula do ciclo anterior, então não há o que agendar para baixo — veja o 409 NOT_APPLICABLE_FOR_PLAN no endpoint abaixo.
  • Um pareamento que você nunca concluiu não é um número e não é cobrado. A linha “Aguardando conexão”, que aparece enquanto o seu usuário final está no diálogo do Facebook, fica de fora da cobrança e da sua capacidade, e é removida automaticamente 24h depois de criada.

DELETE /v1/subscription/extra-numbers — Agendar uma redução

Agenda a redução de quantity slot(s) pago(s) para o próximo ciclo:
Comportamento:
  • Agendado, não imediato. Este ciclo mantém a capacidade atual (sem estorno); a redução vale a partir do próximo rollover, quando os meses futuros cobram menos.
  • Editável. Chamar de novo sobrescreve o alvo agendado. Cancele com DELETE …/schedule (abaixo).
  • Não pode ficar abaixo dos números conectados. Se o alvo deixaria o limite abaixo dos números que você ainda tem conectados, retorna 409 NUMBER_LIMIT_EXCEEDED ({ currentNumberCount, maxNumbers }) — delete um número antes.
  • Não existe no Pay As You Go. Retorna 409 NOT_APPLICABLE_FOR_PLAN. Não há capacidade paga a devolver: o Pay As You Go cobra pelos números que você tem conectados, e o próximo ciclo já cobra apenas o que continuar conectado. Para pagar menos, delete o número — não é preciso agendar nada.
  • quantity tem default 1 e é limitado para nunca ficar abaixo de 0 extras pagos. Chaves de escopo de número recebem 403.
Resposta — paidExtraNumbers continua no valor do ciclo atual; scheduledPaidExtraNumbers é o alvo que passa a valer no próximo ciclo:

DELETE /v1/subscription/extra-numbers/schedule — Cancelar a redução agendada

Cancela uma redução pendente para que o próximo ciclo mantenha sua capacidade paga atual. No-op se nada estiver agendado.

POST /v1/billing/checkout — Recarga de carteira / adicionar um cartão

Gera uma URL de checkout hospedada para ações de cobrança:
  • purpose: "wallet_topup" — recarrega a carteira pré-paga.
  • purpose: "add_card" — salva um cartão para futuras cobranças On Demand.
A resposta contém uma checkoutUrl para abrir no navegador.