Carteira e cartão pela API
Toda cobrança de um workspace — números, plano, linhas telefônicas — sai primeiro da carteira pré-paga e, no que a carteira não cobrir, do cartão salvo. Estes endpoints permitem que o seu sistema abasteça os dois sem mandar o seu cliente ao painel:
Nenhuma destas chamadas cobra nada. Elas só emitem a cobrança: uma pessoa paga o Pix, preenche a página hospedada ou confirma o cartão na sua página. A carteira é creditada quando o pagamento é confirmado, e o webhook
wallet.topup_paid avisa você.
Credenciais e permissões
- Uma credencial de nível de workspace: uma chave de workspace, ou uma chave de conta com
x-workspace-id. Uma chave de número, ou um token limitado a alguns números, recebe 403NUMBER_SCOPE_NOT_ALLOWED. - Papel, com uma chave de conta ou um token OAuth/MCP: recarregar e salvar cartão são ações do Proprietário; ler o status de uma recarga (
GET /v1/billing/topups/{id}) exige Proprietário ou Administrador. Um papel abaixo disso recebe 403PERMISSION_DENIED. Uma chave de workspace não tem usuário, então nenhum papel se aplica. - Moeda: o valor é sempre na moeda do workspace (
BRLouUSD). Não dá para escolher por requisição.
Recarga com Pix
O Pix está disponível em workspaces em BRL.POST /v1/billing/checkout com purpose: "wallet_topup", method: "pix" e o amount:
- Mostre
pix.copyPaste(o código copia e cola) e/oupix.qrCode(a imagem do QR code como URIdata:image/png;base64,…, pronta para um<img src>; pode virnull) para quem vai pagar. Um Pix expira em 1 hora (pix.expiresAt). - Guarde o
orderId: é com ele que você acompanha o pagamento emGET /v1/billing/topups/{id}e é ele que o webhookwallet.topup_paidinforma. - Um workspace em USD recebe 400
PIX_NOT_ELIGIBLE. Use cartão. successUrlecancelUrlnão fazem sentido num Pix: enviá-los dá 400FIELD_NOT_APPLICABLE.
Recarga ou cartão numa página hospedada do Stripe
O mesmo endpoint, commethod: "card" (o padrão), responde com uma url para uma página hospedada pelo Stripe. Abra-a no navegador de quem vai pagar.
Resposta (200)
purpose: "add_card", a página salva um cartão no workspace, sem cobrar nada. A resposta é { "url": "…", "purpose": "add_card" }. O cartão passa a ser o cartão salvo do workspace, em qualquer plano: ele cobre a carteira em toda cobrança — números, renovações do plano e linhas telefônicas. method não se aplica ao add_card (400 FIELD_NOT_APPLICABLE).
string
obrigatório
wallet_topup ou add_card. Qualquer outro valor → 400 INVALID_PURPOSE.number
Obrigatório no
wallet_topup: um número positivo na moeda do workspace. Ausente, zero, negativo ou não numérico → 400 INVALID_AMOUNT.string
padrão:"card"
card ou pix, só no wallet_topup. Qualquer outro valor → 400 INVALID_METHOD.string
Só cartão. Para onde a página hospedada leva o navegador depois de pagar ou salvar.
string
Só cartão. Para onde a página hospedada leva o navegador quando a pessoa desiste.
NO_BILLING_EMAIL. O Pix não exige.
Acompanhar uma recarga
GET https://pilotstatus.com.br/v1/billing/topups/{id}, com o orderId de qualquer recarga — Pix, página hospedada ou Elements.
Resposta (200)
- Só lê. Não chama nenhum provedor de pagamento, então consultar repetidamente é barato. O pedido passa a
paidquando o provedor de pagamento nos confirma o pagamento. - Prefira o webhook a consultar em loop. O
wallet.topup_paidchega uma vez por pedido creditado. Ele só é enviado depois que o pedido é concluído, então, quando chega, este endpoint já respondepaid. - Um id de outro workspace recebe o mesmo 404
TOPUP_NOT_FOUNDde um id que não existe.
Cartão na sua própria página (Stripe Elements)
Com estes endpoints, os campos do cartão ficam na sua página, feitos com o Payment Element do Stripe. O seu servidor nos pede um intent; a sua página o confirma com o Stripe.js; o seu servidor chama osync.
Os quatro endpoints:
- respondem com
Cache-Control: no-store— umclientSecretpermite a quem o tiver confirmar o intent, então não o guarde em cache nem em log; - devolvem a
publishableKeycom que carregar o Stripe.js, então você não precisa de uma conta Stripe própria; - respondem 503
PAYMENTS_NOT_CONFIGUREDquando pagamentos com cartão não estão disponíveis do nosso lado. Ofereça Pix (BRL) ou tente de novo mais tarde.
Salvar um cartão
POST https://pilotstatus.com.br/v1/billing/card/setup-intent, sem corpo (ou {}). Qualquer campo dá 400 UNKNOWN_FIELDS.
Resposta (200)
clientSecret e chame stripe.confirmSetup(...). Quando ele resolver, chame:
POST https://pilotstatus.com.br/v1/billing/card/setup-intent/{setupIntentId}/sync
Resposta (200)
- O
synclê o intent no Stripe; ele nunca confia na sua página. Quando o Stripe dizsucceeded, o cartão passa a ser o cartão salvo do workspace, substituindo o anterior. - Ainda não concluído (
processing,requires_action, …):saved: false,card: nulle ostatusdo Stripe. Chame de novo mais tarde, ou conte com o nosso lado: o Stripe também nos avisa, e o cartão é salvo nesse momento. - Idempotente. Chamar de novo, ou concorrer com o nosso próprio aviso do Stripe, salva o cartão uma vez só.
- Um id que não é
seti_…→ 400INVALID_SETUP_INTENT_ID. Um id que não criamos para este workspace → 404SETUP_INTENT_NOT_FOUND.
Recarga com cartão
POST https://pilotstatus.com.br/v1/billing/payment-intents
string
obrigatório
wallet_topup, o único valor hoje. Qualquer outro → 400 INVALID_PURPOSE.number
obrigatório
Um número positivo na moeda do workspace, arredondado para centavos. Não positivo → 400
INVALID_AMOUNT. Abaixo do mínimo de cobrança com cartão do Stripe → 400 AMOUNT_TOO_SMALL.boolean
padrão:"false"
true também salva este cartão como o cartão do workspace quando o pagamento for concluído. Se não for booleano → 400 INVALID_FIELD_TYPE.string
Opcional. Até 255 caracteres, sem caracteres de controle (caso contrário, 400
IDEMPOTENCY_KEY_INVALID). Veja abaixo.UNKNOWN_FIELDS.
stripe.confirmPayment(...) com o clientSecret. Quando ele resolver, chame:
POST https://pilotstatus.com.br/v1/billing/payment-intents/{paymentIntentId}/sync
Resposta (200)
- O
syncnunca cobra. Ele não é o/confirmdo Stripe: só reconcilia o que o Stripe já decidiu. A carteira é creditada exatamente uma vez, pelosyncou pelo nosso aviso do Stripe, o que chegar primeiro. - Um id que não é
pi_…→ 400INVALID_PAYMENT_INTENT_ID. Um id que não criamos como recarga deste workspace → 404PAYMENT_INTENT_NOT_FOUND. - O
orderIdfunciona emGET /v1/billing/topups/{id}como o de qualquer outra recarga.
Idempotency-Key
Envie-a noPOST /v1/billing/payment-intents para que uma nova tentativa depois de um timeout não abra um segundo pedido.
- Ausente: toda chamada cria um novo pedido e um novo payment intent.
- Mesma chave e mesmo corpo em até 24 horas: você recebe o mesmo
orderId,paymentIntentIdeclientSecret, com o headerIdempotent-Replayed: true. Nada novo é criado. - Mesma chave, corpo diferente: 409
IDEMPOTENCY_KEY_REUSED. Use uma chave nova. - Mesma chave enquanto a primeira chamada ainda está rodando: 409
IDEMPOTENCY_KEY_IN_USE. Tente de novo em instantes. - As chaves são por workspace. Uma chamada que falhou na validação, ou falhou depois, não gasta a chave.
Erros
Os erros trazem umcode e uma mensagem error no formato English | Português — também no POST /v1/billing/checkout desde 29/10/2026 (INVALID_PURPOSE, INVALID_AMOUNT, NO_BILLING_EMAIL e CHECKOUT_FAILED eram só em inglês; os códigos e os status não mudaram). Decida pelo code, nunca pela frase. Os endpoints do Elements põem detalhes extras em details (por exemplo, details.unknownFields).
Os erros de autenticação (
401, 400 WORKSPACE_ID_REQUIRED, 403 WORKSPACE_MEMBERSHIP_REQUIRED) estão descritos em Tipos de chave.
Revendedores e o cartão compartilhado
O workspace de um cliente final de um revendedor pode ser vinculado ao cartão compartilhado (cartão de reserva) do revendedor. Quem controla o vínculo, workspace por workspace, é o revendedor:"shareCard": true no POST /v1/workspaces (ausente ou false: não compartilhado), e PUT / DELETE /v1/workspaces/{id}/shared-card depois; a equipe da Pilot Status só configura qual dos workspaces do revendedor guarda esse cartão. Antes de 29/10/2026, os workspaces criados por um revendedor o herdavam automaticamente. Esse cartão só cobre as cobranças que a plataforma faz — renovações, números, linhas — quando a carteira do workspace não as cobre e o workspace não tem cartão próprio. Ele nunca é usado por estes endpoints: uma recarga aqui é paga por quem paga o Pix, a página hospedada ou o seu formulário do Elements, e o add_card ou um setup intent salvam um cartão no próprio workspace, que passa a ter prioridade sobre o compartilhado. Veja Cobrança para revendedores.