Sandbox¶
Para: Dev — Conferido em 2026-10-18.
A operação Teste roda contra um simulador de PSP: nenhum dinheiro se move e você controla o desfecho de cada depósito e saque por rotas /v1/sandbox/*. Use-a para provar o seu conector inteiro antes de pedir uma operação Real.
O que é¶
O "sandbox" do Dracma é o comportamento de uma operação do tipo Teste. Ele não é um servidor separado: quem decide é a operação a que a chave pertence (prefixo key_test_). O GET /v1/ping devolve environment: "sandbox" quando a chave é de uma operação Teste.
| Operação Teste | Operação Real | |
|---|---|---|
| Prefixo da chave | key_test_ |
key_live_ |
| Dinheiro | Nenhum se move | Dinheiro real, em qualquer instância |
| PSP | Simulador do Dracma (sem conexão cadastrada, o simulador é o padrão) | PSP real da operação |
Rotas /v1/sandbox/* |
Existem | Respondem 404 not_found, sem executar nada |
copy_paste do PIX |
BR Code sintético com o marcador SANDBOX |
Cobrança real |
Onde ela fica: no hml, o host api. atende operações Teste e o host api-live. atende operações Real. Em produção só existem operações Real. A tabela de hosts está em Ambientes, tipos de operação e hosts.
- PIX sintético. O
instructions.pix.copy_pastede um depósito Teste traz o marcadorSANDBOXe uma chave de recebedor fictícia (sandbox@dracma.invalid). Nenhum banco aceita esse código. Se umcopy_pastesem o marcador aparecer na sua operação Teste, pare e avise o suporte: você pode estar apontando para uma operação Real. - Cada tipo recusa a chave do outro.
key_test_contra um host de operação Real (e o inverso) responde401 unknown_key. Veja Ambientes, tipos de operação e hosts. - Mesma autenticação da produção em todas as rotas, inclusive
/sandbox/*: assinatura HMAC, nonce e janela de tempo (Autenticação). - Mesmos limites de taxa da produção. O sandbox não tem um perfil de limites menor: o mesmo balde de listagem, o mesmo limite de depósitos e de saques por jogador por hora valem na operação Teste (Limites e quotas). Uma suíte que cria muitos saques para o mesmo jogador esbarra em
429 rate_limited; useexternal_refde jogadores diferentes. - Webhook só para a URL cadastrada na operação. O Dracma nunca entrega para uma URL que venha no corpo de uma requisição (Webhooks).
Dinheiro real
"Sandbox" descreve o tipo da operação, não o hml. No hml existe também operação Real (key_live_), e ela move dinheiro real. Confira o prefixo da chave e o environment do GET /v1/ping antes de rodar uma receita desta seção.
Quando usar¶
- Antes de pedir a operação Real: o go-live exige a Suíte de conformidade verde e as Receitas por caminho provadas contra o seu receptor e o seu livro.
- Para testar um caminho que a produção só produz por acaso: pagamento de terceiro, valor divergente, expiração, estorno, chargeback, saque devolvido, queda do Dracma.
- Para testar o seu código de repetição e de deduplicação: queda simulada e reentrega de webhook.
Como funciona¶
Rotas de controle¶
| Rota | Escopo exigido | O que faz |
|---|---|---|
POST /v1/sandbox/deposits/{id}/pay |
deposits:write |
Simula o pagamento do PIX; aceita pagador e valor diferentes |
POST /v1/sandbox/deposits/{id}/expire |
deposits:write |
pending vira expired |
POST /v1/sandbox/deposits/{id}/refund |
deposits:write |
paid vira refunded |
POST /v1/sandbox/deposits/{id}/chargeback |
deposits:write |
paid vira chargeback |
POST /v1/sandbox/withdrawals/{id}/{action} |
withdrawals:write |
Decisão do revisor ou resultado do PSP no saque (approve, reject, pay, fail, return) |
POST /v1/sandbox/outage |
deposits:write ou withdrawals:write |
Liga e desliga a queda simulada da operação |
POST /v1/sandbox/webhooks/redeliver |
deposits:write ou withdrawals:write |
Reentrega um evento já gravado |
GET /v1/sandbox/webhooks |
read |
Log das últimas entregas de webhook |
- Sem o escopo, a resposta é
403 insufficient_scope. Um objeto de outra operação responde404 not_found, nunca403. - Uma chave com
deposits:write,withdrawals:writeereadcobre todas as rotas da tabela. - Em operação Real, toda rota
/v1/sandbox/*responde404 not_founda uma chave com o escopo exigido, sem executar nada.
Reservado no contrato
POST /v1/sandbox/bank-transfers/incoming existe só para transferência bancária, que a operação PIX não usa: um corpo válido recebe 400 validation_failed com reason: rail_not_enabled. Veja Rotas e campos reservados.
Idempotência nas rotas de controle¶
Mande Idempotency-Key em todo POST, inclusive nas rotas /sandbox/*; sem ela a API responde 400 validation_failed com field: Idempotency-Key. Use uma chave nova a cada ação de controle (por exemplo sbx_<uuidv7>). Repetir a mesma chave devolve a resposta guardada (Idempotent-Replayed: true) sem executar a ação de novo. Isso é o que você quer em POST /v1/deposits, mas atrapalha se você quiser, por exemplo, ligar e desligar a queda simulada duas vezes com a mesma chave.
Pagar um depósito¶
POST /v1/sandbox/deposits/{id}/pay aceita um corpo opcional. Vazio significa "pago pelo próprio jogador, valor exato".
{
"payer_document": {"type": "CPF", "number": "11144477735", "country": "BR"},
"paid_amount": {"amount": "4999", "currency": "BRL"}
}
Os dois campos são opcionais: payer_document (type, number e country) e paid_amount (um Money, na moeda do depósito). Se payer_document vier, number é obrigatório. O exemplo simula um terceiro pagando R$ 49,99, valor diferente do depósito.
- Só funciona em depósito
pending; em qualquer outro estado:409 invalid_state_transition. paid_amountem moeda diferente da do depósito:400 validation_failedcomreason: currency_mismatch.- A resposta é
200com o objeto. A API espera até 3 segundos pelo resultado do simulador; se ele demorar mais, o objeto volta ainda empendinge o desfecho chega pelo webhook. Faça o fetch-back em vez de supor o estado. - Simulador indisponível:
503 service_unavailablecomRetry-After: 1eretryable: true. Repita com uma chave nova de controle.
Ações no saque¶
POST /v1/sandbox/withdrawals/{id}/{action}, sem corpo. A tabela completa de efeitos está em Receitas por caminho.
action |
Resposta quando aceita |
|---|---|
approve, reject |
200 com o saque já decidido (como se o revisor tivesse agido no painel) |
pay, fail |
200 com o saque no estado atual; o desfecho (paid ou failed) chega depois, por webhook |
return |
200 com o saque já em returned |
- Ação fora do enum:
400 validation_failed. - Ação válida para outro estado:
409 invalid_state_transition. compliance_hold,compliance_clear,compliance_reject,send,transit,recall_accepterecall_rejectexistem no enum por causa de transferências bancárias; em PIX respondem409 invalid_state_transition.- Simulador indisponível:
503 service_unavailablecomRetry-After: 5.
Queda simulada¶
POST /v1/sandbox/outage com {"down": true} responde {"down": true}. A partir daí, toda rota da sua operação fora de /v1/sandbox/* responde 503 service_unavailable, com retryable: true e Retry-After: 5. GET /v1/ping e as próprias rotas de sandbox continuam respondendo. Outras operações não são afetadas. {"down": false} religa. O campo down é obrigatório: sem ele, 400 validation_failed.
Log de entregas e reentrega de webhook¶
GET /v1/sandbox/webhooks devolve {"data": [...]} com as 50 entregas mais recentes da operação, da mais nova para a mais antiga. Não há filtro nem paginação, e o corpo do evento não vem no log. Cada item traz:
| Campo | Conteúdo |
|---|---|
id |
Id da entrega |
event_id, event_type |
O evento entregue (Dracma-Event-Id) e o seu tipo |
environment |
sandbox para operação Teste |
status |
pending, delivered, dlq ou skipped |
skip_reason |
Presente só em skipped |
attempts, total_attempts |
Tentativas do ciclo atual e acumuladas |
next_attempt_at |
Próxima tentativa, enquanto pending |
last_status_code, last_duration_ms |
Resposta HTTP do seu receptor e a duração |
last_error |
Erro de rede ou de TLS, truncado em 200 caracteres |
created_at, delivered_at, resolved_at, resolution_reason |
Marcas de tempo e motivo de resolução |
Use esse log para ver as suas respostas 401 e 5xx sem precisar de log no receptor. Estados e cronograma: Retentativas, skipped e DLQ.
POST /v1/sandbox/webhooks/redeliver com {"event_id": "evt_..."} reentrega:
200com{"event_id": "evt_...", "scheduled": n}, ondené o número de entregas reabertas (uma por URL cadastrada). Cada entrega reaberta volta apendingcom as tentativas zeradas.- Funciona também para um evento que já estava
delivered, o que permite testar a sua deduplicação. A reentrega leva o mesmo corpo e o mesmoDracma-Event-Id. event_idfora do formatoevt_mais letras e dígitos:400 validation_failedcomreason: format.- Evento inexistente ou de outra operação:
404 not_found.
Exemplos¶
As chamadas abaixo usam o cliente de shell de Exemplos executáveis. Os comandos completos, do ping ao saque, estão em Primeiro depósito e primeiro saque.
# Ligar a queda simulada (chave de controle nova a cada chamada)
echo '{"down":true}' > corpo-queda.json
bash exemplos/shell/assinar.sh POST /sandbox/outage corpo-queda.json "sbx_$(date +%s)_ligar"
# Ver as últimas entregas de webhook
bash exemplos/shell/assinar.sh GET /sandbox/webhooks
Erros e casos de borda¶
| Você vê | Causa | O que fazer |
|---|---|---|
404 not_found em toda rota /sandbox/* |
A chave é de operação Real, ou o objeto é de outra operação | Confira o prefixo da chave e o environment do GET /v1/ping |
403 insufficient_scope |
A chave não tem o escopo da tabela | Peça uma chave com o escopo certo |
409 invalid_state_transition |
O objeto não está no estado que a ação exige | Leia o objeto com GET e escolha a ação certa |
400 validation_failed com Idempotency-Key |
Faltou a chave no POST |
Mande uma chave nova |
503 service_unavailable em rotas normais |
Queda simulada ligada | Desligue com {"down": false} ou trate como no Retry |
503 service_unavailable em /sandbox/* |
Simulador do PSP indisponível | Repita com Retry-After e chave nova |
429 rate_limited |
Limites iguais aos da produção | Espere o Retry-After |
Veja também¶
- Receitas por caminho: um passo a passo para cada desfecho.
- Suíte de conformidade: o teste de aceite do contrato.
- Dados de teste: CPF, e-mail e valores que o simulador reconhece.
- Ciclo do depósito e Ciclo do saque: as máquinas de estado.
- Webhooks: garantias de entrega e como verificar.