{"openapi":"3.1.0","info":{"title":"Throne API","version":"1.0.0","summary":"API REST do gateway Throne · PIX in/out + cripto out.","description":"## API REST do Throne\n\nUse esta API pra integrar o **Throne Gateway** no seu checkout, e-commerce\nou plataforma de assinatura. Suporta:\n\n- **Criar cobranças PIX** (QR Code copia-e-cola)\n- **Solicitar saques** PIX e cripto (com 2FA TOTP)\n- **Consultar saldo** disponível em tempo real\n- **Receber webhooks** dos eventos `transaction.paid`, `withdrawal.completed`, `withdrawal.failed`\n\n### Autenticação\n\nTodas as requisições usam `Authorization: Bearer pk_live_xxx:sk_live_xxx`.\n\n- **Public key** (`pk_live_*` ou `pk_test_*`) é o ID público da sua API key.\n- **Secret key** (`sk_live_*` ou `sk_test_*`) é o segredo · **NUNCA exponha em código cliente**.\n\nGere suas keys em [app.throne.com.br/painel/api-keys](https://app.throne.com.br/painel/api-keys).\nO secret aparece UMA VEZ na criação; depois é só hash bcrypt no servidor.\n\n### Idempotência\n\nToda operação mutante (POST/PUT/PATCH/DELETE) **exige** o header\n`Idempotency-Key`. Recomendamos um UUID v4 por operação. Se o cliente\nmandar a mesma key duas vezes em até 24h, retornamos a **mesma resposta**\nsem efeito duplicado · útil pra retry seguro.\n\n### Rate limits\n\n| Recurso | Limite |\n|---|---|\n| API geral | 10 req/seg/key |\n| Criação de saques | 1/min/seller |\n| Webhooks ingress | 50 req/seg/IP |\n\n### Money em centavos\n\nTodos os valores monetários são **inteiros em centavos** (BIGINT). Ex:\nR$ 10,50 = `1050`. Nunca floats · evita erros de arredondamento.","contact":{"name":"Throne · Suporte Developers","email":"developers@throne.com.br","url":"https://throne.com.br/developers"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://app.thronecorporate.com/api/v1","description":"API pública"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Saúde","description":"Endpoint de saúde sem auth."},{"name":"Transações","description":"Cobranças PIX (QR Code)."},{"name":"Saques","description":"PIX out e cripto out (exigem 2FA)."},{"name":"Saldo","description":"Consulta de saldo da wallet."}],"paths":{"/health":{"get":{"tags":["Saúde"],"summary":"Health check (sem auth)","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/balance":{"get":{"tags":["Saldo"],"summary":"Saldo atual da wallet","description":"Retorna saldo disponível, reservado (em saques) e pendente.","responses":{"200":{"description":"Saldo retornado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Balance"},"example":{"balance_cents":543210,"pending_balance_cents":0,"reserved_cents":50000,"available_cents":543210,"currency":"BRL"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/transactions":{"post":{"tags":["Transações"],"summary":"Criar cobrança PIX","description":"Gera QR Code copia-e-cola que o cliente final paga. Status inicial = `pending`. Quando o pagamento for confirmado pela adquirente, disparamos webhook `transaction.paid` e creditamos o saldo do seller.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTransactionRequest"},"example":{"amount_cents":10000,"payment_method":"pix","idempotency_key":"tx-pedido-2026-001","expires_at":"2026-05-06T18:00:00Z","customer":{"name":"João Cliente","document":"12345678901","email":"joao@example.com","phone":"+5511999999999"},"metadata":{"order_id":"PEDIDO-42","sku":"CAMISA-AZUL-M"}}}}},"responses":{"201":{"description":"Transação criada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/AcquirerError"}}}},"/transactions/{id}":{"get":{"tags":["Transações"],"summary":"Consultar transação","parameters":[{"$ref":"#/components/parameters/PublicId"}],"responses":{"200":{"description":"Transação encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/transactions/list":{"get":{"tags":["Transações"],"summary":"Listar transações (paginado)","description":"Lista as transações do seller. Aceita filtros por status, período e payment_method. Paginação cursor-based.","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","paid","failed","refunded","chargeback","expired"]},"description":"Filtra por status."},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Data inicial (YYYY-MM-DD)."},{"name":"until","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Data final (YYYY-MM-DD)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Cursor da página seguinte (opaco, vem em `next_cursor`)."}],"responses":{"200":{"description":"Lista paginada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/transactions/{id}/refund":{"post":{"tags":["Transações"],"summary":"Estornar transação paga","description":"Cria entry tipo `reverse` no ledger. Estorno parcial OK (passe `amount_cents`). Se omitir, estorna o líquido total.","parameters":[{"$ref":"#/components/parameters/PublicId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reason"],"properties":{"amount_cents":{"type":"integer","description":"Valor a estornar em centavos. Omitir = estorna o líquido total.","example":5000},"reason":{"type":"string","minLength":10,"description":"Motivo (mínimo 10 caracteres) · fica no audit log.","example":"Cliente solicitou cancelamento dentro do prazo de arrependimento"}}}}}},"responses":{"200":{"description":"Estorno aceito","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationError"}}}},"/withdrawals":{"post":{"tags":["Saques"],"summary":"Solicitar saque PIX ou cripto","description":"Exige **2FA TOTP** (`totp_code`) e **2FA habilitado** no seller. Lock pessimista impede over-draft mesmo em chamadas concorrentes. Após criar, status = `requested`. Webhook `withdrawal.completed` ou `withdrawal.failed` chega quando o banco confirma.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWithdrawalRequest"},"examples":{"pix":{"summary":"Saque PIX","value":{"amount_cents":50000,"totp_code":"123456","idempotency_key":"wdr-2026-05-06-001","destination":{"key":"a@b.com","key_type":"email"}}},"crypto":{"summary":"Saque cripto USDT TRC20","value":{"amount_cents":100000,"totp_code":"654321","idempotency_key":"wdr-crypto-001","destination":{"address":"TXXxxxxxxxxxxxxxxxxxxxxxxxxxx","network":"USDT_TRC20"}}}}}}},"responses":{"201":{"description":"Saque criado (status=requested)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Withdrawal"}}}},"401":{"description":"2FA inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Seller não aprovado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Saldo insuficiente / validação","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Limite diário ou rate limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/withdrawals/{id}":{"get":{"tags":["Saques"],"summary":"Consultar saque","parameters":[{"$ref":"#/components/parameters/PublicId"}],"responses":{"200":{"description":"Saque encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Withdrawal"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/withdrawals/list":{"get":{"tags":["Saques"],"summary":"Listar saques (paginado)","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["requested","approved","processing","completed","failed","reversed"]}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["pix","crypto"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Lista paginada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawalList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"pk_live_xxx:sk_live_xxx","description":"Bearer com `<public_key>:<secret_key>` (separadas por dois pontos)."}},"schemas":{"Health":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"env":{"type":"string","example":"production"},"time":{"type":"string","format":"date-time"}}},"Balance":{"type":"object","required":["balance_cents","currency"],"properties":{"balance_cents":{"type":"integer","description":"Disponível AGORA pra saque.","example":543210},"pending_balance_cents":{"type":"integer","description":"Aguardando liquidação ou revisão. Vira disponível automaticamente no prazo definido pela equipe Throne.","example":0},"reserved_cents":{"type":"integer","description":"Reservado em saques em andamento.","example":50000},"available_cents":{"type":"integer","description":"Alias de balance_cents (pra clareza)."},"currency":{"type":"string","enum":["BRL"]}}},"Customer":{"type":"object","description":"Dados do cliente final pagador. Cifrados em rest no Throne.","properties":{"name":{"type":"string","maxLength":255,"example":"João Cliente"},"document":{"type":"string","description":"CPF (11 dígitos) ou CNPJ (14)","example":"12345678901"},"email":{"type":"string","format":"email","example":"joao@example.com"},"phone":{"type":"string","description":"E.164 com +55","example":"+5511999999999"}}},"CreateTransactionRequest":{"type":"object","required":["amount_cents","payment_method"],"properties":{"amount_cents":{"type":"integer","minimum":1,"maximum":5000000,"description":"Valor em centavos."},"payment_method":{"type":"string","enum":["pix"]},"idempotency_key":{"type":"string","minLength":8,"maxLength":128,"description":"Pode vir no body OU no header Idempotency-Key."},"expires_at":{"type":"string","format":"date-time","description":"Quando o QR expira. Default: +1h."},"customer":{"$ref":"#/components/schemas/Customer"},"metadata":{"type":"object","additionalProperties":true,"description":"Qualquer JSON livre (até 4KB) que volta nos webhooks."}}},"PaymentData":{"type":"object","description":"Dados pra exibir QR Code no checkout.","properties":{"qr_code_payload":{"type":"string","description":"BR Code copia-e-cola."},"qr_code_image_base64":{"type":"string","nullable":true,"description":"PNG do QR em base64 (sem prefixo data:)."},"expires_at":{"type":"string","format":"date-time"}}},"Transaction":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","paid","failed","refunded","chargeback","expired"]},"payment_method":{"type":"string","enum":["pix"]},"amount_cents":{"type":"integer"},"fee_cents":{"type":"integer"},"net_amount_cents":{"type":"integer"},"paid_at":{"type":"string","format":"date-time","nullable":true},"expires_at":{"type":"string","format":"date-time","nullable":true},"payment_data":{"$ref":"#/components/schemas/PaymentData"},"metadata":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"}}},"PixDestination":{"type":"object","required":["key","key_type"],"properties":{"key":{"type":"string","description":"Chave PIX do destinatário."},"key_type":{"type":"string","enum":["cpf","cnpj","email","phone","evp"]}}},"CryptoDestination":{"type":"object","required":["address","network"],"properties":{"address":{"type":"string"},"network":{"type":"string","enum":["BTC","ETH","USDT_TRC20","USDT_ERC20"]}}},"CreateWithdrawalRequest":{"type":"object","required":["amount_cents","totp_code","destination"],"properties":{"amount_cents":{"type":"integer","minimum":1000,"description":"Mínimo R$ 10,00."},"totp_code":{"type":"string","description":"6 dígitos do app autenticador do seller."},"idempotency_key":{"type":"string","minLength":8,"maxLength":128},"destination":{"oneOf":[{"$ref":"#/components/schemas/PixDestination"},{"$ref":"#/components/schemas/CryptoDestination"}]}}},"Withdrawal":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["pix","crypto"]},"status":{"type":"string","enum":["requested","approved","processing","completed","failed","reversed"]},"amount_cents":{"type":"integer"},"fee_cents":{"type":"integer"},"net_amount_cents":{"type":"integer"},"requested_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time","nullable":true},"failure_reason":{"type":"string","nullable":true}}},"TransactionList":{"type":"object","required":["data","has_more"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Transaction"}},"has_more":{"type":"boolean","description":"Tem mais páginas após esta."},"next_cursor":{"type":"string","nullable":true,"description":"Cursor para a próxima página (opaco)."}}},"WithdrawalList":{"type":"object","required":["data","has_more"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Withdrawal"}},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","nullable":true}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Código machine-readable.","example":"insufficient_balance"},"message":{"type":"string","description":"Mensagem humana em pt-BR.","example":"Saldo insuficiente: disponível 30000 centavos, solicitado 50200 centavos."},"detail":{"type":"string","description":"Detalhe adicional.","nullable":true}}},"ValidationErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"example":{"amount_cents":["The amount cents must be at least 1."]}}}},"WebhookTransactionPaid":{"type":"object","properties":{"type":{"type":"string","enum":["transaction.paid"]},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"transaction_id":{"type":"string","format":"uuid"},"amount_cents":{"type":"integer"},"fee_cents":{"type":"integer"},"net_amount_cents":{"type":"integer"},"paid_at":{"type":"string","format":"date-time"}}}}},"WebhookWithdrawalCompleted":{"type":"object","properties":{"type":{"type":"string","enum":["withdrawal.completed"]},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"withdrawal_id":{"type":"string","format":"uuid"},"amount_cents":{"type":"integer"},"completed_at":{"type":"string","format":"date-time"}}}}},"WebhookWithdrawalFailed":{"type":"object","properties":{"type":{"type":"string","enum":["withdrawal.failed"]},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"withdrawal_id":{"type":"string","format":"uuid"},"amount_cents":{"type":"integer"},"reason":{"type":"string"}}}}},"WebhookTransactionRefunded":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["transaction.refunded"]},"version":{"type":"string","example":"2026-05-01"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"transaction_id":{"type":"string","format":"uuid"},"amount_refunded_cents":{"type":"integer"},"reason":{"type":"string"},"refunded_at":{"type":"string","format":"date-time"}}}}},"WebhookTransactionHeld":{"description":"Transaction colocada em hold (cautelar) pelo time de risk. UNICA no mercado · seller só vê quando liberado.","type":"object","properties":{"event_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["transaction.held"]},"version":{"type":"string","example":"2026-05-01"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"transaction_id":{"type":"string","format":"uuid"},"held_until":{"type":"string","format":"date-time","nullable":true,"description":"NULL = hold indefinido até decisão manual."},"reason":{"type":"string"}}}}},"WebhookChargebackCreated":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["chargeback.created"]},"version":{"type":"string","example":"2026-05-01"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"chargeback_id":{"type":"string","format":"uuid"},"transaction_id":{"type":"string","format":"uuid"},"amount_cents":{"type":"integer"},"reason_code":{"type":"string","example":"fraudulent"},"dispute_deadline":{"type":"string","format":"date-time"}}}}},"WebhookSellerApproved":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["seller.approved"]},"version":{"type":"string","example":"2026-05-01"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"seller_id":{"type":"integer"},"approved_at":{"type":"string","format":"date-time"},"mdr_pix":{"type":"number","description":"Taxa MDR PIX em decimal (ex: 0.05 = 5%)"}}}}}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"UUID v4 ou string única (8-128 chars). Replay = mesma resposta cacheada por 24h.","schema":{"type":"string","minLength":8,"maxLength":128},"example":"a3b6e3f8-2f1d-4f6b-9e7c-9b4f5d1c3a2e"},"PublicId":{"name":"id","in":"path","required":true,"description":"UUID v4 público da Transaction ou Withdrawal.","schema":{"type":"string","format":"uuid"}}},"responses":{"Unauthorized":{"description":"Credenciais inválidas / faltando","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"unauthorized","detail":"invalid_credentials"}}}},"Forbidden":{"description":"Operação proibida (ex: seller suspenso)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"seller_not_approved","message":"Seller com status 'suspended' não pode operar."}}}},"NotFound":{"description":"Recurso não encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"not_found","message":"Transação não encontrada."}}}},"BadRequest":{"description":"Request mal formada / Idempotency-Key faltando","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"idempotency_key_required","message":"Header Idempotency-Key é obrigatório (8-128 caracteres)."}}}},"ValidationError":{"description":"Validação de campos falhou","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"RateLimited":{"description":"Rate limit atingido","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Segundos até poder tentar de novo."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"rate_limited","message":"Tente novamente em 60 segundos."}}}},"AcquirerError":{"description":"Adquirente externa retornou erro","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"acquirer_error","message":"..."}}}}}},"externalDocs":{"description":"Site público","url":"https://throne.com.br/developers"}}