O que é#
O Checkout Brasil é o checkout de cartão para o comprador brasileiro. Você cria o checkout com POST /elements/checkout/br e coloca o transaction_id no mesmo Throne Elements que já usa. O que muda está na página que o comprador vê: ela sai sempre em português, pede o CPF junto com o cartão e abre para comprador de qualquer país.
O nome e o CPF que o comprador digita vão para a adquirente junto com o cartão, na autorização. São os dados que o emissor de um cartão brasileiro espera receber numa compra.
Nota Nada a mudar no que já está no ar. O
POST /elements/checkoutcontinua igual, com a mesma resposta e o mesmo webhook. O Checkout Brasil é um endpoint a mais, para a página do seu funil que vende ao comprador brasileiro.
Antes de começar#
O Checkout Brasil funciona nas adquirentes habilitadas para o Checkout Brasil na sua conta. As adquirentes de cartão da sua conta estão em GET /elements/acquirers, mas nem toda adquirente atende o Checkout Brasil: se nenhuma das suas atender, a criação responde 422 acquirer_not_enabled e nada é criado. Para pedir a habilitação, fale com o suporte.
- A chave de API é a mesma, com a permissão
transactions:write. Nenhuma chave precisa ser gerada de novo. - O comprador precisa ter CPF. Sem um CPF válido, o pagamento não sai da página. Para o comprador sem CPF, use o checkout comum.
- A
Idempotency-Key, o timeout de 60 segundos e a regra de repetição são os de sempre. Veja Comece aqui.
Criar#
A criação fala com a adquirente. Use 60 segundos de timeout no seu cliente HTTP e gere a Idempotency-Key antes de chamar, guardando junto do pedido. Use uma chave nova, nunca a de uma chamada ao POST /elements/checkout: a chave devolve a resposta da chamada em que foi usada.
curl -X POST https://app.thronecorporate.com/api/v1/elements/checkout/br \
--max-time 60 \
-H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"amount_cents": 9700,
"currency": "brl",
"customer": { "name": "Maria Souza", "email": "maria@exemplo.com" }
}'201 Created:
{
"transaction_id": "c4d7a2b1-6e3f-4a9c-8b5d-2f1e0a9c7b63",
"status": "pending",
"checkout_url": "https://pay.example.com/checkout/5a4b3c2d1e0f99887766554433221100",
"display": { "currency": "BRL", "amount_cents": 9700 },
"expires_at": "2026-10-20T14:20:00Z"
}A resposta é a mesma do checkout comum: transaction_id, status, checkout_url, acquirer (a adquirente que ficou com a venda), display, expires_at e, quando houver aviso, warnings. Veja a resposta do checkout comum. O que é próprio do Checkout Brasil está em Referência dos campos.
Na sua página, nada muda:
<div data-throne-elements
data-id="c4d7a2b1-6e3f-4a9c-8b5d-2f1e0a9c7b63"
data-color="#7c3aed"
data-theme="light"
data-radius="10"></div>
<script src="https://app.thronecorporate.com/throne-elements.js" async></script>O elemento monta a página em português, com o campo de CPF junto dos dados do cartão. O comprador digita o cartão, o nome e o CPF, e paga. Os eventos throne-elements:ready, throne-elements:paid e throne-elements:error chegam como sempre. A confirmação que vale para liberar o pedido continua sendo o webhook transaction.paid ou o GET /transactions/{id} com status: "paid".
O que muda em relação ao checkout comum#
| Item | Checkout comum | Checkout Brasil |
|---|---|---|
| Endpoint | POST /elements/checkout |
POST /elements/checkout/br |
| Idioma da página | Pelo país do comprador | Sempre português, seja qual for o país do comprador, o idioma do navegador ou o ?nl= no checkout_url |
| CPF | Não pede | Pede na tela. Obrigatório e conferido antes do envio |
| País do comprador | Segue o país do comprador | Qualquer país: a página abre e o pagamento vai para a adquirente seja qual for o país do comprador ou do cartão |
| Adquirente | A pedida em acquirer ou a padrão da conta |
A habilitada para o Checkout Brasil na conta. acquirer é opcional e só aceita uma que atenda o Checkout Brasil. O roteamento fixado na conta e o roteamento por valor não valem aqui |
one_click_from e recurrence |
Aceitos | Não existem: 422 field_not_supported |
| Aparência da página | data-color, data-theme e data-radius do elemento |
Os mesmos, mais o objeto appearance na criação: texto do botão, valor no botão, cores, formato, tamanho e moldura. Veja Aparência |
| Throne Elements, eventos, moedas, limites, tentativas, validade de 24 horas, status e webhook | Iguais | Iguais |
O comportamento da página depois do clique em pagar (verificação do banco, tentativas, códigos em throne-elements:error) é o da adquirente que ficou com a venda, como no checkout comum: veja o guia dela em Comparar adquirentes.
Aparência#
Você pode ajustar a página do Checkout Brasil na própria criação, com o objeto appearance: o texto do botão, se o valor aparece nele, as cores, o arredondamento, a altura e a largura do botão, e uma moldura em volta dos campos. Tudo é opcional. O que você não mandar segue o padrão e os atributos data-color e data-radius do elemento, como hoje.
curl -X POST https://app.thronecorporate.com/api/v1/elements/checkout/br \
--max-time 60 \
-H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"amount_cents": 9700,
"currency": "brl",
"appearance": {
"button": { "text": "Finalizar compra", "background_color": "#15803d" },
"fields": { "radius": 8 },
"frame": { "border_width": 1, "padding": 24, "shadow": "md" }
}
}'O botão sai "Finalizar compra R$ 97,00" em verde, com o texto em branco escolhido sozinho para ficar legível, e os campos ficam dentro de uma moldura com borda e sombra.
| Campo | Aceita | Padrão | O que faz |
|---|---|---|---|
button.text |
Texto de 2 a 32 caracteres: letras, com ou sem acento, espaço e ! ? , - ', com pelo menos uma letra |
Pagar |
Texto do botão. Número, símbolo de moeda e as palavras da lista abaixo não entram: o valor aparece sozinho |
button.show_amount |
true ou false |
true |
Mostra o valor depois do texto. Com false, o botão mostra só o texto e o valor aparece fora dele: logo acima do botão, ou no topo do formulário quando a venda é criada em outra moeda |
button.background_color |
Cor #rrggbb |
O data-color |
Cor do botão |
button.text_color |
Cor #rrggbb, só junto de background_color |
Escolhida sozinha | Cor do texto do botão. O contraste com o fundo precisa ser de 3:1 ou mais |
button.radius |
Inteiro de 0 a 32 |
O dos campos | Arredondamento do botão, em px. Com a metade da altura, o botão vira pílula |
button.height |
Inteiro de 44 a 64 |
48 |
Altura mínima do botão, em px. Texto longo quebra a linha e o botão cresce |
button.full_width |
true ou false |
true |
Com false, o botão fica do tamanho do texto, centralizado, com no mínimo 200 px |
fields.focus_color |
Cor #rrggbb |
button.background_color, senão o data-color |
Cor de destaque: a borda do campo em foco, o contorno de foco do botão e o indicador da tela de espera |
fields.radius |
Inteiro de 0 a 32 |
O data-radius, senão 10 |
Arredondamento dos campos, em px |
frame.max_width |
Inteiro de 320 a 720 |
460 |
Largura máxima do checkout, em px |
frame.padding |
Inteiro de 0 a 40 |
0 |
Espaço entre a moldura e os campos, em px. Em tela de até 400 px, no máximo 6 |
frame.border_width |
Inteiro de 0 a 3 |
0 |
Espessura da borda da moldura. Com só border_color, vale 1. Em tela de até 400 px, no máximo 1 |
frame.border_color |
Cor #rrggbb |
A cor das linhas dos campos | Cor da borda |
frame.radius |
Inteiro de 0 a 32 |
12 |
Arredondamento da moldura |
frame.shadow |
none, sm, md ou lg |
none |
Sombra da moldura. Em site escuro, prefira a borda: a sombra quase não aparece |
Como a validação funciona:
- Mande JSON com os tipos certos:
48, não"48";false, não"false". Uma chave comnullvale como ausente. - Chave que não existe, valor fora da regra ou combinação impossível:
422 invalid_appearancee nada é criado. A resposta trazfieldcom o caminho da chave, por exemploappearance.button.text. - O texto do botão não aceita, em maiúsculas ou minúsculas, as palavras real, reais, centavo, centavos, grátis, gratis, gratuito, gratuita, free, zero, cancelar, voltar, fechar e sair: o botão sempre paga o valor da venda.
- Contraste:
text_colorcom contraste menor que 3:1 sobrebackground_coloré recusado. De 3:1 até 4,5:1 é aceito, com o avisolow_contrastemwarnings. Branco sobre#16a34adá 3,29:1 (aceito, com aviso); branco sobre#15803d, 5,01:1. fields.focus_colorque quase some sobre fundo claro ou escuro também geralow_contrast.- A moldura precisa deixar pelo menos 256 px para os campos:
frame.max_width, menos 32 (ou 56 comshadow: lg), menos duas vezes a soma deframe.paddingeframe.border_width.
Quem vence quando você também usa os atributos do elemento:
| Aspecto | Sem a chave em appearance |
Com a chave |
|---|---|---|
| Cor do botão | data-color |
button.background_color |
| Cor de destaque dos campos | data-color |
fields.focus_color, senão button.background_color |
| Arredondamento | data-radius, nos campos e no botão |
fields.radius e button.radius |
| Tema e cor de fundo | data-theme e a detecção do fundo do seu site |
Os mesmos: appearance não muda |
As chaves que você manda ficam gravadas na criação e não mudam pela URL do checkout; as que você não manda seguem os atributos do elemento. Para mudar o que foi gravado, crie um checkout novo.
O que não muda: os nomes e os exemplos dos campos (número do cartão, nome no cartão, validade, CVV e CPF), a frase de segurança abaixo do botão, os textos de processamento, de verificação do banco, de aprovação e de recusa, o botão "Tentar de novo", a fonte e as bandeiras. São os textos que o comprador e o banco esperam ver numa página de pagamento.
O botão em cada momento: antes do clique, o seu texto, com ou sem o valor; durante o envio, "Processando", desativado e nas suas cores; recusado, a tela de recusa com "Tentar de novo", e de volta ao formulário o botão volta ao seu texto; aprovado, a tela de pagamento aprovado.
Erros#
Os erros do checkout comum valem aqui, com o mesmo significado: invalid_amount, currency_not_supported, fx_unavailable, card_not_enabled, invalid_acquirer, os de Idempotency-Key, 502 checkout_failed e 503 temporarily_unavailable. Veja a tabela do checkout comum. O que é próprio do Checkout Brasil:
| Status | error |
message |
Quando | Repetir |
|---|---|---|---|---|
422 |
acquirer_not_enabled |
O Checkout Brasil não está habilitado para nenhuma adquirente da sua conta. Fale com o suporte. | A conta não tem adquirente habilitada para o Checkout Brasil. Nada foi criado | Não, até habilitar |
422 |
acquirer_not_enabled |
A adquirente pedida não está habilitada para o Checkout Brasil na sua conta. | O campo acquirer pediu uma adquirente que não atende o Checkout Brasil. Nada foi criado |
Com chave nova, sem o campo ou com outra adquirente |
422 |
field_not_supported |
O campo one_click_from não é aceito no Checkout Brasil. Remova o campo e repita a chamada. | O corpo trouxe one_click_from ou recurrence. Nada foi criado |
Com chave nova, sem o campo |
422 |
invalid_appearance |
appearance.button.color não existe. Em appearance.button valem: text, show_amount, background_color, text_color, radius, height e full_width. | O objeto appearance trouxe chave que não existe, valor fora da regra ou combinação impossível. O campo field diz qual chave. Nada foi criado |
Com chave nova, depois de corrigir |
No Checkout Brasil, invalid_amount vem com alternatives vazio e o 503 não sugere outra adquirente: acima do máximo, divida o pedido.
Decida sempre pelo campo error. O message é texto de apoio e pode mudar.
Perguntas que aparecem sempre#
O CPF do comprador fica guardado? Não. Ele vai para a adquirente na autorização do pagamento e só. O Throne não guarda o CPF digitado, e ele não volta na consulta nem no webhook. Se você quiser o documento registrado na venda, mande customer.document na criação, como no checkout comum.
Serve para Pix? Não. O Checkout Brasil é só cartão. Para Pix, use POST /transactions com payment_method: "pix", como em Cobrar com Pix.
Posso usar o mesmo Throne Elements? Sim. O script, os atributos e os eventos são os mesmos: só troque o data-id pelo transaction_id novo. Vale a regra de sempre: para trocar de checkout, use um container novo (detalhes).
Preciso de outra chave de API? Não. A mesma chave, com transactions:write, cria os dois checkouts.
E se o comprador não tiver CPF? O pagamento não sai: o campo é obrigatório e conferido na tela. Para esse comprador, crie o checkout comum.
O customer.document da criação preenche o CPF? Não. O campo CPF da página nasce vazio e o comprador digita o dele. O que vai para a adquirente é o CPF digitado na tela; o customer.document fica registrado na venda e volta no webhook, como no checkout comum.
O ?nl= no checkout_url muda o idioma? Não. No Checkout Brasil a página sai em português sempre, inclusive para teste.
A venda aparece diferente na consulta ou no webhook? Não. É uma venda de cartão como as outras: mesmo GET /transactions/{id}, mesmo transaction.paid, mesmo acquirer.
Posso mudar a frase de segurança ou o nome dos campos? Não. Só o botão, as cores, o formato e a moldura mudam, pelo objeto appearance. O resto é o texto que o comprador e o banco esperam ver numa página de pagamento.
O appearance funciona no POST /elements/checkout? Não. Ele só existe no Checkout Brasil; no checkout comum o campo é ignorado.
Referência dos campos#
Requisição, POST /elements/checkout/br:
| Campo | Obrigatório | Regra |
|---|---|---|
amount_cents |
Sim | Inteiro na menor unidade da moeda (R$ 97,00 = 9700). Mínimo e máximo como no checkout comum: pela adquirente, pela moeda e pela cotação do dia |
currency |
Sim | Código de 3 letras, maiúsculas ou minúsculas. As mesmas 48 moedas do checkout comum; para o comprador brasileiro, brl |
acquirer |
Não | Só uma adquirente habilitada para o Checkout Brasil na sua conta; outra volta 422 acquirer_not_enabled. Sem o campo, a venda vai para a habilitada |
customer.name |
Não | Como no checkout comum: vai pré-preenchido no nome do cartão, e o comprador pode corrigir |
customer.email, customer.document, customer.document_type, customer.phone, customer.address |
Não | Como no checkout comum: ficam registrados na venda e voltam no webhook. Nenhum gera erro; o que vier fora do formato é ajustado ou descartado, com aviso em warnings |
appearance |
Não | Objeto com button, fields e frame. Veja Aparência. Fora da regra: 422 invalid_appearance |
one_click_from, recurrence |
Não existem | 422 field_not_supported |
metadata e itens não são aceitos, como no checkout comum: guarde o transaction_id para ligar a venda ao seu pedido.
Resposta 201: os mesmos campos do checkout comum. Veja a referência da resposta. O que é próprio do Checkout Brasil:
warningspode trazer, além dos avisos decustomer, o avisolow_contrast, sobreappearance.
Veja também Cartão: como funciona e Throne Elements.