Throne

Cartão

Server-to-server na Vortex

Integração por API, sem Throne Elements, na adquirente Vortex: cobrança na moeda do comprador, 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 Vortex é 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 Vortex. Nas outras adquirentes a integração continua sendo o Throne Elements.

A diferença da Vortex para a integração direta da Eminence está na moeda: aqui 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ê vende para compradores de vários países e quer cobrar na moeda de cada um sem mandá-los ao Throne Elements.

Quando não usar:

  • Você quer um checkout pronto, sem desenvolver a tela do cartão: use o Throne Elements.
  • Você quer cobrar em outra adquirente: só a Eminence e a Vortex aceitam a integração direta.
  • Você precisa de parcelamento: a integração direta cobra sempre à vista.

Upsell em um clique e recorrência funcionam aqui. O upsell tem rota própria, o POST /api/v1/vortex/upsell, e ele mesmo pode ser recorrente. O campo one_click_from do checkout comum continua não existindo nesta modalidade: ele volta 422 one_click_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 Vortex habilitada na sua conta (confira em GET /api/v1/elements/acquirers).
  • A integração direta da Vortex 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 duas chamadas respondem 422 partner_api_not_enabled. Sem a Vortex, 422 acquirer_not_enabled. Sem o escopo, 403 scope_required.

A liberação é por adquirente: quem já usa a integração direta da Eminence precisa pedir a da Vortex à parte. Habilitar só a Vortex na conta, sem essa liberação, dá acesso ao Throne Elements, não a esta API.

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 de uso único.
  2. Cobrar com esse card_token. A resposta já traz o resultado.

Atenção Nunca chame a API do navegador do comprador: a chave de API daria acesso à sua conta. A sua página de pagamento envia o cartão ao seu servidor, e o seu servidor chama o Throne.

Passo 1: tokenizar o cartão#

cURL
curl -X POST https://app.thronecorporate.com/api/v1/vault/vortex/cards \
  --max-time 45 \
  -H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "4000000000000010",
    "exp_month": 12,
    "exp_year": 2030,
    "cvv": "123",
    "holder_name": "LENA FISCHER"
  }'

Resposta 201:

JSON
{
  "card_token": "ac1c3b53b22d47e2baa7b81662dc3a82",
  "brand": "visa",
  "last4": "0010",
  "exp_month": 12,
  "exp_year": 2030,
  "expires_at": "2026-11-03T06:35:06Z"
}

O token vale até o expires_at e serve para uma cobrança. Usado, recusado ou vencido, tokenize de novo.

Passo 2: cobrar#

cURL
curl -X POST https://app.thronecorporate.com/api/v1/vortex/payments \
  --max-time 120 \
  -H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "amount_cents": 4990,
    "currency": "eur",
    "card_token": "ac1c3b53b22d47e2baa7b81662dc3a82",
    "customer": {
      "name": "Lena Fischer",
      "email": "lena@exemplo.de",
      "phone": "+4915112345678",
      "ip": "91.64.12.33"
    },
    "description": "Plano anual",
    "metadata": { "order_id": "ORD-2026-00001" }
  }'

Resposta 201 (aprovado):

JSON
{
  "transaction_id": "ae3bf1da-0c9b-4818-9140-c6432152c23e",
  "status": "paid",
  "authorized": true,
  "acquirer": "vortex",
  "acquirer_message": "Pagamento autorizado.",
  "decline_code": null,
  "retryable": false,
  "card": { "brand": "visa", "last4": "0010" },
  "amount_cents": 4990,
  "currency": "EUR",
  "created_at": "2026-10-27T06:35:09Z"
}

Resposta 201 (recusado):

JSON
{
  "transaction_id": "6ea30223-578f-4f3f-b9fb-24ff227c2f17",
  "status": "failed",
  "authorized": false,
  "acquirer": "vortex",
  "acquirer_message": "Cartão recusado.",
  "decline_code": "r800",
  "retryable": false,
  "card": { "last4": "0010" },
  "amount_cents": 4990,
  "currency": "EUR",
  "created_at": "2026-10-27T06:35:09Z"
}

Como ler a resposta#

Toda cobrança que chega a ser criada responde 201 com o transaction_id. O resultado está no campo status:

status O que significa O que fazer
paid Aprovado. A venda já está na sua carteira, como qualquer venda de cartão Libere o pedido
pending Autorizado pelo banco e em análise de risco, ou resultado ainda em confirmação Aguarde o webhook transaction.paid ou consulte GET /api/v1/transactions/{id}. Não cobre de novo
failed Recusado, ou não processado. Nada foi cobrado Leia acquirer_message para o comprador. Com retryable: true, crie uma nova cobrança (token novo e Idempotency-Key nova)

Nota Na Vortex a aprovação nem sempre é imediata. O banco do comprador autoriza na hora, mas a venda ainda passa por uma análise de risco antes de virar paga. Nesse intervalo o status é pending, e isso é normal: não trate como falha e não cobre de novo. O desfecho chega em segundos, pelo webhook. Uma reprovação na análise fecha a venda como recusada.

Erros 4xx, 429 e 503 antes da cobrança significam que nada foi criado: corrija e repita, inclusive com a mesma Idempotency-Key. Uma chamada com a mesma Idempotency-Key e o mesmo corpo de uma cobrança já feita devolve a resposta original (cabeçalho Idempotent-Replay: true), sem cobrar de novo.

Campos do passo 2#

Campo Tipo Obrigatório O que é
amount_cents integer sim Valor na menor unidade da moeda (€ 49,90 = 4990). Em moedas sem casa decimal, a unidade inteira (¥ 5000 = 5000)
currency string sim Código de 3 letras, maiúsculas ou minúsculas. As 48 da lista
card_token string sim O token do passo 1
customer.name string sim Nome do comprador, até 120 caracteres
customer.email string sim E-mail válido do comprador, até 180 caracteres
customer.phone string não Telefone do comprador, até 30 caracteres
customer.ip string sim IP de onde o comprador está, nunca o do seu servidor. Sem ele a chamada volta 422 customer_ip_required_for_vortex e nada é criado
customer.document string não CPF ou CNPJ do comprador, até 20 caracteres. Mande quando tiver: um documento válido entra na análise de risco da adquirente e aumenta a aprovação
description string não Até 255 caracteres. Volta em metadata.description na consulta e no webhook
metadata object não Até 20 chaves com valores simples (texto, número ou booleano). Volta na consulta e no webhook. Chaves de uso interno são recusadas com 422 metadata_reserved_key: as que começam com throne_, vortex_, stripe_, chargeback_, refund_, partial_ ou original_, e nomes como description, currency, acquirer, items e seller_id. Use nomes seus, como order_id ou pedido
recurrence object não Recorrência: cycle (um dos sete ciclos) e max_payments opcional, de 2 a 120. Esta cobrança é a primeira e as seguintes saem sozinhas, no mesmo cartão. Veja Recorrência
Idempotency-Key header sim Uma chave nova por cobrança (UUID v4). Veja Comece aqui

Nome e e-mail do comprador são obrigatórios nesta modalidade, ao contrário da integração direta da Eminence. Sem eles, ou fora dos tamanhos, a chamada volta 422 customer_required_for_vortex e nada é criado.

Nesta adquirente a autorização do banco vem primeiro e a análise de risco vem depois, então o que você manda do comprador decide a venda. Quanto mais real for o cadastro, mais vendas passam. Em ordem de peso:

  • customer.ip: obrigatório. O IP de onde o comprador está, nunca o do seu servidor.
  • customer.document: CPF ou CNPJ, quando o comprador tem um.
  • customer.phone: com DDD, no formato brasileiro. Um número que não existe pesa contra.
  • customer.email: um endereço que recebe mensagem de verdade.

Mandar um campo com valor inventado é pior do que não mandar: a adquirente confere o que pode conferir.

Campos da resposta#

Campo O que é
transaction_id Id público da venda. Use no GET /api/v1/transactions/{id} e para casar com o webhook
status paid, pending ou failed (veja a tabela acima)
authorized true só quando aprovado
acquirer Sempre vortex
acquirer_message Texto pronto para mostrar ao comprador. Pode mudar; decida pelo status
decline_code Código da recusa devolvido pela adquirente, ou um destes: invalid_card_token, invalid_request, idempotency_mismatch, processing_unavailable. null quando não se aplica
retryable true quando vale tentar de novo com uma nova cobrança
card Bandeira e últimos 4 dígitos, quando conhecidos
amount_cents O valor que você cobrou, na menor unidade da moeda enviada
currency A moeda que você enviou
created_at Data da criação, ISO 8601 em UTC
recurrence_id Só com recurrence na chamada: o id da recorrência, para consultar e cancelar. Nulo quer dizer que a assinatura não abriu
cycle Só com recurrence: o ciclo gravado
next_charge_at Só com recurrence: estimativa da próxima cobrança, ISO 8601 em UTC

Consulta#

A venda da integração direta é uma transação comum do Throne. Use GET /api/v1/transactions/{id} com o transaction_id.

Estorno#

Pelo suporte, como em qualquer venda de cartão. Não existe endpoint de estorno. Veja Status e ciclo de vida.

Webhook#

Igual ao cartão pelo Throne Elements: transaction.paid quando a venda é aprovada, inclusive as que ficaram pending em análise e foram aprovadas depois. O payload é o mesmo de sempre, com currency, native_amount_cents e fx_rate. Veja Webhooks.

Upsell em um clique#

Cobra um segundo produto no mesmo cartão de uma venda já paga, sem pedir o cartão outra vez ao comprador e sem card_token nenhum. É a oferta que aparece depois do obrigado: o comprador clica uma vez e pronto.

Habilitação à parte. Ter a integração direta liberada não basta: o upsell em um clique é liberado conta por conta. Sem isso, a rota responde 403 one_click_not_enabled. Fale com o suporte.

A chamada#

HTTP
POST /api/v1/vortex/upsell
Authorization: Bearer pk_live_xxx:sk_live_xxx
Content-Type: application/json
Idempotency-Key: upsell-pedido-9001
JSON
{
  "parent_transaction_id": "e1b9c0a4-7f3d-4e21-9a8b-3c5d6e7f8a90",
  "amount_cents": 4700,
  "currency": "USD",
  "description": "Plano anual",
  "metadata": { "pedido": "9001-up1" }
}

O parent_transaction_id é o transaction_id que você recebeu na cobrança da venda de origem. Nunca um id do processador.

Não existe card_token nesta rota, e é esse o ponto. Também não existem customer nem installments: o comprador é o da venda de origem e o upsell é sempre à vista. Mandar qualquer um desses campos volta 422 field_not_supported, e nada é criado — é de propósito, para você não receber um 201 achando que mandou um cartão.

O upsell pode ser recorrente#

A venda de origem é única; o upsell pode se repetir. É a assinatura vendida no pós-compra: o comprador pagou o produto à vista e assinou com um clique.

Mande o mesmo campo recurrence da cobrança comum:

JSON
{
  "parent_transaction_id": "e1b9c0a4-7f3d-4e21-9a8b-3c5d6e7f8a90",
  "amount_cents": 4700,
  "currency": "USD",
  "recurrence": { "cycle": "monthly", "max_payments": 12 }
}

cycle é um de weekly, biweekly, monthly, bimonthly, quarterly, semiannually ou yearly. max_payments é opcional, de 2 a 120, e conta este upsell como a primeira cobrança; sem ele, a recorrência segue até você cancelar em /recurrences.

A resposta 201 ganha três campos:

JSON
{
  "transaction_id": "9f2c1d7e-4a8b-4c3d-8e9f-1a2b3c4d5e6f",
  "status": "pending",
  "recurrence_id": "rec_a1b2c3d4e5f60718293a4b5c",
  "cycle": "monthly",
  "next_charge_at": "2026-11-28T18:04:11Z"
}

A assinatura só passa a valer quando este upsell for aprovado, e aqui a aprovação nunca é imediata (veja acima). Até lá a recorrência fica pending. recurrence_id nulo, com cycle e next_charge_at nulos, quer dizer que a cobrança foi criada mas a assinatura não abriu: não haverá cobranças seguintes.

Ciclo fora dos sete volta 422 invalid_cycle com a lista na mensagem, e nada é criado nem cobrado. max_payments sem cycle é pedido pela metade e volta 422 validation_failed.

A resposta#

Sempre 201 quando a venda é criada, com o status real:

JSON
{
  "transaction_id": "9f2c1d7e-4a8b-4c3d-8e9f-1a2b3c4d5e6f",
  "status": "pending",
  "authorized": false,
  "acquirer": "vortex",
  "acquirer_message": "Pagamento em análise. O resultado chega pelo webhook e pela consulta da venda.",
  "decline_code": null,
  "retryable": false,
  "card": { "brand": "visa", "last4": "4242" },
  "amount_cents": 4700,
  "currency": "USD",
  "one_click": true,
  "created_at": "2026-10-28T18:04:11Z"
}

pending é o desfecho normal aqui, e ele já significa cobrado. Nesta adquirente o cartão não aprova na hora, e no upsell há um motivo a mais: o processador confirma a cobrança sem devolver o número do pedido dela, que chega depois, no aviso. Então:

  • espere o webhook transaction.paid, como em qualquer venda pending;
  • não repita a chamada. Repetir cobra de novo. Se o seu cliente HTTP desistir antes da resposta, consulte a venda pelo GET ou repita a mesma chamada com a mesma Idempotency-Key.

failed é recusa de verdade: o decline_code e o acquirer_message dizem o motivo, e retryable diz se vale repetir (com uma Idempotency-Key nova).

O que a venda de origem precisa ser#

Regra Valor
Da sua conta sempre; venda de outra conta responde como inexistente
Paga paid, sem estorno e sem contestação
Dentro da janela 120 minutos desde o pagamento
Dentro do teto no máximo 5 upsells por venda de origem
Mesma adquirente a venda de origem tem de ser da Vortex
Com cartão guardado a venda de origem tem de ter sido cobrada pela Vortex depois de 28/10/2026; antes disso o cartão não era guardado

Upsell de upsell funciona: o segundo aponta para o primeiro no parent_transaction_id, e os dois contam no teto da venda que abriu o funil.

Erros#

Antes de criar a venda (nada foi criado, a Idempotency-Key fica livre):

HTTP error O que aconteceu O que fazer
403 one_click_not_enabled O upsell em um clique não está liberado na conta Fale com o suporte
403 seller_not_approved A conta não está aprovada Fale com o suporte
422 field_not_supported Mandou card_token, customer, recurrence, installments ou one_click_from Tire o campo do corpo
422 validation_failed Campo inválido; errors lista cada um Corrija o corpo
422 acquirer_not_enabled Vortex não habilitada Fale com o suporte
422 currency_not_supported Moeda fora das aceitas Use uma moeda da lista
422 fx_unavailable Cotação momentaneamente indisponível Espere o Retry-After (60 s) e repita
422 amount_out_of_range Valor fora da faixa. A resposta traz min_amount_cents, max_amount_cents e currency, na moeda que você enviou Ajuste o valor
422 metadata_reserved_key Chave de metadata reservada Troque o nome da chave
422 invalid_cycle O recurrence.cycle não é um dos sete. A resposta traz a lista Mande um dos sete
422 recurrence_not_supported A cobrança recorrente não está disponível nesta adquirente no momento Fale com o suporte, ou cobre sem recurrence
409 parent_not_found Não existe venda sua com esse parent_transaction_id Confira o id
409 parent_not_paid A venda de origem não está paga Espere o transaction.paid dela
409 parent_refunded A venda de origem foi estornada Não serve de origem
409 parent_charged_back A venda de origem foi contestada Não serve de origem
409 parent_too_old A venda de origem passou dos 120 minutos Cobre pelo caminho normal, com card_token
409 upsell_limit_reached A venda de origem já tem 5 upsells Cobre pelo caminho normal
409 parent_other_acquirer A venda de origem é de outra adquirente O upsell cai na mesma adquirente dela
503 temporarily_unavailable Indisponível no momento Aguarde o Retry-After e repita

Depois de criada, a venda responde 201 com o status, e aí o error do corpo dá lugar ao decline_code:

decline_code O que aconteceu O que fazer
one_click_unavailable A venda de origem não tem cartão guardado (foi cobrada antes de 28/10/2026, ou pelo checkout da Vortex) Cobre pelo caminho normal, com card_token
declined O processador recusou a cobrança Mostre o acquirer_message ao comprador
unavailable Nada foi decidido no processador; nada foi cobrado Repita com uma Idempotency-Key nova
invalid_request O corpo não passou na validação da ponte Corrija e repita com uma chave nova
processing_unavailable Não deu para processar agora; nada foi cobrado Repita com uma Idempotency-Key nova

Dinheiro e webhook#

Igual a qualquer venda de cartão: o upsell entra na sua carteira com a sua taxa, obedece à retenção e à maturação da conta, e o webhook é o transaction.paid de sempre, com currency, native_amount_cents e fx_rate. Nenhum campo novo entra no seu webhook: amarre o upsell ao funil pelo transaction_id que esta chamada devolveu.

Checkout da Vortex (iframe)#

O upsell em um clique existe só na integração direta. No checkout hospedado da Vortex o campo one_click_from continua respondendo one_click: false.

Recorrência#

A integração direta aceita o mesmo campo recurrence do checkout comum: esta cobrança é a primeira e as seguintes saem sozinhas, no mesmo cartão, sem novo card_token e sem nova chamada sua.

No passo 1 (tokenização):

HTTP error O que aconteceu O que fazer
401 unauthorized Chave de API ausente ou inválida Confira o Authorization
403 scope_required A chave não tem transactions:write Gere uma chave com esse escopo
403 seller_not_approved A conta não está aprovada (suspensa ou em análise) Fale com o suporte
422 partner_api_not_enabled Integração direta da Vortex não liberada Fale com o suporte
422 acquirer_not_enabled Vortex não habilitada Fale com o suporte
422 invalid_card Número, validade, CVV ou nome inválidos. O campo field diz qual Peça ao comprador para conferir o cartão
429 rate_limit_exceeded Limite de requisições por segundo Aguarde 1 segundo e repita
503 temporarily_unavailable Tokenização indisponível no momento Repita em alguns segundos

No passo 2 (cobrança), antes de criar a venda (nada foi criado):

HTTP error O que aconteceu O que fazer
400 idempotency_key_required Faltou o cabeçalho Idempotency-Key Envie uma chave por cobrança
401 unauthorized Chave de API ausente ou inválida Confira o Authorization
403 scope_required A chave não tem transactions:write Gere uma chave com esse escopo
403 seller_not_approved A conta não está aprovada (suspensa ou em análise) Fale com o suporte
422 partner_api_not_enabled Integração direta da Vortex não liberada Fale com o suporte
422 acquirer_not_enabled Vortex não habilitada Fale com o suporte
422 validation_failed Campo inválido; errors lista cada um Corrija o corpo
422 customer_required_for_vortex Faltou customer.name ou customer.email, ou um deles está fora do tamanho Mande os dois campos
422 currency_not_supported Moeda fora das 48 aceitas Use uma moeda da lista
422 fx_unavailable Cotação momentaneamente indisponível Espere o Retry-After (60 s) e repita
422 invalid_card_token card_token fora do formato Tokenize de novo
422 invalid_cycle O recurrence.cycle não é um dos sete ciclos aceitos. A resposta traz a lista. Nada foi criado Mande um de weekly, biweekly, monthly, bimonthly, quarterly, semiannually ou yearly
422 recurrence_not_supported A cobrança recorrente não está disponível nesta adquirente no momento. Nada foi criado Fale com o suporte, ou cobre sem o campo recurrence
422 one_click_not_supported Mandou one_click_from nesta rota. O upsell em um clique tem rota própria. Nada foi criado Use POST /api/v1/vortex/upsell
422 amount_out_of_range Valor fora da faixa aceita. A resposta traz min_amount_cents, max_amount_cents e currency, sempre na moeda que você enviou Ajuste o valor
422 metadata_reserved_key Chave de metadata reservada Troque o nome da chave
422 idempotency_key_mismatch A mesma Idempotency-Key com outro corpo Use uma chave nova
409 idempotency_key_processing A mesma Idempotency-Key ainda está em processamento Aguarde a primeira resposta
429 rate_limit_exceeded Limite de requisições por segundo Aguarde o Retry-After e repita
503 temporarily_unavailable ou busy Cobrança indisponível no momento Aguarde o Retry-After e repita

Depois de criada, a venda responde sempre 201 com o status (veja Como ler a resposta).

Dinheiro#

O fluxo financeiro é igual ao cartão pelo Throne Elements: a venda aprovada entra na sua carteira com a sua taxa de cartão, obedece à retenção e à maturação da sua conta e pode ser antecipada ou sacada do mesmo jeito. A cotação que credita o seu saldo é fixada na criação da cobrança e volta no webhook em fx_rate. Veja Moedas e limites.

Limites e tempos#

  • Timeout do seu cliente HTTP: 45 segundos no passo 1 e 120 segundos no passo 2. Na prática as respostas levam poucos segundos.
  • Limite por conta: 10 requisições por segundo em cada passo, por padrão (o suporte ajusta). Acima disso, 429 rate_limit_exceeded.
  • Tetos fixos, que não mudam com o ajuste da conta: 10 tokenizações por segundo por IP no passo 1 e 6 cobranças em andamento ao mesmo tempo no passo 2 (acima disso, 503 busy com Retry-After, e nada é criado).
  • Mínimo e máximo por cobrança variam com a moeda e com a cotação do dia. Fora da faixa, 422 amount_out_of_range com os limites na sua moeda.
  • Um card_token por cobrança: ele é de uso único.
  • Se o seu cliente desistir antes da resposta do passo 2, consulte a venda pelo GET ou repita a mesma chamada com a mesma Idempotency-Key. Nunca crie uma cobrança nova para o mesmo pedido sem saber o resultado da anterior.

Testar#

No Throne não existe ambiente de testes separado: use um cartão de verdade com valor baixo e peça o estorno ao suporte. Cartão sem saldo, bloqueado para compra online ou com dados errados volta failed com o motivo em acquirer_message. Veja Como testar.

Checklist#

  • Vortex habilitada e integração direta da Vortex liberada na conta (fale com o suporte).
  • Chave de API com transactions:write, guardada só no servidor.
  • Página de pagamento manda o cartão ao seu servidor; o seu servidor chama o Throne.
  • Número, validade e CVV nunca gravados em banco, arquivo ou log.
  • Um card_token novo por cobrança.
  • customer.name e customer.email em toda cobrança.
  • Idempotency-Key nova por cobrança e timeout de 120 segundos no passo 2.
  • Decisão pelo status: paid libera, pending espera o webhook, failed mostra o acquirer_message.
  • Webhook transaction.paid tratado como no cartão pelo Throne Elements.
  • Teste real de valor baixo antes de abrir ao público.

Se você vai usar o upsell em um clique, mais três:

  • Upsell em um clique liberado na conta (é à parte da integração direta).
  • Guardado o transaction_id de cada venda paga, para usar em parent_transaction_id dentro dos 120 minutos.
  • O upsell pending nunca é repetido: você espera o webhook.
  • Se o upsell for recorrente: recurrence_id conferido na resposta, e o acesso liberado pelo transaction.paid de cada cobrança, não pelo next_charge_at (que é estimativa).