Throne

Cartão

Server-to-server na ShadowBank

Integração por API, sem Throne Elements, na adquirente ShadowBank: cobrança na moeda do comprador, com recorrência e upsell em um clique, para quem já tem checkout próprio. Habilitação caso a caso.

Ver em Markdown

O que é esta integração#

A integração direta da ShadowBank é uma alternativa ao Throne Elements para quem tem um checkout de cartão próprio e quer cobrar pela API, do próprio servidor, sem o iframe do Throne. Ela existe para a Eminence, para a Vortex e para a ShadowBank, e esta página cobre a ShadowBank. Nas outras adquirentes a integração continua sendo o Throne Elements.

Você cobra na moeda do seu comprador, as mesmas 48 da lista, e a cotação que credita o seu saldo é fixada na criação da cobrança, como no checkout comum.

Quando usar:

  • Você é um gateway, subadquirente ou agregador e já tem a própria tela de cartão.
  • Você quer cobrança recorrente e upsell em um clique sem mandar o comprador a uma tela do Throne.

Quando não usar:

  • Você quer um checkout pronto, sem desenvolver a tela do cartão: use o Throne Elements.
  • Você precisa de parcelamento: nesta modalidade a cobrança é sempre à vista.

Upsell em um clique e recorrência funcionam aqui, e o upsell também pode ser recorrente. O upsell tem rota própria, o POST /api/v1/shadowbank/upsell. O campo one_click_from do checkout comum não existe nesta modalidade: ele volta 422 field_not_supported e a mensagem aponta a rota certa.

Atenção Na integração direta o número do cartão passa pelo seu servidor antes de chegar ao Throne. A guarda desses dados do seu lado (PCI DSS) é responsabilidade sua: nunca grave número, validade ou CVV em banco, arquivo ou log.

Habilitação#

A integração direta é liberada caso a caso. Fale com o suporte. São três requisitos:

  • A ShadowBank habilitada na sua conta (confira em GET /api/v1/elements/acquirers).
  • A integração direta da ShadowBank liberada na sua conta.
  • Uma chave de API com o escopo transactions:write (gere no painel, em Chaves de API).

Sem a liberação, as chamadas respondem 422 partner_api_not_enabled. Sem a ShadowBank, 422 acquirer_not_enabled. Sem o escopo, 403 scope_required.

A liberação é por adquirente: quem já usa a integração direta da Eminence ou da Vortex precisa pedir a da ShadowBank à parte.

Para o upsell em um clique há um quarto requisito, que é por conta e não por adquirente: o upsell em um clique habilitado. Sem ele a rota do upsell responde 403 one_click_not_enabled, e a cobrança comum continua funcionando.

O caminho, em dois passos#

Toda cobrança tem duas chamadas, nesta ordem, as duas feitas do seu servidor e com a sua chave de API:

  1. Tokenizar o cartão. Você manda o cartão e recebe um card_token.
  2. Cobrar com esse card_token. A resposta já traz o resultado.

O cartão nunca é enviado ao endpoint de cobrança. Se você mandar qualquer campo de cartão nele, a resposta é 400 card_data_not_allowed e nada é cobrado.

Passo 1: tokenizar o cartão#

Texto
POST /api/v1/vault/shadowbank/cards
Authorization: Bearer pk_live_...:sk_live_...
Content-Type: application/json
JSON
{
  "number": "5555555555554444",
  "exp_month": 11,
  "exp_year": 2031,
  "cvv": "737",
  "holder_name": "MARIA S SOUZA",
  "customer": {
    "name": "Maria Souza",
    "email": "maria@exemplo.com"
  }
}

Resposta 201:

JSON
{
  "card_token": "sbt_7b58f4a1600bd9419cb20b7f111bc831",
  "brand": "mastercard",
  "last4": "4444",
  "exp_month": 11,
  "exp_year": 2031,
  "expires_at": "2026-11-09T03:00:00Z"
}

O card_token vale até expires_at — no máximo sete dias, e nunca depois do fim do mês de validade do cartão.

O bloco customer neste passo é opcional e recomendado. Ele não é repassado à adquirente além do nome: serve para que o mesmo comprador caia sempre no mesmo cadastro do lado dela quando voltar a comprar. Mande o mesmo customer que você vai mandar na cobrança.

Erros deste passo:

HTTP error Quando
422 invalid_card Número, validade, CVV ou titular fora do formato, ou o cartão recusado na tokenização. O campo problemático vem em field.
401 unauthorized Chave de API ausente ou inválida.
403 scope_required A chave não tem transactions:write.
422 partner_api_not_enabled A integração direta não está liberada na conta.
422 acquirer_not_enabled A ShadowBank não está habilitada na conta.
429 rate_limit_exceeded Limite por segundo da conta. Aguarde 1 segundo.
503 temporarily_unavailable Tokenização indisponível. Tente de novo em instantes.

Passo 2: cobrar#

Texto
POST /api/v1/shadowbank/payments
Authorization: Bearer pk_live_...:sk_live_...
Idempotency-Key: pedido-9823
Content-Type: application/json
JSON
{
  "amount_cents": 2500,
  "currency": "BRL",
  "card_token": "sbt_7b58f4a1600bd9419cb20b7f111bc831",
  "description": "Plano Pro",
  "customer": {
    "name": "Maria Souza",
    "email": "maria@exemplo.com"
  },
  "metadata": {
    "pedido": "9823"
  }
}

Resposta 201:

JSON
{
  "transaction_id": "a960cd5a-a166-4e16-8e28-72a64b4013ed",
  "status": "paid",
  "authorized": true,
  "amount_cents": 2500,
  "currency": "BRL",
  "installments": 1,
  "message": "Pagamento aprovado.",
  "created_at": "2026-11-02T01:15:35-03:00",
  "card": { "brand": "mastercard", "last4": "4444" }
}

Como ler a resposta#

Depois que a venda é criada, a resposta é sempre 201, e o que muda é o status:

status O que fazer
paid Aprovado e liberado. Entregue o pedido.
pending Em análise da adquirente, ou resultado indefinido. Não repita a cobrança: espere o webhook transaction.paid ou consulte a venda.
failed Recusado, ou nada processado. Veja retryable.

Em failed, o campo retryable diz o que fazer:

  • retryable: true — nada foi cobrado. Você pode tentar de novo, com um card_token novo.
  • retryable: false — a adquirente recusou. Não insista no mesmo cartão; decline_code traz o código dela.

pending é desfecho normal nesta adquirente, não erro: a cobrança pode cair em análise e fechar depois, pelo webhook.

Antes de a venda ser criada (erro de validação, conta sem liberação, valor fora da faixa), a resposta é 4xx ou 503 e a Idempotency-Key fica livre para ser repetida.

Campos do passo 2#

Campo Obrigatório Regra
amount_cents sim Inteiro, na menor unidade da moeda.
currency sim Três letras, uma das 48 aceitas.
card_token sim O token do passo 1.
customer.name sim Nome do comprador, até 120 caracteres.
customer.email não E-mail do comprador. Opcional nesta adquirente.
description não Até 255 caracteres. Vira o nome do produto no extrato interno.
metadata não Até 20 chaves de texto, número ou booleano.
installments não Só 1. Qualquer outro valor é 422.
recurrence não Veja Recorrência.

Campos recusados nesta rota, com o motivo na resposta: one_click_from (use a rota do upsell).

Campos da resposta#

Campo Sempre O que é
transaction_id sim O identificador da venda no Throne. Guarde este.
status sim paid, pending ou failed.
authorized sim true só em paid.
amount_cents, currency sim Ecoam o seu pedido, não o valor interno.
installments sim Sempre 1.
message sim Frase pronta para registro.
card quase sempre brand e last4.
decline_code em failed O código da adquirente.
retryable em failed Se pode tentar de novo.
recurrence_id, cycle, next_charge_at com recorrência Veja Recorrência.

Consulta#

GET /api/v1/transactions/{transaction_id}, igual a qualquer venda. Veja Transações.

Estorno#

O estorno é feito pelo Throne, não pela API do parceiro. Fale com o suporte.

Webhook#

O webhook não muda por causa desta modalidade: transaction.paid, transaction.failed e os demais chegam no mesmo formato de sempre, no mesmo endpoint. Veja Webhooks.

Libere o pedido pelo webhook ou pela consulta, nunca só pela resposta da cobrança.

Upsell em um clique#

Cobra o mesmo cartão de uma venda que já foi paga, sem pedir o cartão ao comprador de novo e sem card_token nenhum. Você manda só o transaction_id da venda de origem.

Texto
POST /api/v1/shadowbank/upsell
Authorization: Bearer pk_live_...:sk_live_...
Idempotency-Key: upsell-9823-1
Content-Type: application/json
JSON
{
  "parent_transaction_id": "a960cd5a-a166-4e16-8e28-72a64b4013ed",
  "amount_cents": 1500,
  "currency": "BRL",
  "description": "Garantia estendida"
}

Resposta 201:

JSON
{
  "transaction_id": "7fb09848-911d-45ee-97ee-2d0847c2d3eb",
  "status": "paid",
  "authorized": true,
  "amount_cents": 1500,
  "currency": "BRL",
  "installments": 1,
  "one_click": true,
  "message": "Pagamento aprovado.",
  "created_at": "2026-11-02T01:24:35-03:00",
  "card": { "brand": "visa", "last4": "1881" }
}

O status se lê igual ao da cobrança comum.

O upsell pode ser recorrente#

Mande recurrence no corpo do upsell e ele vira a primeira cobrança de uma assinatura:

JSON
{
  "parent_transaction_id": "a960cd5a-a166-4e16-8e28-72a64b4013ed",
  "amount_cents": 2000,
  "currency": "BRL",
  "description": "Clube mensal",
  "recurrence": { "cycle": "monthly", "max_payments": 6 }
}

A resposta traz, além dos campos de sempre, os três da recorrência:

JSON
{
  "transaction_id": "45f577d8-e706-4198-91b0-323f64697b93",
  "status": "paid",
  "one_click": true,
  "recurrence_id": "rec_a8158e00a2a6e23bc68f1532",
  "cycle": "monthly",
  "next_charge_at": "2026-12-02T15:00:00Z"
}

O que a venda de origem precisa ser#

Requisito Por quê
Sua Venda de outra conta responde como se não existisse.
Paga O upsell cobra o cartão de uma venda que deu certo.
Na ShadowBank O upsell cai na mesma adquirente da venda de origem.
Dentro da janela A janela padrão é de 2 horas desde o pagamento.
Com cartão guardado Vendas pagas antes desta versão não têm o cartão guardado.
Abaixo do limite de upsells Até 5 upsells por venda de origem.

O valor do upsell tem um teto próprio: o menor entre um limite absoluto e vinte vezes o valor da venda de origem. Ele existe porque o comprador não digita nada nesta cobrança — um erro de valor do seu lado debitaria algo que ele nunca viu.

Erros do upsell#

HTTP error Quando
409 parent_not_found Não existe venda sua com esse parent_transaction_id.
409 parent_not_paid A venda de origem não está paga.
409 parent_refunded A venda de origem foi estornada.
409 parent_charged_back A venda de origem foi contestada.
409 parent_too_old Fora da janela do um clique.
409 upsell_limit_reached A venda de origem já atingiu o limite de upsells.
409 parent_other_acquirer A venda de origem é de outra adquirente.
409 one_click_unavailable O um clique não está disponível para essa venda.
403 one_click_not_enabled O upsell em um clique não está habilitado na conta.
422 field_not_supported Você mandou card_token, customer, installments ou one_click_from. O campo vem em field.
422 amount_out_of_range Acima do teto do upsell ou fora da faixa da adquirente.
503 busy Outro upsell desta venda de origem está em andamento. Tente em 3 segundos.

O upsell não recebe comprador: ele é o da venda de origem, e mandar customer é 422.

Recorrência#

Mande recurrence na cobrança e ela se torna a primeira de uma assinatura. A adquirente guarda o cartão e cobra os ciclos seguintes sozinha.

JSON
{
  "amount_cents": 2500,
  "currency": "BRL",
  "card_token": "sbt_7b58f4a1600bd9419cb20b7f111bc831",
  "customer": { "name": "Maria Souza" },
  "recurrence": { "cycle": "monthly", "max_payments": 12 }
}
Campo Obrigatório Regra
recurrence.cycle sim, se mandar recurrence Um dos sete: weekly, biweekly, monthly, bimonthly, quarterly, semiannually, yearly.
recurrence.max_payments não De 2 a 120, contando a primeira cobrança. Sem ele, a assinatura não tem fim.

A resposta ganha três campos:

Campo O que é
recurrence_id O identificador da recorrência no Throne.
cycle O ciclo, de volta.
next_charge_at Quando a próxima cobrança cai.

Pontos que importam:

  • A primeira cobrança é a desta chamada. A assinatura na adquirente começa a valer a partir do ciclo seguinte, então o comprador nunca é cobrado duas vezes no mesmo dia.
  • A assinatura só abre se a primeira cobrança for aprovada. Recusada, a resposta traz recurrence_id e a recorrência fica pendente, sem nada cobrando.
  • Os ciclos seguintes chegam pelo webhook, como vendas novas ligadas à mesma recorrência.
  • Ciclo fora dos sete é 422 invalid_cycle, com a lista na mensagem.
  • Recorrência e parcelamento não se combinam: esta modalidade é sempre à vista.

Para listar, consultar e cancelar recorrências, veja Recorrências.

Dinheiro#

Taxa, cautela, maturação, antecipação e saque seguem as regras da sua conta, iguais às de qualquer venda de cartão. Veja Como o dinheiro entra.

Limites e tempos#

  • Limite por segundo: o da sua conta, compartilhado entre a tokenização e a cobrança.
  • A cobrança pode levar até 85 segundos. Configure o seu cliente HTTP com no mínimo 90 segundos de leitura.
  • Repetir a mesma Idempotency-Key devolve a resposta da primeira chamada, sem cobrar de novo.

Atenção Nunca repita uma cobrança que respondeu pending. Ela pode ter sido aprovada do outro lado, e uma segunda chamada cobraria o comprador duas vezes.

Testar#

Não há ambiente de testes nesta modalidade: as chamadas são reais. Comece com um valor baixo e um cartão seu.

Checklist#

  • A ShadowBank habilitada na conta.
  • A integração direta da ShadowBank liberada.
  • Chave de API com transactions:write.
  • Para o upsell: o um clique habilitado na conta.
  • O cartão nunca vai ao endpoint de cobrança.
  • Número, validade e CVV não são gravados em banco, arquivo nem log do seu lado.
  • Idempotency-Key em toda cobrança e todo upsell.
  • Cliente HTTP com 90 segundos ou mais de leitura.
  • pending nunca é repetido.
  • O pedido é liberado pelo webhook ou pela consulta, nunca só pela resposta.