Referência rápida¶
Para: Dev — Conferido em 2026-10-18.
Uma página com as regras obrigatórias do integrador, os endpoints, os erros, os estados e os eventos. É o formato que uma pessoa consulta com o conector aberto e que um agente de código usa como requisito de aceite. Cada linha aponta para a página que explica o assunto por inteiro. Onde o código de hoje difere do contrato, veja Divergências conhecidas.
O que é¶
Cinco blocos, nesta ordem: regras, endpoints, erros, estados e eventos. As palavras MUST e NEVER têm o sentido da RFC 2119. Cada regra tem um id estável (R01 a R36) que você pode citar em testes e em revisões.
Quando usar¶
- Ao revisar o conector antes do go-live: percorra as regras e prove cada uma (Checklist de go-live).
- Ao decidir o que fazer com uma resposta ou um estado: use as tabelas 3 e 4.
- Ao instruir um agente de código: entregue esta página e o
llms.txtcomo requisitos.
Como funciona¶
1. Regras do integrador (MUST / NEVER)¶
Chamadas ao Dracma¶
- R01 MUST chamar o Dracma só do servidor do conector. NEVER do navegador, do app do jogador ou de código com segredo em bundle (
NEXT_PUBLIC_*,VITE_*). - R02 MUST assinar toda requisição: pedido canônico de 6 linhas sem
\nfinal, caminho com/v1e query exatamente como enviada, sha256 do corpo cru,HMAC-SHA256com o segredo da chave (Pedido canônico e assinatura). - R03 MUST gerar nonce de 32 hex minúsculos por CSPRNG, novo em toda requisição, inclusive em repetição. NEVER
Math.random()nemmath/rand. - R04 MUST mandar
Dracma-Timestampem segundos e manter o relógio por NTP (desvio acima de 5 s é alerta; a janela é de ±300 s). - R05 MUST serializar o corpo uma vez e enviar exatamente os bytes assinados.
- R06 MUST reproduzir os vetores de
vetores-assinatura.jsonbyte a byte no CI, inclusive recusar o negativo. - R07 MUST usar timeout de cliente de 10 s (Timeouts).
Idempotência e repetição¶
- R08 MUST mandar
Idempotency-Keyem todoPOST(inclusivecancele/sandbox/*). - R09 MUST usar
Idempotency-Key = external_idemPOST /depositsePOST /withdrawals, e gravar os dois no seu banco antes da chamada (outbox). - R10 NEVER gerar
Idempotency-Keynova para repetir umPOSTde dinheiro. Repetição = mesma chave, mesmos bytes, timestamp, nonce e assinatura novos. - R11 MUST repetir
5xx,429,409 idempotency_in_progress, timeout e erro de rede com a mesma chave, respeitandoRetry-After(backoff exponencial com jitter). Veja a árvore de decisão. - R12 NEVER repetir um
4xx(é decisão do Dracma). Tentar de novo depois de uma recusa é uma operação nova, comexternal_idnovo. - R13 MUST tratar
codedesconhecido pela classe HTTP e peloretryable(4xx não repete; 5xx e 429 repetem).
Webhooks e fetch-back¶
- R14 MUST verificar a assinatura do webhook sobre o corpo cru, antes de interpretar o JSON, aceitando qualquer
v1com qualquer segredo ativo (lista de 1 ou 2), em tempo constante; janela de 300 s;Dracma-Timestampigual at=(13 passos). - R15 MUST responder
400seDracma-Event-Idfor diferente doiddo corpo e deduplicar porDracma-Event-Id(guarde por no mínimo 7 dias): duplicata recebe200sem efeito. - R16 MUST fazer fetch-back (
GET /deposits/{id}ouGET /withdrawals/{id}com a própria credencial) antes de mover dinheiro. NEVER creditar, debitar ou devolver reserva pelo corpo do webhook. - R17 MUST conferir no fetch-back:
external_idé seu;amount.amount,amount.currencyeplayer_refidênticos ao que você registrou. Divergência: não move dinheiro, abre revisão e alerta. - R18 MUST ignorar estado com
versionmenor ou igual à última aplicada para o objeto (responda200). - R19 MUST responder ao webhook em até 10 s;
503quando o fetch-back falhar por rede ou5xx(o Dracma reentrega). - R20 MUST rodar um job de
GET /events?after=<último evento aplicado>a cada 5 minutos, com cursor persistido, passando cada evento pelo mesmo caminho do webhook (Recuperação comGET /events).
Dinheiro¶
- R21 MUST creditar depósito só em
paid, uma vez (idempotente porexternal_id), pelo valor que você registrou na criação. - R22 NEVER mover dinheiro em estado, tipo de evento,
method,kindou motivo desconhecido: trate como não terminal, responda200e confira depois. - R23 MUST reservar (debitar) o saldo do jogador antes de
POST /withdrawals, na mesma transação que grava o saque local. - R24 MUST devolver a reserva só em
rejected,failedoucancelled(lidos por fetch-back) ou em4xxconclusivo na criação. NEVER em timeout,5xxou429. - R25 NEVER debitar nem recreditar automaticamente em
refunded,chargeback,returnedou pagamento depois deexpired: abraneeds_decision, dispare alerta e deixe uma pessoa decidir (Política de exceções). - R26 MUST representar dinheiro como string de inteiro na menor unidade (
"5000"= R$ 50,00). NEVER float (Money).
Dados do jogador¶
- R27 MUST usar
player.external_refopaco e imutável. NEVER e-mail, telefone ou documento como id. - R28 MUST mandar
player.ip(IP do jogador, não o do seu servidor) em todo saque; sem ele o saque nunca é automático. - R29 MUST ler as exigências da operação em
GET /currencies(method_details[].deposit_requirements) e mandar os campos exigidos (por exemplo,player.nameeplayer.email), vindos do cadastro do jogador. NEVER inventados (Exigências por operação). - R30 NEVER usar, fora de produção, e-mail ou documento de pessoa real (inclusive o seu). E-mail de teste só em
.test,.invalidou.example; CPF de teste com dígito verificador válido (Dados de teste). - R31 NEVER mostrar ao jogador o motivo de bloqueio ou de revisão (listas,
PAYER_MISMATCH...).
Segredos, rede e operação¶
- R32 MUST guardar segredo de chamada e segredo de webhook em cofre ou arquivo
0400do usuário do serviço. NEVER em repositório, imagem, log, ticket ou variável de front (Segredos e vazamento). - R33 MUST manter a lista de IPs da operação com todos os IPs de saída do conector, mesmo que hoje ela esteja registrada e não aplicada, e apresentar o certificado de cliente se a sua instância ligar o mTLS (Rede, allowlist e mTLS).
- R34 MUST registrar
Dracma-Trace-Idem todo log de chamada. NEVER logarDracma-Signatureinteiro, segredo, documento completo ou chave PIX em claro. - R35 MUST reconciliar diariamente (
GET /reconciliation, depois das 02:00 UTC), conferir o digest e a assinatura e tratar divergência como incidente. NEVER "consertar" o livro para bater (Reconciliar com o seu livro). - R36 MUST apontar homologação para uma operação Teste (
key_test_) e produção para uma operação Real (key_live_); uma operação Real move dinheiro real em qualquer instância.
2. Endpoints¶
Base: https://<host>/v1 (hosts em Ambientes, tipos de operação e hosts). Todos exigem a assinatura da regra R02; todo POST exige Idempotency-Key. A lista completa de 31 rotas, com o operationId de cada uma, está no Índice de endpoints.
| Método e caminho | Escopo | Sucesso | Erros típicos | Página |
|---|---|---|---|---|
GET /ping |
qualquer chave | 200 {ok, operation_id, environment, server_time} |
401, 403 | Ping |
GET /currencies |
read |
200 {data: [Moeda + method_details]} |
503 | Moedas |
POST /deposits |
deposits:write |
201 (pending ou failed) ou 202 (created) |
400, 409, 422, 429, 503 | Criar |
GET /deposits |
read (listagem 5/s) |
200 {data, next_cursor} |
400 | Listar |
GET /deposits/{id} |
read |
200 Deposito |
404 | Consultar |
POST /deposits/{id}/cancel |
deposits:write |
200 Deposito (cancelled) |
404, 409 | Cancelar |
POST /withdrawals |
withdrawals:write |
201 Saque (approved, under_review ou requested) |
400, 409, 422, 503 | Criar |
GET /withdrawals |
read (listagem 5/s) |
200 {data, next_cursor} |
400 | Listar |
GET /withdrawals/{id} |
read |
200 Saque |
404 | Consultar |
POST /withdrawals/{id}/cancel |
withdrawals:write |
200 Saque (cancelled) |
404, 409 | Cancelar |
GET /players/{external_ref}/limits?currency= |
read |
200 LimitesJogador |
400, 404, 503 | Limites |
GET /balances |
read |
200 {data: [{available, pending_in, pending_out, as_of}]} |
503 | Saldos |
GET /events?after=&object_id=&limit= |
read (listagem 5/s) |
200 {data: [Evento], next_cursor} |
400 | GET /events |
GET /reconciliation?date=¤cy=&cursor=&limit= |
read |
200 (a última página traz totals, digest e o cabeçalho Dracma-Signature) |
400, 409 day_open, 503 |
Reconciliação |
GET /rules |
read |
200 conjunto vigente com ETag |
404, 503 | Ler |
POST /rules/change-requests |
rules:propose |
202 {id, status: pending_approval} |
412 etag_mismatch |
Propor |
POST /fx/quotes |
deposits:write ou withdrawals:write |
nenhum | 422 fx_not_enabled sempre |
Reservadas |
GET /fx/quotes/{id} |
read |
nenhum | 404 sempre |
Reservadas |
GET /receipts |
read (listagem 5/s) |
200 {data: [], next_cursor: null} |
400 | Reservadas |
GET /receipts/{id} |
read |
nenhum | 404 sempre |
Reservadas |
POST /withdrawals/{id}/recall |
withdrawals:write |
nenhum | 400, 404, 409 invalid_state_transition |
Reservadas |
POST /sandbox/deposits/{id}/pay |
deposits:write |
200 Deposito |
400, 404, 409, 503 | Sandbox |
POST /sandbox/deposits/{id}/{expire,refund,chargeback} |
deposits:write |
200 Deposito |
404, 409 | Sandbox |
POST /sandbox/withdrawals/{id}/{approve,reject,pay,fail,return} |
withdrawals:write |
200 Saque (estado atual) |
400, 404, 409, 503 | Ações no saque |
POST /sandbox/bank-transfers/incoming |
deposits:write |
nenhum | 400 rail_not_enabled |
Reservadas |
POST /sandbox/outage |
deposits:write ou withdrawals:write |
200 {down} |
400 | Queda simulada |
GET /sandbox/webhooks |
read |
200 log de entregas |
503 | Log de entregas |
POST /sandbox/webhooks/redeliver |
deposits:write ou withdrawals:write |
200 {event_id, scheduled} |
400, 404, 503 | Reentrega |
GET /openapi.yaml (fora de /v1) |
nenhum | 200, com ETag |
nenhum | OpenAPI |
Em operação Real, todo /v1/sandbox/* responde 404. As rotas de câmbio, recebimentos e recall existem só para manter o contrato 1.1.0 inteiro: nenhuma move dinheiro nem cria objeto.
3. Erros e o que fazer¶
O catálogo completo (30 code), os 22 motivos de validação e as respostas da borda estão em Erros.
| HTTP | code |
Repetir? | Ação |
|---|---|---|---|
| 400 | validation_failed |
não | corrija o pedido (errors[].field e reason) |
| 400 | currency_not_enabled, method_not_enabled, rail_not_enabled |
não | configuração da operação; confira GET /currencies |
| 401 | invalid_signature, timestamp_out_of_window, replayed_nonce, unknown_key |
não | assinatura, relógio, nonce, chave e host (Problemas de integração) |
| 403 | ip_not_allowed, insufficient_scope, operation_suspended |
não | escopo da chave, suporte (FAQ) |
| 404 | not_found |
não | id ou operação errados (objeto de outra operação também é 404) |
| 409 | idempotency_key_reused |
não | bug: chave reusada com outro corpo |
| 409 | duplicate_external_id |
não | use o objeto em existing |
| 409 | invalid_state_transition |
não | consulte o estado atual |
| 409 | idempotency_in_progress |
sim | mesma chave depois do Retry-After |
| 409 | day_open |
sim, depois | agende para depois do Retry-After, sem laço |
| 412 | etag_mismatch |
não | releia GET /rules e proponha de novo |
| 413 | validation_failed (too_large) |
não | corpo de até 64 KiB |
| 422 | amount_below_minimum, amount_above_maximum, document_invalid, document_mismatch, player_blocked, destination_blocked, velocity_exceeded, insufficient_operation_balance, fx_not_enabled |
não | recusa de negócio, sem objeto; num saque, devolva a reserva |
| 429 | rate_limited |
sim | mesma chave depois do Retry-After (Limites) |
| 500 | internal_error |
sim | mesma chave; abra chamado com o trace_id se persistir |
| 503 | service_unavailable |
sim | mesma chave depois do Retry-After (Modo degradado) |
4. Estados e efeito no livro do integrador¶
A tradução completa para os estados do seu produto, com mensagens, está em Estados no seu produto.
Depósito¶
| Estado | Terminal? | Efeito |
|---|---|---|
created |
não | nenhum |
pending |
não | nenhum (mostre o PIX) |
under_review |
não | nenhum |
paid |
sim, para o crédito | credita uma vez |
expired, cancelled, failed, returned |
sim | nenhum (mesmo com paid_amount preenchido) |
refunded, chargeback |
sim | débito por política sua: needs_decision (só no sandbox hoje) |
pending_compliance, frozen, paid_partial |
não alcançáveis em PIX | nenhum automático |
| desconhecido | tratar como não terminal | nenhum |
Saque (a reserva é feita antes do POST)¶
| Estado | Terminal? | Efeito na reserva |
|---|---|---|
requested, under_review, approved, processing |
não | mantém |
paid |
sim (pode ir a returned) |
finaliza |
rejected, failed, cancelled |
sim | devolve |
returned |
sim | nenhum automático: needs_decision |
pending_compliance, sent, in_transit, recall_requested, recalled |
não alcançáveis em PIX | mantém |
| desconhecido | tratar como não terminal | mantém |
5. Eventos de webhook¶
São 17 tipos emitidos hoje (Catálogo de eventos).
| Objeto | Eventos |
|---|---|
| Depósito (9) | deposit.pending, deposit.under_review, deposit.paid, deposit.expired, deposit.cancelled, deposit.failed, deposit.returned, deposit.refunded, deposit.chargeback |
| Saque (8) | withdrawal.under_review, withdrawal.approved, withdrawal.processing, withdrawal.paid, withdrawal.rejected, withdrawal.failed, withdrawal.cancelled, withdrawal.returned |
deposit.refunded e deposit.chargeback só ocorrem no sandbox hoje.
Reservado no contrato
Os tipos deposit.pending_compliance, deposit.frozen, deposit.paid_partial, withdrawal.pending_compliance, withdrawal.sent, withdrawal.in_transit, withdrawal.recall_requested, withdrawal.recall_rejected, withdrawal.recalled e receipt.* pertencem ao contrato 1.1.0, mas nenhum tem gatilho hoje. Trate qualquer type desconhecido pela regra R22.
Não disponível
rules.updated aparece em listas antigas, mas o Dracma nunca o emite e ele não pode ser assinado. Para saber se as regras mudaram, consulte GET /v1/rules.
Exemplos¶
Um depósito do começo ao fim, em uma linha por passo: grave external_id e a intenção (R09); POST /deposits assinado com Idempotency-Key igual ao external_id (R02, R08); receba deposit.paid, verifique a assinatura e deduplique (R14, R15); faça o fetch-back e confira valor, moeda e jogador (R16, R17); credite uma vez, na mesma transação que grava a version (R18, R21). O código completo está em Receptor passo a passo e em Exemplos executáveis.
Erros e casos de borda¶
- Uma regra que parece conflitar com o seu produto não se negocia pelo código: abra a página da regra, entenda o motivo e, se necessário, fale com o suporte (Suporte).
- Esta página resume. Em divergência com uma página de detalhe, vale a página de detalhe, e a divergência é um erro desta página.