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.txt como 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 \n final, caminho com /v1 e query exatamente como enviada, sha256 do corpo cru, HMAC-SHA256 com 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() nem math/rand.
  • R04 MUST mandar Dracma-Timestamp em 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.json byte 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-Key em todo POST (inclusive cancel e /sandbox/*).
  • R09 MUST usar Idempotency-Key = external_id em POST /deposits e POST /withdrawals, e gravar os dois no seu banco antes da chamada (outbox).
  • R10 NEVER gerar Idempotency-Key nova para repetir um POST de 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, respeitando Retry-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, com external_id novo.
  • R13 MUST tratar code desconhecido pela classe HTTP e pelo retryable (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 v1 com qualquer segredo ativo (lista de 1 ou 2), em tempo constante; janela de 300 s; Dracma-Timestamp igual a t= (13 passos).
  • R15 MUST responder 400 se Dracma-Event-Id for diferente do id do corpo e deduplicar por Dracma-Event-Id (guarde por no mínimo 7 dias): duplicata recebe 200 sem efeito.
  • R16 MUST fazer fetch-back (GET /deposits/{id} ou GET /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.currency e player_ref idênticos ao que você registrou. Divergência: não move dinheiro, abre revisão e alerta.
  • R18 MUST ignorar estado com version menor ou igual à última aplicada para o objeto (responda 200).
  • R19 MUST responder ao webhook em até 10 s; 503 quando o fetch-back falhar por rede ou 5xx (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 com GET /events).

Dinheiro

  • R21 MUST creditar depósito só em paid, uma vez (idempotente por external_id), pelo valor que você registrou na criação.
  • R22 NEVER mover dinheiro em estado, tipo de evento, method, kind ou motivo desconhecido: trate como não terminal, responda 200 e 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, failed ou cancelled (lidos por fetch-back) ou em 4xx conclusivo na criação. NEVER em timeout, 5xx ou 429.
  • R25 NEVER debitar nem recreditar automaticamente em refunded, chargeback, returned ou pagamento depois de expired: abra needs_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_ref opaco 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.name e player.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, .invalid ou .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 0400 do 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-Id em todo log de chamada. NEVER logar Dracma-Signature inteiro, 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=&currency=&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.

Veja também