Rotas e campos reservados

Para: Dev — Conferido em 2026-10-18.

O contrato 1.1.0 define câmbio, recebimentos bancários, recall de saque e transferência bancária (wire e SWIFT). O Dracma publica essas rotas no documento OpenAPI, mas nenhuma operação tem câmbio nem trilho bancário habilitado. Esta página mostra o que cada rota responde hoje, o que cada campo reservado vale e o que o seu código deve fazer para continuar correto.

O que é

Não disponível

O Dracma não oferece hoje câmbio, cotação de moeda, recebimento de transferência bancária (wire ou SWIFT) nem recall de saque. As rotas existem para manter o contrato 1.1.0 inteiro, mas respondem sempre com um erro do catálogo ou com uma lista vazia, sem criar nem alterar nada. O único método de depósito e de saque é pix, em BRL.

Rota Escopo operationId Resposta hoje
POST /v1/withdrawals/{id}/recall withdrawals:write pedirRecallDeSaque saque da operação: 409 invalid_state_transition; saque inexistente ou de outra operação: 404; corpo inválido: 400
POST /v1/fx/quotes deposits:write ou withdrawals:write criarCotacao corpo válido: 422 fx_not_enabled; corpo inválido: 400
GET /v1/fx/quotes/{id} read obterCotacao sempre 404 not_found
GET /v1/receipts read listarRecebimentos 200 com {"data": [], "next_cursor": null}; parâmetro inválido: 400
GET /v1/receipts/{id} read obterRecebimento sempre 404 not_found
POST /v1/sandbox/bank-transfers/incoming deposits:write sandboxTransferenciaRecebida corpo válido: 400 rail_not_enabled; corpo inválido: 400 validation_failed; em operação Real: 404

Essas rotas existem desde o ajuste de 2026-10-02: antes disso respondiam 404 de rota inexistente. Veja OpenAPI.

Quando usar

Na prática, não use. O que importa para o seu conector:

  • Não monte telas nem fluxos que dependam de câmbio, recibo bancário ou recall: o Dracma não os atende.
  • Um cliente gerado a partir do OpenAPI vai ter métodos para essas rotas. Elas existem para o contrato fechar, não para uso.
  • O seu código deve tolerar os estados, campos e eventos reservados (seção "Campos, estados e eventos reservados"). Assim, nada quebra se um dia forem preenchidos.

Como funciona

Recall de saque: POST /v1/withdrawals/{id}/recall

Recall só vale para saque wire ou SWIFT já enviado. Todo saque do Dracma é PIX, então não há caminho de sucesso. A API confere, nesta ordem:

  1. id fora do formato wdr_ mais letras e números: 404 not_found.
  2. Corpo: reason_code é obrigatório e deve ser um destes: duplicate, wrong_beneficiary, wrong_amount, fraud_suspected, other. justification é opcional, até 1000 caracteres. Corpo fora disso: 400 validation_failed (enum para o motivo, max_length para a justificativa, e as demais razões do corpo estrito).
  3. Saque inexistente, ou de outra operação: 404 not_found.
  4. Saque existente da operação: 409 invalid_state_transition. Nada muda no saque, qualquer que seja o estado dele.

Para desfazer um saque que ainda não foi enviado, use o cancelamento descrito em Saques.

Cotação de câmbio: POST /v1/fx/quotes e GET /v1/fx/quotes/{id}

POST /v1/fx/quotes valida o corpo, confere o escopo e responde 422 fx_not_enabled. A ordem:

  1. Corpo que não é JSON válido ou tem campo desconhecido: 400 validation_failed, field: body, reason: invalid_json.
  2. Campos fora do schema, com reason: invalid:

    errors[0].field Regra
    purpose obrigatório: deposit ou withdrawal
    sell_currency sell_currency e buy_currency obrigatórias e diferentes
    sell_amount exatamente um entre sell_amount e buy_amount, nunca os dois nem nenhum
    sell_amount, buy_amount texto de inteiro na menor unidade, sem zero à esquerda, até 38 dígitos
  3. Escopo conforme o purpose: deposits:write para deposit, withdrawals:write para withdrawal. Sem ele: 403 insufficient_scope.

  4. Corpo válido: 422 fx_not_enabled. Nenhuma cotação é criada, de nenhuma operação.

GET /v1/fx/quotes/{id} responde sempre 404 not_found, com id bem ou mal formado: não há como saber se uma cotação existe.

Os campos fx_quote_id e payout_currency não têm efeito. No depósito, fx_quote_id é recusado (unknown_field); no saque, fx_quote_id, payout_currency e purpose são aceitos pela forma e ignorados. Veja Divergências conhecidas.

Recebimentos bancários: GET /v1/receipts e GET /v1/receipts/{id}

Um recebimento seria um crédito bancário (wire ou SWIFT) que não casou com um depósito. Como nenhuma operação tem trilho bancário, nenhum recebimento existe.

  • GET /v1/receipts valida os parâmetros do contrato e devolve {"data": [], "next_cursor": null}. É uma rota de listagem e usa o balde de listagem do rate limit.
  • Os parâmetros são validados: status precisa estar em unmatched, matched, returned, frozen (reason: enum); limit de 1 a 200 (range); updated_since em RFC 3339 (format).
  • Qualquer cursor é inválido: 400 com reason: format, porque a API nunca emitiu um cursor de recebimento. Não é uma página vazia.
  • GET /v1/receipts/{id} responde sempre 404 not_found, sem distinguir id bem ou mal formado.

Transferência bancária simulada: POST /v1/sandbox/bank-transfers/incoming

Rota de sandbox que simularia um crédito bancário entrante. Em operação Teste ela exige deposits:write e Idempotency-Key, valida o corpo e responde 400 rail_not_enabled: nada é casado nem criado. Em operação Real ela não existe (404).

Corpo (amount e rail são obrigatórios):

Campo Regra
amount Money: amount é texto de inteiro sem zero à esquerda, até 38 dígitos; currency é o código da moeda em maiúsculas
rail ^[a-z][a-z0-9_]{1,31}$
reference até 140 caracteres
payer_name até 140 caracteres
payer_document type em CPF, CNPJ, PASSPORT, NATIONAL_ID, TAX_ID; number de 1 a 32 caracteres; country ISO alfa-2
payer_country ISO alfa-2
screening clear ou hit

Corpo fora disso: 400 validation_failed com reason: invalid e o campo em errors[0].field. Corpo válido: 400 com code: rail_not_enabled e errors[0] = {field: "rail", reason: "rail_not_enabled"}. Nenhuma operação tem trilho habilitado, então não existe corpo que resulte em sucesso. Nem uma reference de um depósito seu faz diferença: a rota não lê depósito algum.

Campos, estados e eventos reservados

Reservado no contrato

Tudo o que está nesta seção existe no contrato 1.1.0 (e, para Saque, também no documento OpenAPI servido), mas o Dracma não preenche, não emite ou não alcança hoje. Trate como informativo e aplique o leitor tolerante.

Onde O que Valor hoje
Deposito rail, received_amount, receipts, fee, fees, fx, compliance, expected_settlement_date, return não são devolvidos
Saque rail, fees, charge_bearer, fx, purpose, compliance, expected_settlement_date, sent_at, tracking, recall null, e fees é []
Saque fee null. Sem tarifa descontada do saque
Saque return preenchido em returned. Não é reservado. Veja Saques
Moeda rails não é devolvido
Metodo card, crypto, boleto, bank_transfer, wire, swift 400 method_not_enabled
StatusDeposito pending_compliance, frozen, paid_partial nenhum depósito chega a esses estados
StatusSaque pending_compliance, sent, in_transit, recall_requested, recalled nenhum saque chega a esses estados; só valem como filtro de status
Eventos deposit.pending_compliance, deposit.frozen, deposit.paid_partial, withdrawal.pending_compliance, withdrawal.sent, withdrawal.in_transit, withdrawal.recall_requested, withdrawal.recall_rejected, withdrawal.recalled, receipt.unmatched, receipt.matched, receipt.returned, receipt.frozen não são emitidos. Veja Catálogo de eventos
Reconciliacao kind fee, recall, receipt; fee do item; totals.fees sem itens desses kind; fee é null; totals.fees é "0". Veja Reconciliação
Cambio, Compliance, RastreioBancario, Recall, Recebimento, Tarifa, TrilhoDisponivel schemas inteiros nunca devolvidos hoje

Exemplos

Cotação com corpo válido, resposta 422:

POST /v1/fx/quotes HTTP/1.1
Host: api.example.test
Content-Type: application/json; charset=utf-8
Idempotency-Key: fxq-0192a3b4-5c6d-7e8f-9a0b-1c2d3e4f5a6b
Dracma-Key-Id: key_test_01J9EXEMPLO
Dracma-Timestamp: 1790000000
Dracma-Nonce: 0123456789abcdef0123456789abcdef
Dracma-Signature: v1=<assinatura>

{
  "purpose": "deposit",
  "sell_currency": "USD",
  "buy_currency": "BRL",
  "sell_amount": "10000"
}
{
  "type": "https://docs.dracma.test/errors/fx_not_enabled",
  "title": "fx_not_enabled",
  "status": 422,
  "code": "fx_not_enabled",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "retryable": false
}

Recall de um saque PIX da sua operação. Corpo do pedido:

{
  "reason_code": "duplicate",
  "justification": "Pedido duplicado por falha do meu conector."
}

Resposta 409:

{
  "type": "https://docs.dracma.test/errors/invalid_state_transition",
  "title": "invalid_state_transition",
  "status": 409,
  "code": "invalid_state_transition",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "retryable": false
}

Listagem de recebimentos, resposta 200:

{
  "data": [],
  "next_cursor": null
}

Transferência simulada com corpo válido, resposta 400:

{
  "type": "https://docs.dracma.test/errors/rail_not_enabled",
  "title": "rail_not_enabled",
  "status": 400,
  "code": "rail_not_enabled",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "retryable": false,
  "errors": [
    {
      "field": "rail",
      "message": "trilho não habilitado na operação",
      "reason": "rail_not_enabled"
    }
  ]
}

Erros e casos de borda

Situação Resposta
Qualquer das rotas sem o escopo exigido 403 insufficient_scope
POST sem Idempotency-Key 400 validation_failed
Rota de sandbox em operação Real 404 not_found (nunca 403)
422 fx_not_enabled e 400 rail_not_enabled recusas definitivas: não repita
409 invalid_state_transition no recall definitiva: o recall não se aplica a saque PIX
  • Uma recusa 4xx guardada pela idempotência volta igual por 30 dias. Veja Idempotência e repetição.
  • GET /v1/receipts conta no balde de listagem: não faça polling nela.

Veja também