Throne

Pix

Cobrar com Pix

Criar cobrança Pix, mostrar o QR Code, acompanhar o pagamento e vender produto físico.

Ver em Markdown

Como funciona#

  1. O seu servidor cria a cobrança com POST /transactions.
  2. Você mostra ao comprador o QR Code e o código copia e cola.
  3. O comprador paga no aplicativo do banco.
  4. O Throne envia o webhook transaction.paid para o seu servidor. Só então libere o pedido.

A cobrança Pix é sempre em reais. Antes de começar, veja autenticação e Idempotency-Key.

O recebimento por Pix precisa estar habilitado na sua conta. Se não estiver, a criação responde 422 pix_not_enabled e nada é criado; o cartão e os saques por Pix continuam normais. No painel, em Documentação da API, a linha do PIX aparece só quando o recebimento está habilitado.

Criar a cobrança#

curl -X POST https://app.thronecorporate.com/api/v1/transactions \
  -H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "payment_method": "pix",
    "amount_cents": 4990,
    "customer": {
      "name": "Maria Souza",
      "document": "12345678909",
      "email": "maria@exemplo.com"
    },
    "metadata": { "loja_pedido_id": "PED-1042" }
  }'

Campos#

Campo Obrigatório Regra
payment_method Sim "pix"
amount_cents Sim Inteiro em centavos, de 100 (R$ 1,00) a 5000000 (R$ 50.000,00)
customer.name Sim De 3 a 255 caracteres
customer.document Sim CPF (11 dígitos) ou CNPJ (14 dígitos), só números
customer.email Sim E-mail válido
customer.phone Não Até 20 caracteres, por exemplo +5511999998888
customer.birth_date Não AAAA-MM-DD
customer.address Não zip_code, street, number, complement, neighborhood, city, state (UF, 2 letras), country (2 letras)
expires_at Não Data e hora ISO 8601. Se não vier, a cobrança vale 1 hora
metadata Não Objeto livre que volta na consulta e no webhook. Use nomes de campo com um prefixo seu, como loja_pedido_id
items Não Lista de produtos. Veja produto físico
shipping_address Não Endereço de entrega. Veja produto físico
splits Não Divisão do recebimento. Veja dividir o recebimento

A descrição que o comprador vê no banco é definida pelo Throne e não pode ser alterada. Campos fora desta lista são ignorados.

Resposta#

201 Created:

JSON
{
  "id": "72394240-db89-4ec5-b370-4a3e7b998409",
  "status": "pending",
  "payment_method": "pix",
  "amount_cents": 4990,
  "fee_cents": 250,
  "net_amount_cents": 4740,
  "currency": "BRL",
  "native_amount_cents": 4990,
  "fx_rate": null,
  "paid_at": null,
  "expires_at": "2026-10-03T15:20:00Z",
  "payment_data": {
    "qr_code_payload": "00020126580014br.gov.bcb.pix0136...",
    "qr_code_image_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
    "expires_at": "2026-10-03T12:20:00-03:00"
  },
  "customer": { "name": "Maria Souza", "document": "12345678909", "email": "maria@exemplo.com" },
  "shipping_address": null,
  "items": null,
  "metadata": { "loja_pedido_id": "PED-1042" },
  "created_at": "2026-10-03T14:20:00Z"
}
  • Guarde o id. É com ele que você consulta a cobrança e reconhece o webhook.
  • fee_cents e net_amount_cents já vêm calculados pela taxa da sua conta.
  • payment_data.qr_code_payload é o copia e cola. payment_data.qr_code_image_base64 é a imagem do QR Code em PNG, em base64 puro.

Mostrar o QR Code#

HTML
<img src="data:image/png;base64,{{ qr_code_image_base64 }}" alt="QR Code Pix" width="240" height="240">
<input readonly value="{{ qr_code_payload }}">
<button onclick="navigator.clipboard.writeText('{{ qr_code_payload }}')">Copiar código Pix</button>

Se qr_code_image_base64 vier null, gere o QR Code você mesmo a partir de qr_code_payload (qualquer biblioteca de QR Code serve). Se qr_code_payload vier vazio, não mostre nada ao comprador: crie outra cobrança com uma Idempotency-Key nova.

payment_data.expires_at vem com fuso (-03:00) e o expires_at da cobrança vem em UTC: os dois representam o mesmo instante.

Confirmar o pagamento#

A cobrança nasce pending e vira paid quando o pagamento é confirmado. Há duas formas de saber:

  1. Webhook transaction.paid (recomendado). Chega no seu servidor assim que o pagamento é confirmado. Veja Webhooks para validar a assinatura.
  2. Consulta com GET /transactions/{id}, usando o id da criação. Precisa da permissão transactions:read.
cURL
curl https://app.thronecorporate.com/api/v1/transactions/72394240-db89-4ec5-b370-4a3e7b998409 \
  -H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
  -H "Accept: application/json"

Payload do webhook de um Pix pago:

JSON
{
  "event_id": "8c1f3c5e-2c1a-4d1e-9a2b-1f0c9d7e6b5a",
  "type": "transaction.paid",
  "version": "2026-05-01",
  "created_at": "2026-10-03T14:21:07Z",
  "data": {
    "transaction_id": "72394240-db89-4ec5-b370-4a3e7b998409",
    "status": "paid",
    "payment_method": "pix",
    "amount_cents": 4990,
    "fee_cents": 250,
    "net_amount_cents": 4740,
    "paid_at": "2026-10-03T14:21:05Z",
    "customer": { "name": "Maria Souza", "document": "12345678909", "email": "maria@exemplo.com" },
    "shipping_address": null,
    "items": null,
    "metadata": { "loja_pedido_id": "PED-1042" }
  }
}

Regras que evitam problemas:

  • Libere o pedido só com o webhook transaction.paid ou com uma consulta que mostre status: "paid".
  • Deduplique pelo data.transaction_id: o mesmo pagamento pode chegar mais de uma vez.
  • Trate o vencimento pelo expires_at, não pelo status: uma cobrança não paga costuma continuar pending depois do prazo. Um Pix pago depois do prazo ainda vira paid e gera transaction.paid. Não existe webhook de expiração.
  • Campos que vierem a mais no data (como card_brand ou fx_rate com valor null) podem ser ignorados.
  • A API não tem listagem de cobranças. Guarde o id de cada uma e use o webhook para conciliar.

Ciclo da cobrança#

Status Quando
pending Aguardando o pagamento. Continua assim depois do prazo se ninguém pagar
paid Pagamento confirmado
expired Raro: a cobrança venceu e foi encerrada. Mesmo assim, se o pagamento chegar, ela vira paid

Estorno de Pix não é feito pela API. Fale com o suporte do Throne.

Produto físico#

Para vender produto físico, envie a lista de itens e o endereço de entrega. Os dois aparecem no painel e voltam no webhook, então você processa o pedido sem outra chamada.

JSON
{
  "payment_method": "pix",
  "amount_cents": 29800,
  "customer": { "name": "Maria Compradora", "document": "98765432100", "email": "maria@exemplo.com", "phone": "+5511988887777" },
  "items": [
    { "title": "Camisa Polo, Azul, M", "sku": "POLO-AZUL-M", "quantity": 2, "unit_amount_cents": 9900 },
    { "title": "Boné Preto", "sku": "BONE-PRETO", "quantity": 1, "unit_amount_cents": 10000 }
  ],
  "shipping_address": {
    "recipient_name": "Maria Compradora",
    "recipient_phone": "+5511988887777",
    "zip_code": "04567000",
    "street": "Rua das Flores",
    "number": "250",
    "complement": "Bloco B, apto 304",
    "neighborhood": "Vila Mariana",
    "city": "São Paulo",
    "state": "SP",
    "country": "BR",
    "shipping_method": "standard"
  }
}
  • items: até 100 itens. Cada um exige title, quantity e unit_amount_cents; sku, description, category e image_url são opcionais.
  • A soma de quantity × unit_amount_cents precisa ser exatamente amount_cents. Senão: 422 items_total_mismatch.
  • shipping_address: exige recipient_name, zip_code, street, number, city e state (UF). shipping_method aceita standard, express ou pickup.

Dividir o recebimento#

Com splits, parte do valor de uma cobrança vai para outra conta do Throne quando ela é paga (por exemplo, num marketplace).

JSON
"splits": [
  { "recipient_seller_id": 4821, "type": "percentage", "percent_basis_points": 1500 },
  { "recipient_seller_id": 5310, "type": "fixed", "amount_cents": 500 }
]
  • type: "percentage": percent_basis_points de 1 a 10000 (1500 = 15%).
  • type: "fixed": amount_cents a partir de 100.
  • Até 20 divisões por cobrança. Não é possível dividir para a sua própria conta (422 split_invalid).

Um link de pagamento é uma página pronta do Throne, que você compartilha por WhatsApp, e-mail ou redes. A chave precisa da permissão payment_links:write (e payment_links:read para consultar).

cURL
curl -X POST https://app.thronecorporate.com/api/v1/payment-links \
  -H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "description": "Consultoria de 1 hora", "amount_cents": 15000, "max_uses": 1 }'
Campo Obrigatório Regra
description Sim Até 500 caracteres
amount_cents Sim De 100 a 5000000
customer_required Não Se o comprador precisa preencher os dados (padrão true)
max_uses Não Quantas vezes o link pode ser pago, de 1 a 100000
expires_at Não Data futura em ISO 8601
redirect_url_success Não Para onde o comprador vai depois de pagar
redirect_url_expired Não Para onde vai se o link tiver expirado
metadata Não Objeto livre

A resposta traz o campo url: é ele que você compartilha. Outros endpoints:

  • GET /payment-links: os 100 links mais recentes.
  • GET /payment-links/{id}: um link, com used_count e usable.
  • POST /payment-links/{id}/revoke: desativa o link. Se já estava desativado: 409 already_revoked.

Cada pagamento feito pelo link é uma cobrança Pix normal e gera transaction.paid.

Como o link é sempre Pix, ele segue a mesma regra: com o recebimento por Pix desabilitado na conta, POST /payment-links responde 422 pix_not_enabled e um link já criado mostra "Link indisponível" ao comprador até o recebimento ser habilitado de novo.

Erros comuns#

Status error O que fazer
422 (validação) Corrija o campo indicado em errors. O caso mais comum é faltar customer ou customer.document
422 invalid_request Regra de valor ou método (por exemplo, abaixo de R$ 1,00). Leia o message
422 pix_not_enabled O recebimento por Pix não está habilitado nesta conta. Nada foi criado. Fale com o suporte; cartão e saques por Pix continuam
422 items_total_mismatch A soma dos itens não bate com amount_cents
422 split_invalid Divisão para a própria conta
409 idempotency_key_processing A primeira chamada com essa Idempotency-Key ainda está em andamento. Espere alguns segundos e repita a mesma chamada, igual. Veja como repetir com segurança
429 rate_limit_exceeded Mais de 10 cobranças por segundo. Espere o Retry-After e tente com uma Idempotency-Key nova
502 acquirer_error, com "retry_same_key": true A cobrança pode ter sido criada. Repita a mesma chamada, com a mesma Idempotency-Key e o mesmo corpo, e nunca com uma chave nova
502 acquirer_error, sem retry_same_key A adquirente recusou antes de criar, e nada foi criado. Tente de novo com uma Idempotency-Key nova

Lista completa em Erros.