Depósitos¶
Para: Dev — Conferido em 2026-10-18.
Um depósito é uma intenção de cobrança PIX: você o cria, o Dracma devolve o copia-e-cola, o jogador paga e o Dracma
avisa por webhook. Esta página descreve as quatro rotas (criar, consultar, listar e cancelar), a validação do corpo,
os erros na ordem em que a API os confere e os campos que o objeto Deposito realmente devolve.
O que é¶
| Rota | Escopo | operationId |
Resposta de sucesso |
|---|---|---|---|
POST /v1/deposits |
deposits:write |
criarDeposito |
201 com o PIX pronto, ou 202 com o depósito ainda em created |
GET /v1/deposits |
read |
listarDepositos |
200 com {data, next_cursor} |
GET /v1/deposits/{id} |
read |
obterDeposito |
200 com o Deposito |
POST /v1/deposits/{id}/cancel |
deposits:write |
cancelarDeposito |
200 com o Deposito em cancelled |
Hoje só existe PIX em BRL. Qualquer outro método do enum Metodo responde 400 method_not_enabled.
method |
Situação |
|---|---|
pix |
disponível |
card, crypto, boleto, bank_transfer, wire, swift |
não disponível: 400 method_not_enabled |
qualquer outro valor (por exemplo "ted") |
400 validation_failed com errors[0] = {field: "method", reason: "enum"} |
Não disponível
O Dracma não oferece hoje cartão, cripto, boleto, transferência bancária, wire nem SWIFT para depósito. A
tentativa responde 400 method_not_enabled e não cria nada. O único método é pix, na moeda BRL.
O Dracma credita o valor cheio no depósito pago. O objeto Deposito não traz tarifa descontada: o campo fee do
contrato não é devolvido (veja a seção "Objeto Deposito" mais abaixo). As tarifas do contrato com o Dracma estão em
Tarifas.
Quando usar¶
O fluxo recomendado, de ponta a ponta:
- Grave o depósito no seu lado antes de chamar o Dracma.
- Chame
POST /v1/depositscomIdempotency-Keyigual aoexternal_id. Use timeout de cliente de 10 s. - Em erro de rede,
5xxou429, repita com a mesma chave. Se perdeu a resposta, consulteGET /v1/deposits?external_id=. - Mostre
instructions.pix.copy_pasteao jogador atéinstructions.pix.expires_at. - Ao receber
deposit.paid, verifique a assinatura, deduplique e faça o fetch-back comGET /v1/deposits/{id}. Só credite quando ostatuslido forpaid.
Nunca credite pelo corpo do webhook. O efeito de cada estado no seu livro está em Ciclo do depósito.
Como funciona¶
Criar: POST /v1/deposits¶
O corpo é um objeto JSON com estas chaves. Qualquer chave fora da lista é recusada.
| Campo | Obrigatório | Regra |
|---|---|---|
external_id |
sim | seu id do depósito, ^[A-Za-z0-9_.:-]{1,64}$, único por operação |
player.external_ref |
sim | seu id do jogador, mesmo formato, opaco e imutável (nunca e-mail, telefone ou CPF) |
player.document |
sim | type em CPF, CNPJ, PASSPORT, NATIONAL_ID, TAX_ID; CPF/CNPJ só dígitos (11 a 14); country ISO 3166 alfa-2 em maiúsculas |
player.name |
depende da operação | até 120 caracteres |
player.email |
depende da operação | validado sempre que vier. Veja "Exigências por operação" |
player.ip, player.device_id |
depende da operação | informativos, entram na análise de risco. Veja "Exigências por operação" |
player.birth_date, player.kyc_level |
não | informativos |
amount |
sim | Money com amount maior que zero |
method |
sim | pix |
expires_in_seconds |
não | de 300 a 86400. Padrão 1800 |
locale |
não | por exemplo pt-BR |
metadata |
não | até 20 chaves, valores texto |
Para PIX o documento do jogador só pode ser CPF ou CNPJ. Os outros tipos passam na validação de forma, mas voltam
422 document_invalid.
O documento do jogador fica fixado no primeiro uso do external_ref. Mandar outro documento para o mesmo
external_ref depois resulta em 422 document_mismatch. Veja Dados e privacidade.
Validação estrita. O corpo é recusado com 400 validation_failed, antes de qualquer efeito, quando tem:
| Problema | errors[].reason |
|---|---|
campo desconhecido, inclusive status, version, paid_amount ou operation_id aninhado |
unknown_field |
| chave JSON repetida em qualquer nível | duplicate_key |
| UTF-8 inválido | invalid_utf8 |
| JSON inválido | syntax |
| conteúdo depois do objeto | trailing_data |
| tipo errado | type |
external_id, external_ref, número de documento ou país em formato inválido |
format |
| tipo de documento fora da lista | enum |
expires_in_seconds fora da faixa, ou metadata com mais de 20 chaves |
range |
amount ausente ou zero, method ausente |
required |
operation_id na raiz do corpo é descartado em silêncio: o tenant e a operação vêm só da credencial. Não o envie.
method_options e fx_quote_id existem só no contrato 1.1.0 (o documento OpenAPI servido não os traz) e não são aceitos em depósito PIX: voltam unknown_field
(veja Divergências conhecidas). Corpo acima de 64 KiB volta 413.
Exigências por operação¶
Alguns PSPs exigem dados que o contrato deixa opcionais. O Dracma escolhe o PSP de depósito de cada operação no
onboarding e declara as exigências em GET /v1/currencies (method_details[].deposit_requirements). Veja
Ping e moedas.
Quando a operação exige um campo e ele vem ausente, em branco ou só com espaços, a API recusa antes de criar qualquer coisa e antes do motor de regras:
errors[].field |
errors[].reason |
Quando |
|---|---|---|
o campo exigido, por exemplo player.email |
required_by_operation |
a operação exige e o campo não veio |
player.email |
format |
fora de local@dominio.tld, ou com nome de exibição. Vale sempre que o e-mail vier |
player.email |
max_length |
mais de 254 caracteres |
player.email |
reserved_domain_required |
operação Teste: o e-mail só pode ter TLD reservado (.test, .invalid, .example) |
player.name |
max_length |
mais de 120 caracteres. Vale sempre |
- É um
4xx: não cria objeto, jogador nem evento. A mesmaIdempotency-Keydevolve o mesmo400por 30 dias. Depois de corrigir o cadastro, crie comexternal_idnovo. - Mande o e-mail cadastrado do jogador, lido do seu servidor. Nunca um e-mail digitado no pedido de depósito e nunca um inventado.
- Em operação Teste, e-mail real de um cadastro copiado de produção recebe
reserved_domain_required. Reescreva os e-mails do seu ambiente de teste (por exemplojogador1@operador.test). Se a operação não exige e-mail, não envie o campo. - Mande sempre
player.name: operações reais costumam exigi-lo. - Em operação Real o domínio do e-mail não é restrito, só o formato.
Resposta 201: PIX pronto¶
O depósito é criado e o PSP já devolveu o PIX. status vem pending, version vem 2 e instructions.pix traz
copy_paste (o BR Code, que é o conteúdo do QR) e expires_at. qr_code_png_base64 vem quando o PSP o fornece;
se não vier, gere o QR a partir do copy_paste.
- Use o
instructions.pix.expires_atdevolvido, não o prazo que você pediu: o PSP pode ajustar o prazo. - Em operação Teste o BR Code é sintético e nenhum dinheiro real se move.
201comstatus: "failed"também existe: o PSP recusou a cobrança antes da resposta. O objeto foi criado e é conclusivo (vejafailure_code). Não repita; crie outro depósito comexternal_idnovo se fizer sentido.
Dinheiro real
Em uma operação Real, o PIX devolvido é um PIX de verdade: o pagamento move dinheiro real. Faça seus testes de ponta a ponta numa operação Teste.
Resposta 202: aceito, PIX ainda não disponível¶
Se o PSP demorar mais que o orçamento de resposta da API (cerca de 7 s), o Dracma responde 202 com status: "created",
version: 1 e instructions: null. Não é erro. Espere o webhook deposit.pending ou consulte GET /v1/deposits/{id}
até o status ser pending, e então mostre o PIX. Não crie outro depósito para tentar de novo.
Consultar: GET /v1/deposits/{id}¶
É o fetch-back: o estado autoritativo que você lê antes de creditar. 200 devolve o Deposito. Um id que não existe
nesta operação responde 404 not_found. Objeto de outra operação também é 404, nunca 403, e um id fora do
formato dep_ seguido de letras e números também.
Antes de creditar, confira o que veio contra o que você gravou na criação: external_id, amount.amount,
amount.currency e player_ref têm de ser idênticos. Se algo divergir, não credite, marque para revisão e alerte.
Listar: GET /v1/deposits¶
Escopo read. Usa o balde de listagem do rate limit (veja Limites e quotas).
| Parâmetro | Uso |
|---|---|
external_id |
acha o depósito pelo seu id. É o jeito de saber o destino de um POST cuja resposta se perdeu |
player_ref |
depósitos de um jogador |
status |
filtra por estado. Valor fora do enum de StatusDeposito responde 400 com reason: format |
updated_since |
RFC 3339. Devolve itens com updated_at maior ou igual ao instante dado |
cursor |
o next_cursor da página anterior. Cursor inválido responde 400 com reason: format |
limit |
de 1 a 200. Padrão 50. Valor fora da faixa responde 400 com reason: format |
A resposta é {"data": [Deposito, ...], "next_cursor": "dep_..." | null}. A ordem é a do id do depósito, que
segue a ordem de criação, e não a de updated_at. next_cursor é o id dep_... do último item da página e vira null
na última. Para uma varredura incremental, guarde o maior updated_at visto e use updated_since com ele
(o >= repete o último item, então deduplique). Veja Paginação e filtros.
Assine o caminho com a query exatamente como enviada.
Cancelar: POST /v1/deposits/{id}/cancel¶
Escopo deposits:write. Corpo vazio. Idempotency-Key obrigatória.
- Só cancela de
pending. A resposta é200com o objeto emcancelled. Se ele já estavacancelled, a resposta é o mesmo200, sem evento novo. - Em
created,paid,expired,under_reviewou qualquer outro estado, a resposta é409 invalid_state_transition. Emcreated, esperependinge cancele depois. - Cancelar no Dracma não cancela a cobrança no PSP. O PIX continua pagável até o prazo do PSP. Se alguém pagar depois,
o estado não muda e o
paid_amounté gravado: não credite e trate como exceção. Veja Política de exceções de dinheiro e a divergência D-D2 em Divergências conhecidas.
Expiração¶
O Dracma expira sozinho o depósito pending depois de expires_at mais 2 minutos de folga (o job roda a cada 30 s). A folga
existe porque o PSP ainda pode aceitar o pagamento logo depois do prazo. Ao expirar sai o webhook deposit.expired.
Objeto Deposito¶
O Deposito é o mesmo no 201, no GET e no data.object do webhook. A API devolve 16 campos e nenhum outro. Os campos
da v1.1.0 do contrato (rail, received_amount, receipts, fee, fees, fx, compliance, expected_settlement_date, return) existem no
contrato 1.1.0, mas não no documento OpenAPI servido, e nunca são devolvidos em depósito. Não dependa deles.
| Campo | Tipo | Devolvido hoje? | Conteúdo |
|---|---|---|---|
id |
texto | sim | id do Dracma, dep_ seguido de 32 caracteres hexadecimais. Trate como opaco |
external_id |
texto | sim | o seu id |
status |
texto | sim | estado atual |
version |
inteiro | sim | começa em 1 (created) e sobe a cada transição. Ignore estado com version menor ou igual à já aplicada |
amount |
Money |
sim | valor cobrado |
paid_amount |
Money ou null |
sim | valor pago. Em paid é igual a amount. Pode vir preenchido em estado terminal sem crédito (pagamento tardio) |
method |
texto | sim | pix |
player_ref |
texto | sim | o seu player.external_ref |
payer |
objeto ou null |
sim | quem pagou. Preenchido em paid e under_review. Veja abaixo |
instructions |
objeto ou null |
sim | null em created. Depois, {"pix": {copy_paste, expires_at, qr_code_png_base64?}} |
failure_code |
texto ou null |
sim | motivo técnico em failed. Lista aberta |
review_reasons |
lista de texto | sim | motivos de under_review. Vazia ([]) fora de revisão |
created_at, updated_at |
texto | sim | RFC 3339 em UTC com segundos, sem fração, por exemplo 2026-10-18T15:04:05Z |
paid_at |
texto ou null |
sim | instante do pagamento |
expires_at |
texto ou null |
sim | fim do prazo do PIX |
rail, received_amount, receipts, fee, fees, fx, compliance, expected_settlement_date, return |
— | não | reservados da v1.1.0 (só no contrato; fora do OpenAPI servido) |
Reservado no contrato
fee, fees, fx, compliance, return e os demais campos da v1.1.0 estão no schema Deposito do OpenAPI, mas a API
não os preenche em depósito PIX. A tarifa não é descontada do valor creditado (veja Tarifas).
payer. Traz document (type, number, country), name e matches_player, que é true quando o documento de quem
pagou bate com o do jogador. Use-o só para exibir e auditar; a decisão de crédito é o status.
status. O enum StatusDeposito tem 13 valores:
status |
Como o depósito chega aqui | Alcançável em PIX hoje |
|---|---|---|
created |
aceito, PIX ainda não gerado | sim |
pending |
PIX gerado, aguardando pagamento | sim |
under_review |
dinheiro recebido com divergência (pagador diferente, valor diferente, pago após o prazo ou pagador não confirmado) | sim |
paid |
pago com valor exato e pagador conferido, ou aprovado na revisão | sim |
expired |
prazo vencido sem pagamento | sim |
cancelled |
cancelado por você | sim |
failed |
o PSP recusou a cobrança | sim |
returned |
devolvido na revisão: o depósito não foi aceito e nunca foi creditado | sim |
refunded, chargeback |
depois de paid |
só no sandbox, por ação simulada |
pending_compliance, frozen, paid_partial |
acréscimos da v1.1.0 | não: nenhum depósito chega a esses estados hoje |
Estado desconhecido é não-terminal e não move dinheiro no seu lado: confira de novo pelo fetch-back (leitor tolerante). A máquina de estados completa e o efeito de cada estado no seu livro estão em Ciclo do depósito.
review_reasons. Lista aberta de códigos em maiúsculas, por exemplo PAYER_MISMATCH, PAYER_UNKNOWN, AMOUNT_MISMATCH, PAID_AFTER_EXPIRY,
RULES_UNAVAILABLE e RULES_INVALID_RESPONSE. Código desconhecido não muda nada: o que manda é o status. O significado de cada um e o
que o painel faz com ele está em Ciclo do depósito.
Exemplos¶
Pedido de criação (os valores de assinatura são ilustrativos; o algoritmo está em Autenticação HMAC):
POST /v1/deposits HTTP/1.1
Host: api.example.test
Content-Type: application/json; charset=utf-8
Idempotency-Key: dep_0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6b
Dracma-Key-Id: key_test_01J9EXEMPLO
Dracma-Timestamp: 1790000000
Dracma-Nonce: 0123456789abcdef0123456789abcdef
Dracma-Signature: v1=<assinatura>
{
"external_id": "dep_0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6b",
"player": {
"external_ref": "0192a3b4-0000-7000-8000-000000000001",
"document": { "type": "CPF", "number": "12345678909", "country": "BR" },
"name": "Jogador Teste",
"email": "jogador1@operador.test",
"ip": "203.0.113.10"
},
"amount": { "amount": "5000", "currency": "BRL" },
"method": "pix",
"expires_in_seconds": 1800
}
Resposta 201, PIX pronto:
{
"id": "dep_0192a3b40c6d7e8f9a0b1c2d3e4f5a6b",
"external_id": "dep_0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6b",
"status": "pending",
"version": 2,
"amount": { "amount": "5000", "currency": "BRL" },
"paid_amount": null,
"method": "pix",
"player_ref": "0192a3b4-0000-7000-8000-000000000001",
"payer": null,
"instructions": {
"pix": {
"copy_paste": "00020126...6304ABCD",
"expires_at": "2026-10-18T15:30:00Z"
}
},
"failure_code": null,
"review_reasons": [],
"created_at": "2026-10-18T15:00:00Z",
"updated_at": "2026-10-18T15:00:01Z",
"paid_at": null,
"expires_at": "2026-10-18T15:30:00Z"
}
Resposta 202, PIX ainda não disponível:
{
"id": "dep_0192a3b40c6d7e8f9a0b1c2d3e4f5a6c",
"external_id": "dep_0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6c",
"status": "created",
"version": 1,
"amount": { "amount": "5000", "currency": "BRL" },
"paid_amount": null,
"method": "pix",
"player_ref": "0192a3b4-0000-7000-8000-000000000001",
"payer": null,
"instructions": null,
"failure_code": null,
"review_reasons": [],
"created_at": "2026-10-18T15:00:00Z",
"updated_at": "2026-10-18T15:00:00Z",
"paid_at": null,
"expires_at": "2026-10-18T15:30:00Z"
}
O mesmo depósito depois de pago, lido no fetch-back:
{
"id": "dep_0192a3b40c6d7e8f9a0b1c2d3e4f5a6b",
"external_id": "dep_0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6b",
"status": "paid",
"version": 3,
"amount": { "amount": "5000", "currency": "BRL" },
"paid_amount": { "amount": "5000", "currency": "BRL" },
"method": "pix",
"player_ref": "0192a3b4-0000-7000-8000-000000000001",
"payer": {
"document": { "type": "CPF", "number": "12345678909", "country": "BR" },
"name": "Jogador Teste",
"matches_player": true
},
"instructions": {
"pix": {
"copy_paste": "00020126...6304ABCD",
"expires_at": "2026-10-18T15:30:00Z"
}
},
"failure_code": null,
"review_reasons": [],
"created_at": "2026-10-18T15:00:00Z",
"updated_at": "2026-10-18T15:07:41Z",
"paid_at": "2026-10-18T15:07:40Z",
"expires_at": "2026-10-18T15:30:00Z"
}
Um depósito em revisão porque o pagador não é o jogador. Não credite:
{
"id": "dep_0192a3b40c6d7e8f9a0b1c2d3e4f5a6d",
"external_id": "dep_0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6d",
"status": "under_review",
"version": 3,
"amount": { "amount": "5000", "currency": "BRL" },
"paid_amount": { "amount": "5000", "currency": "BRL" },
"method": "pix",
"player_ref": "0192a3b4-0000-7000-8000-000000000002",
"payer": {
"document": { "type": "CPF", "number": "98765432100", "country": "BR" },
"name": "Outra Pessoa",
"matches_player": false
},
"instructions": {
"pix": {
"copy_paste": "00020126...6304ABCD",
"expires_at": "2026-10-18T15:30:00Z"
}
},
"failure_code": null,
"review_reasons": ["PAYER_MISMATCH"],
"created_at": "2026-10-18T15:00:00Z",
"updated_at": "2026-10-18T15:09:10Z",
"paid_at": "2026-10-18T15:09:09Z",
"expires_at": "2026-10-18T15:30:00Z"
}
Recusa por exigência da operação (400, sem objeto criado):
{
"type": "https://docs.dracma.test/errors/validation_failed",
"title": "validation_failed",
"status": 400,
"code": "validation_failed",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"retryable": false,
"errors": [
{
"field": "player.email",
"message": "obrigatório nesta operação (exigência do PSP de cash-in; ver GET /v1/currencies)",
"reason": "required_by_operation"
}
]
}
Listagem para achar um depósito pelo seu id:
GET /v1/deposits?external_id=dep_0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6b&limit=10 HTTP/1.1
Erros e casos de borda¶
Erros da criação, na ordem em que a API os confere¶
| # | HTTP | code |
Quando | O que fazer |
|---|---|---|---|---|
| 1 | 400 | validation_failed |
corpo inválido (veja a tabela de validação) | corrija o pedido; não repita igual |
| 2 | 429 | rate_limited |
mais de 10 depósitos criados por jogador por hora | mostre "tente mais tarde"; repita com a mesma chave depois do Retry-After |
| 3 | 400 | validation_failed (field: method, reason: enum) |
method fora do enum Metodo |
corrija |
| 4 | 400 | method_not_enabled |
method do enum, mas diferente de pix |
não ofereça o método |
| 5 | 422 | document_invalid |
tipo de documento diferente de CPF e CNPJ | revise o cadastro do jogador |
| 6 | 409 | duplicate_external_id |
o external_id já existe (com outra Idempotency-Key); o objeto vem em existing |
use o existing; não crie outro |
| 7 | 400 | currency_not_enabled ou method_not_enabled |
moeda ou método não habilitado nesta operação | configuração do onboarding |
| 8 | 400 | validation_failed (required_by_operation, format, max_length, reserved_domain_required) |
exigência da operação | corrija o cadastro; external_id novo |
| 9 | 422 | amount_below_minimum, amount_above_maximum, document_invalid, document_mismatch, player_blocked, destination_blocked, velocity_exceeded |
recusa do motor de regras, sem objeto | mostre mensagem genérica ao jogador; não revele a causa |
| 10 | 503 | service_unavailable |
motor de regras, cofre de dados ou banco fora | repita com a mesma Idempotency-Key depois do Retry-After |
Notas:
document_invalidno passo 9 cobre CPF ou CNPJ com dígito verificador errado.velocity_exceededno depósito cobre muitos depósitos criados e não pagos numa janela. Os limiares são da regra da operação: consulte Regras (API) e Decisão, limites e regras.- Recusa
4xxnão cria objeto. A mesmaIdempotency-Keydevolve a mesma recusa, guardada por 30 dias. Se você usaIdempotency-Key = external_id, tentar de novo depois de uma recusa exigeexternal_idnovo. Veja Idempotência e repetição. - Erro de rede, timeout,
5xxe429não são respostas conclusivas: repita com a mesma chave.
Erros das outras rotas¶
| Rota | Situação | Resposta |
|---|---|---|
GET /v1/deposits/{id} |
não existe nesta operação, ou id fora do formato |
404 not_found |
GET /v1/deposits |
status, updated_since, limit ou cursor inválidos |
400 validation_failed com o campo em errors[] |
POST /v1/deposits/{id}/cancel |
estado diferente de pending e de cancelled |
409 invalid_state_transition |
POST /v1/deposits/{id}/cancel |
não existe nesta operação | 404 not_found |
| qualquer | sem o escopo exigido | 403 insufficient_scope |
Casos de borda¶
- Pagamento depois de expirar ou cancelar. Se o PIX é pago com o depósito já em
expired,cancelledoufailed, o estado não muda: o Dracma gravapaid_amount,paid_ate o pagador e alerta. Para você,paid_amountpreenchido num estado sem crédito é exceção: não credite. Veja Ciclo do depósito. under_reviewnão credita. O dinheiro entrou, mas há divergência. Espere o desfecho (paidoureturned).- Estado e evento novos. Aplique o leitor tolerante: campo, estado ou motivo desconhecido nunca devem derrubar o seu parser nem mover dinheiro.
- Ambiente. Em operação Teste, e-mail com domínio real é recusado (
reserved_domain_required) e nenhum dinheiro se move.
Veja também¶
- Ciclo do depósito: estados, efeito no seu livro e pagamento tardio.
- Ping e moedas:
deposit_requirements. - Erros e Idempotência e repetição
- Webhooks e Catálogo de eventos
- Sandbox: como simular pagamento, expiração, estorno e chargeback.
- Objetos e campos