Snippet HTML pronto · QR Code automático · webhook configurado · funciona com qualquer checkout próprio. Sem SDK obrigatório.
Crie sua conta seller no Throne · envie documentos KYC (RG + Selfie) · aprovação em até 24h dias úteis. Você recebe email confirmando que pode operar.
Criar conta seller →Acesse /painel/integracao · copie pk_live + sk_live. A secret key aparece UMA VEZ no email de aprovação · guarde em local seguro.
# .env do seu site THRONE_PK=pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx THRONE_SK=sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx THRONE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HTML + JS puro · sem dependências · funciona em qualquer site (WordPress, custom, Next.js, etc).
<!-- Adicione no seu checkout --> <form id="pix-checkout"> <input name="produto" value="Plano Premium" /> <input name="amount_cents" value=9900 /> <!-- R$ 99 --> <input name="sku" value="premium-001" /> <input name="payer_email" placeholder="seu@email.com" /> <input name="payer_cpf" placeholder="000.000.000-00" /> <button type="submit">Pagar com PIX</button> </form> <div id="pix-result"></div> <script> document.getElementById('pix-checkout').addEventListener('submit', async (e) => { e.preventDefault(); const data = Object.fromEntries(new FormData(e.target)); // Chama seu backend que tem as keys (NUNCA expor SK no frontend) const r = await fetch('/api/criar-pix', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); const tx = await r.json(); // Renderiza QR Code + Copia e Cola document.getElementById('pix-result').innerHTML = ` <h3>Aguardando pagamento PIX</h3> <img src="data:image/png;base64,${tx.qr_code_base64}" /> <p>Ou copie o código:</p> <textarea>${tx.pix_payload}</textarea> <button onclick="navigator.clipboard.writeText('${tx.pix_payload}')">Copiar</button> `; // Polling status a cada 3s OU receber via webhook (recomendado) const poll = setInterval(async () => { const s = await fetch(`/api/tx/${tx.public_id}`).then(r => r.json()); if (s.status === 'paid') { clearInterval(poll); window.location = '/sucesso'; } }, 3000); }); </script>
Endpoint próprio que chama Throne API com auth Bearer. Exemplos em 4 linguagens:
Route::post('/api/criar-pix', function (Request $req) { $auth = base64_encode(env('THRONE_PK').':'.env('THRONE_SK')); $response = Http::withHeaders([ 'Authorization' => 'Bearer '.$auth, 'Idempotency-Key' => Str::uuid(), ])->post('https://api.thronecorporate.com/v1/transactions', [ 'payment_method' => 'pix', 'amount_cents' => (int) $req->amount_cents, 'payer_email' => $req->payer_email, 'payer_cpf' => $req->payer_cpf, 'description' => $req->produto, 'metadata' => ['sku' => $req->sku, 'order_id' => Str::uuid()], ]); return $response->json(); });
app.post('/api/criar-pix', async (req, res) => { const auth = Buffer.from(`${process.env.THRONE_PK}:${process.env.THRONE_SK}`).toString('base64'); const r = await fetch('https://api.thronecorporate.com/v1/transactions', { method: 'POST', headers: { 'Authorization': `Bearer ${auth}`, 'Idempotency-Key': crypto.randomUUID(), 'Content-Type': 'application/json', }, body: JSON.stringify({ payment_method: 'pix', amount_cents: req.body.amount_cents, payer_email: req.body.payer_email, payer_cpf: req.body.payer_cpf, description: req.body.produto, metadata: { sku: req.body.sku, order_id: crypto.randomUUID() }, }), }); res.json(await r.json()); });
@app.post('/api/criar-pix') def criar_pix(req): auth = base64.b64encode(f'{THRONE_PK}:{THRONE_SK}'.encode()).decode() r = requests.post( 'https://api.thronecorporate.com/v1/transactions', headers={ 'Authorization': f'Bearer {auth}', 'Idempotency-Key': str(uuid.uuid4()), }, json={ 'payment_method': 'pix', 'amount_cents': req.amount_cents, 'payer_email': req.payer_email, 'payer_cpf': req.payer_cpf, 'description': req.produto, 'metadata': {'sku': req.sku, 'order_id': str(uuid.uuid4())}, }, ) return r.json()
func criarPix(w http.ResponseWriter, r *http.Request) { auth := base64.StdEncoding.EncodeToString([]byte(os.Getenv("THRONE_PK") + ":" + os.Getenv("THRONE_SK"))) body := map[string]interface{}{ "payment_method": "pix", "amount_cents": req.AmountCents, "payer_email": req.PayerEmail, "description": req.Produto, "metadata": map[string]string{"sku": req.SKU}, } jsonBody, _ := json.Marshal(body) httpReq, _ := http.NewRequest("POST", "https://api.thronecorporate.com/v1/transactions", bytes.NewBuffer(jsonBody)) httpReq.Header.Set("Authorization", "Bearer "+auth) httpReq.Header.Set("Idempotency-Key", uuid.NewString()) resp, _ := http.DefaultClient.Do(httpReq) io.Copy(w, resp.Body) }
# Direto pela linha de comando · útil em scripts CI/CD curl -X POST https://api.thronecorporate.com/v1/transactions \ -H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "payment_method": "pix", "amount_cents": 9900, "payer_email": "cliente@example.com", "payer_cpf": "12345678901", "description": "Plano Premium", "metadata": {"sku": "premium-001", "order_id": "PED-42"} }'
require 'net/http' require 'json' require 'securerandom' def criar_pix(amount_cents, payer_email, sku) uri = URI('https://api.thronecorporate.com/v1/transactions') req = Net::HTTP::Post.new(uri, { 'Authorization' => "Bearer #{ENV['THRONE_PK']}:#{ENV['THRONE_SK']}", 'Content-Type' => 'application/json', 'Idempotency-Key' => SecureRandom.uuid, }) req.body = { payment_method: 'pix', amount_cents: amount_cents, payer_email: payer_email, description: 'Plano Premium', metadata: { sku: sku, order_id: SecureRandom.uuid }, }.to_json res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) } JSON.parse(res.body) end
// Java 17+ · HttpClient nativo (sem libs extras) import java.net.URI; import java.net.http.*; import java.util.UUID; public class ThronePixClient { public static String criarPix(int amountCents, String payerEmail, String sku) throws Exception { String auth = "Bearer " + System.getenv("THRONE_PK") + ":" + System.getenv("THRONE_SK"); String body = """ { "payment_method": "pix", "amount_cents": %d, "payer_email": "%s", "description": "Plano Premium", "metadata": {"sku": "%s"} } """.formatted(amountCents, payerEmail, sku); HttpRequest req = HttpRequest.newBuilder() .uri(URI.create("https://api.thronecorporate.com/v1/transactions")) .header("Authorization", auth) .header("Content-Type", "application/json") .header("Idempotency-Key", UUID.randomUUID().toString()) .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString()); return resp.body(); } }
Cada produto da sua loja tem own SKU + valor. Cada venda chega na Throne com metadata específica · sem mistura · sem bug.
Cada chamada POST /v1/transactions com metadata.sku próprio · resultado: 8 vendas independentes · cada uma com informações certas no painel.
Configure URL no painel · Throne envia POST sempre que tx muda status. Use webhook em vez de polling pra produção.
Route::post('/throne/webhook', function (Request $req) { // 1. Verifica signature (anti-spoofing) $payload = $req->getContent(); $signature = $req->header('X-Throne-Signature'); $expected = hash_hmac('sha256', $payload, env('THRONE_WEBHOOK_SECRET')); if (! hash_equals($expected, $signature)) { abort(401); } // 2. Process event $event = json_decode($payload, true); if ($event['type'] === 'transaction.paid') { $tx = $event['data']; // Marca pedido como pago · libera produto · envia email · etc Order::where('metadata->order_id', $tx['metadata']['order_id']) ->update(['status' => 'paid', 'paid_at' => now()]); } return response('ok', 200); // IMPORTANTE: 200 em < 30s });
Taxas Throne descontadas automaticamente antes do saldo · você recebe valor LÍQUIDO direto. Cautelar (anti-fraude) configurável pelo painel admin · proteção contra estornos.
Começar agora → Documentação API completa →