Documentação da plataforma

Para quem vende e para quem integra: o produto sem código e a API, cada tópico em sua página.

API de cartão

Cobre qualquer valor direto do seu servidor, sem cadastrar produto na 3B. Em real, cartão e PIX pela Pagar.me; nas outras moedas, pelo checkout da Whop. Taxas, reserva e repasse continuam os da sua conta.

Antes de começar

  1. 1Gere a sua chave. No painel, em Integrações → API de cartão, clique em Gerar chave. Ela começa com 3bsk_live_ e aparece uma vez só: copie na hora. Perdeu? Gere outra, e a anterior para de funcionar.
  2. 2Use a chave só no servidor. Ela autoriza cobranças em nome da sua loja. Nunca coloque na página, no app ou no repositório. Toda chamada leva o cabeçalho Authorization: Bearer 3bsk_live_....
Valores sempre em centavos (4990 = 49,90). A moeda decide a adquirente: brl vai pela Pagar.me (cartão e PIX), as outras 15 moedas vão pela Whop. Consulte routes no GET ?config=1 para ver a rota da sua conta.
GET/api-charges?config=1Chave pública da Pagar.me, rota por moeda e limites.
curl https://api.pag3b.com/v1/api-charges?config=1 \
  -H "Authorization: Bearer $SUA_CHAVE_3B"

# resposta
{
  "pagarmePublicKey": "pk_...",          // para tokenizar o cartão na página
  "routes": { "brl": "pagarme", "usd": "whop", "eur": "whop", ... },
  "pagarmePaymentMethods": ["credit_card", "pix"],
  "minAmount": 500,                      // centavos
  "maxAmount": 1000000
}

Cartão em real (Pagar.me)

São dois passos. 1. Na sua página, o navegador transforma o cartão em um cardToken direto na Pagar.me, com a chave pública. 2. Seu servidor chama a 3B com o token e o valor. O número do cartão nunca passa pelo seu servidor nem pelo nosso, e é isso que mantém você fora do escopo PCI.

<!-- Na SUA página: o cartão vai direto do navegador para a Pagar.me.
     Nem o seu servidor nem a 3B recebem o número do cartão. -->
<script>
  const PAGARME_PUBLIC_KEY = 'pk_...' // vem do GET ?config=1

  async function tokenizarCartao({ numero, nome, mes, ano, cvv }) {
    const r = await fetch(
      'https://api.pagar.me/core/v5/tokens?appId=' + PAGARME_PUBLIC_KEY,
      {
        method: 'POST',
        // Só Content-Type. Não mande Authorization aqui.
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          type: 'card',
          card: {
            number: numero.replace(/\D/g, ''),
            holder_name: nome,
            exp_month: Number(mes),
            exp_year: Number(ano),
            cvv,
          },
        }),
      },
    )
    const dados = await r.json()
    if (!r.ok || !dados.id) throw new Error('Cartão inválido')
    return dados.id // "token_..." (vale 60 segundos)
  }
</script>
POST/api-chargesCobra o cartão tokenizado.
curl -X POST https://api.pag3b.com/v1/api-charges \
  -H "Authorization: Bearer $SUA_CHAVE_3B" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-123" \
  -d '{
    "amount": 4990,
    "currency": "brl",
    "description": "Plano Premium",
    "reference": "pedido-123",
    "paymentMethod": "credit_card",
    "cardToken": "token_...",
    "installments": 1,
    "customer": {
      "name": "Maria Silva",
      "email": "maria@email.com",
      "document": "12345678909",
      "phone": "11987654321"
    },
    "billingAddress": {
      "street": "Avenida Paulista",
      "number": "1000",
      "neighborhood": "Bela Vista",
      "postalCode": "01310-100",
      "city": "São Paulo",
      "state": "SP"
    }
  }'

# resposta (200 aprovado, 402 recusado)
{
  "id": "1e0bc2b4-...",          // id da cobrança na 3B
  "provider": "pagarme",
  "status": "paid",               // paid | failed | pending
  "amount": 4990,
  "currency": "brl",
  "reference": "pedido-123",
  "sellerAmount": 3942,           // o que fica com você (estimado)
  "platformFee": 549,             // taxa da 3B
  "reserve": 499,                 // reserva (liberada em 90 dias)
  "declineReason": null           // motivo, quando recusado
}
O token vale 60 segundos: tokenize e cobre em seguida. O billingAddress é obrigatório no cartão (sem ele a Pagar.me recusa todas as cobranças). installments vai de 1 a 12. Mandar o número do cartão no corpo é recusado.

PIX em real (Pagar.me)

Mande paymentMethod: "pix" com o CPF ou CNPJ e o celular com DDD do comprador (os dois são exigidos pela Pagar.me). A resposta traz o copia e cola e a imagem do QR. O PIX vence em 1 hora.

POST/api-chargesGera um PIX.
curl -X POST https://api.pag3b.com/v1/api-charges \
  -H "Authorization: Bearer $SUA_CHAVE_3B" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4990,
    "currency": "brl",
    "description": "Plano Premium",
    "reference": "pedido-124",
    "paymentMethod": "pix",
    "customer": {
      "name": "Maria Silva",
      "email": "maria@email.com",
      "document": "12345678909",
      "phone": "11987654321"
    }
  }'

# resposta
{
  "id": "5b1c...",
  "provider": "pagarme",
  "status": "pending",
  "pix": {
    "qrCode": "00020101021226...",   // copia e cola
    "qrCodeUrl": "https://api.pagar.me/.../qrcode",
    "expiresAt": "2026-09-23T00:06:48.000Z"   // 1 hora
  }
}

Outras moedas (Whop)

Em dólar, euro e nas demais moedas a cobrança sai pela Whop, que não aceita cartão tokenizado por API: o comprador paga no checkout dela. A API cria a cobrança com o seu valor e devolve o planId e um link. Você manda o comprador para o link, ou embute o checkout na sua página. Cartão, Apple Pay, Google Pay e os métodos locais aparecem sozinhos.

POST/api-chargesCria a cobrança na Whop.
curl -X POST https://api.pag3b.com/v1/api-charges \
  -H "Authorization: Bearer $SUA_CHAVE_3B" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-125" \
  -d '{
    "amount": 2990,
    "currency": "usd",
    "description": "Premium Plan",
    "reference": "pedido-125",
    "successUrl": "https://seusite.com/obrigado?pedido=pedido-125"
  }'

# resposta
{
  "id": "plan_ypUwc51E4CGMi",
  "provider": "whop",
  "status": "awaiting_payment",
  "amount": 2990,
  "currency": "usd",
  "successUrl": "https://seusite.com/obrigado?pedido=pedido-125",
  "checkout": {
    "planId": "plan_ypUwc51E4CGMi",
    "url": "https://whop.com/checkout/plan_ypUwc51E4CGMi?..."
  }
}
<!-- Checkout embutido na SUA página, com o planId que a API devolveu (Whop Elements) -->
<script src="https://cdn.whop.com/elements/amber/elements.js" data-whop-elements></script>

<div id="checkout"></div>
<script type="module">
  const checkout = window.WhopElements().checkout.create({
    plan: "plan_ypUwc51E4CGMi",
    returnUrl: "https://seusite.com/obrigado",
  });
  checkout.create("checkout", { buyerEmail: "maria@email.com" }).mount("#checkout");
</script>
// npm install @whop/elements @whop/elements-react
import { loadWhop } from "@whop/elements";
import { WhopElements, Checkout, CheckoutElement } from "@whop/elements-react";

const whop = loadWhop();

export function Pagamento({ planId }: { planId: string }) {
  return (
    <WhopElements elements={whop} locale="pt">
      <Checkout plan={planId} returnUrl="https://seusite.com/obrigado">
        <CheckoutElement buyerEmail="maria@email.com" />
      </Checkout>
    </WhopElements>
  );
}
Checkout embutido antigo desligado: o js.whop.com/static/checkout/loader.js (e o @whop/checkout) parou de funcionar em 21/10/2026, por decisão da Whop. Quem embute o checkout troca pelo código acima (Whop Elements), com o mesmo planId. O link checkout.url segue funcionando sem mudança.
Aqui não vai cardToken, billingAddress nem paymentMethod: quem coleta é o checkout da Whop. A cobrança fica awaiting_payment até o comprador pagar; aí nasce o pedido, com o mesmo reference. Crie uma cobrança por compra.
Voltar para a sua página depois de pagar: mande successUrl (URL https completa) na criação e use o checkout.url que a resposta devolve: paga a compra, o comprador sai da Whop e cai nessa página. Sem o campo, ele fica na tela de confirmação da Whop. No checkout embutido, quem faz isso é o returnUrl: a página recebe ?payment=pay_...&status=succeeded (ou failed, canceled), então confira o status. ⚠️ Chegar na página de retorno não prova o pagamento: libere o acesso pelo webhook ou consultando o status.

Consultar o status

Por id (o da 3B, ou o plan_ da Whop) ou pela sua reference. Status possíveis: pending, awaiting_payment (Whop, ainda não pago), paid, failed, expired (PIX vencido), refunded.

GET/api-charges?id= | ?reference=Status de uma cobrança.
curl "https://api.pag3b.com/v1/api-charges?id=1e0bc2b4-..." -H "Authorization: Bearer $SUA_CHAVE_3B"
curl "https://api.pag3b.com/v1/api-charges?id=plan_ypUwc51E4CGMi" -H "Authorization: Bearer $SUA_CHAVE_3B"
curl "https://api.pag3b.com/v1/api-charges?reference=pedido-123" -H "Authorization: Bearer $SUA_CHAVE_3B"

Aviso de venda paga

status: "paid" na resposta do cartão é o que a adquirente respondeu na hora. A venda é confirmada segundos depois, pelo aviso da adquirente para a 3B. Para liberar o acesso sem ficar consultando, ligue o webhook em Integrações: ele chega assinado, com api_charge: true e o seu reference dentro do pedido. Veja como conferir a assinatura em Webhooks e eventos. Na cobrança pela API a 3B não envia e-mail de acesso ao comprador: a entrega é sua.

Idempotência e limites

Mande o cabeçalho Idempotency-Key com um valor único por compra (o id do seu pedido serve). Se a chamada for repetida com a mesma chave, a 3B devolve a mesma cobrança com idempotentReplay: true e não cobra de novo, inclusive quando a primeira foi recusada: para tentar outro cartão, use outra chave. Limites: de 5,00 a 10.000,00 por cobrança e 60 cobranças por minuto.

Erros

401unauthorizedChave ausente, errada ou trocada.
403api_not_enabledA API foi bloqueada para a sua conta.
403seller_not_approvedO cadastro da conta ainda não foi aprovado.
400amount_out_of_rangeValor fora do limite (em centavos).
400currency_not_supportedMoeda que a 3B não vende.
400billing_address_requiredCartão sem endereço de cobrança completo.
400document_requiredCobrança em real sem o CPF ou CNPJ do comprador (PIX e cartão).
400phone_requiredSem o celular do comprador (obrigatório no PIX e no cartão).
402charge_failedA processadora ou o banco recusou. Veja declineReason.
409route_not_readyA sua conta ainda não está pronta nessa adquirente.
422amount_too_lowO valor não cobre as taxas.
429rate_limitedMais de 60 cobranças por minuto.
Não teste com cartão de verdade em massa. Muitas cobranças pequenas e recusadas seguidas parecem teste de cartão roubado para a adquirente, e podem bloquear a sua conta.