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:
- Tokenizar o cartão. Você manda o cartão e recebe um
card_token. - 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#
POST /api/v1/vault/shadowbank/cards
Authorization: Bearer pk_live_...:sk_live_...
Content-Type: application/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:
{
"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#
POST /api/v1/shadowbank/payments
Authorization: Bearer pk_live_...:sk_live_...
Idempotency-Key: pedido-9823
Content-Type: application/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:
{
"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 umcard_tokennovo.retryable: false— a adquirente recusou. Não insista no mesmo cartão;decline_codetraz 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.
POST /api/v1/shadowbank/upsell
Authorization: Bearer pk_live_...:sk_live_...
Idempotency-Key: upsell-9823-1
Content-Type: application/json{
"parent_transaction_id": "a960cd5a-a166-4e16-8e28-72a64b4013ed",
"amount_cents": 1500,
"currency": "BRL",
"description": "Garantia estendida"
}Resposta 201:
{
"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:
{
"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:
{
"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.
{
"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_ide 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-Keydevolve 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-Keyem toda cobrança e todo upsell. - Cliente HTTP com 90 segundos ou mais de leitura.
-
pendingnunca é repetido. - O pedido é liberado pelo webhook ou pela consulta, nunca só pela resposta.