Pular para o conteúdo
DEMO PAYdocs
PTEN
Ir para o painel

Referência da API

Catálogo completo de todos os endpoints públicos da Demo Pay v1. Todos os caminhos são relativos à URL base de produção — https://demo.zentry.cloud/v1. (Um host de sandbox dedicado ainda não está disponível.)

Autentique toda requisição com sua chave de API no cabeçalho apikeyapikey: <DEMO_API_KEY> (dm_test_*/dm_live_*). Todos os corpos são JSON. Todos os valores são inteiros na menor unidade da moeda.

A API é organizada em torno de alguns recursos:

  • Cobranças (/v1/charges) — criar e consultar cobranças Pix: object: "charge", ids ch_…, cabeçalho Idempotency-Key, bloco pix. É por aqui que toda integração começa.
  • Carteiras (/v1/wallets) — o saldo da sua conta.
  • Operações de pagamento (/v1/payments) — reembolso, cancelamento, estatísticas e outras operações sobre uma cobrança, endereçadas pelo id cru (sem o prefixo ch_).
  • Webhooks (/v1/webhooks) — registrar endpoints e inspecionar entregas.

#Cobranças

/v1/charges.

Contrato público das convenções da API §3. Toda resposta é montada por um serializador com allowlist — nenhum id interno, nome de PSP, custo ou payload cru de provedor pode aparecer aqui.

#Criar cobrança

POST /v1/charges — atalho Pix-first: POST /v1/pix/charges fixa payment_method: "pix" no corpo e devolve exatamente a mesma Charge.

Cabeçalhos

CabeçalhoObrigatórioNotas
apikeysimSua chave de API (dm_test_* / dm_live_*).
Idempotency-Keysim8–128 caracteres. É uma escrita financeira — sem ele, é 400.

Corpo

CampoTipoObrigatórioDescrição
amountinteirosimMenor unidade da moeda, > 0.
currencystringnãoPadrão "BRL". Cobranças Pix devem usar BRL.
payment_methodstringsim"pix" — o único valor aceito hoje.
descriptionstringnãoAté 500 caracteres; dobrado em metadata.description na leitura.
customer.namestringnão
customer.documentstringnãoCPF ou CNPJ.
customer.emailstringnão
customer.phonestringnão
metadataobjetonãoLivre; chaves reservadas/prefixadas com underscore são removidas.

Exemplo

bash
curl -X POST https://demo.zentry.cloud/v1/pix/charges \
  -H "apikey: $DEMO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1000,
    "currency": "BRL",
    "description": "Pedido #12345",
    "customer": { "name": "Maria Silva", "document": "12345678901" }
  }'

Resposta 201 Created

json
{
  "id": "ch_a1b2c3d4-0000-0000-0000-000000000009",
  "object": "charge",
  "amount": 1000,
  "currency": "BRL",
  "status": "pending",
  "payment_method": "pix",
  "customer": { "name": "Maria Silva", "document": "12345678901" },
  "pix": {
    "br_code": "000201BRCODEPIX",
    "qr_code_url": "https://qr.example/img.png",
    "expires_at": "2026-07-23T15:00:00.000Z"
  },
  "checkout_url": "https://checkout.demo.zentry.cloud/a1b2c3d4-0000-0000-0000-000000000009",
  "settlement": {},
  "metadata": { "order_id": "12345" },
  "created_at": "2026-07-23T14:30:00.000Z"
}

pix.txid (quando o provedor vinculou um) e settlement.end_to_end_id (só depois de paid e liquidado) são dado contextual do Pix — veja PIX. charge.id nunca é igual a charge.pix.txid.

checkout_url é o checkout hospedado da Demo Pay para a cobrança — redirecione o pagador para lá em vez de renderizar sua própria tela de Pix. Vem tanto na criação quanto no GET /v1/charges/{id}, e não dá para deduzir de charge.id (o caminho do checkout remove o prefixo ch_).

Vocabulário público de status: pending, processing, paid, failed, expired, cancelled, refunded, disputed.


#Consultar cobrança

GET /v1/charges/{id}

Aceita tanto o id com prefixo ch_… quanto o id interno cru. Escopado à conta do chamador — uma cobrança de outra conta responde 404.

Resposta 200 OK — mesma forma de Charge da criação.


#Listar cobranças

Status: o contrato de query abaixo (ListChargesDto + PaymentsService.listCharges) está implementado e testado unitariamente, mas a rota GET /v1/charges ainda não está ligada a um controlador HTTP — chamá-la hoje dá 404. Use a listagem GET /v1/payments até isso subir. Rastreado como follow-up do contrato /v1/charges.

http
GET /v1/charges?limit=25&starting_after=ch_01J…&status=paid
ParâmetroTipoPadrãoDescrição
limitinteiro251–100.
starting_afterstringUm id de cobrança (ch_…) do mesmo recurso — cursor, não offset.
statusenumVocabulário público de status (pending, paid, …).
created_afterISO 8601Limite inferior inclusivo em created_at.
created_beforeISO 8601Limite superior inclusivo em created_at.
customer_idstringFiltra pelo documento do pagador.
json
{
  "object": "list",
  "data": [],
  "has_more": false,
  "next_cursor": null
}

page/offset nunca são aceitos nesta listagem por cursor — apenas starting_after.


#Carteiras

/v1/wallets. Os saldos da sua conta. Somente leitura, com escopo na sua chave de API.

#Consultar saldo

GET /v1/wallets/balance

O parâmetro currency é opcional. Sem ele (forma recomendada), a resposta traz todas as moedas da conta em balances[], mais os campos da moeda primária (BRL por padrão) no topo:

bash
curl "https://demo.zentry.cloud/v1/wallets/balance" \
  -H "apikey: $DEMO_API_KEY"

Resposta 200 OK

json
{
  "available": 880,
  "pending": 0,
  "total": 880,
  "retained": 0,
  "currency": "BRL",
  "next_release_at": null,
  "next_release_amount": null,
  "balances": [
    { "currency": "BRL", "available": 880, "pending": 0, "total": 880 }
  ],
  "primary": { "currency": "BRL", "available": 880, "pending": 0, "total": 880 }
}
CampoDescrição
availableDisponível para gastar/sacar da moeda primária, na menor unidade (centavos no BRL). 880 = R$ 8,80.
pendingLiquidado, mas ainda retido — não disponível ainda (moeda primária).
totalavailable + pending da moeda primária.
retainedTotal em retenção (holds PENDING) da moeda primária.
currencyMoeda primária (ISO 4217). BRL por padrão.
next_release_atQuando a próxima parcela pending é liberada, ou null quando nada está agendado.
next_release_amountValor dessa próxima liberação (menor unidade da moeda), ou null.
balances[]Uma entrada por moeda: { currency, available, pending, total }.
primaryA moeda primária (mesmos campos de uma entrada de balances[]).

Os campos no topo (available/pending/total/currency) são a moeda primária — mantidos por compatibilidade. Para contas multi-moeda, itere sobre balances[].

#Uma moeda só (formato legado)

GET /v1/wallets/balance?currency=BRL

Passe currency para receber o formato achatado de uma única moeda:

bash
curl "https://demo.zentry.cloud/v1/wallets/balance?currency=BRL" \
  -H "apikey: $DEMO_API_KEY"
json
{
  "available": 880,
  "pending": 0,
  "currency": "BRL",
  "next_release_at": null,
  "next_release_amount": null
}

Autenticação e erros. Sempre com o header apikey. Chave ausente ou inválida → 401 (nunca 404). Se você receber 404 nesta rota, o request não chegou na Demo Pay — quase sempre é caminho errado (/v1/wallets/balance, no plural, com o prefixo /v1) ou um proxy/gateway intermediário que não repassa /v1/wallets/*.

#Listar carteiras

GET /v1/wallets

Todas as carteiras da conta (operacional, por moeda), mesma autenticação.

bash
curl https://demo.zentry.cloud/v1/wallets \
  -H "apikey: $DEMO_API_KEY"

Resposta 200 OK

json
[
  {
    "currency": "BRL",
    "walletType": "OPERATIONAL",
    "balance": 880,
    "pendingBalance": 0
  }
]

balance/pendingBalance vêm na menor unidade da moeda — os mesmos valores que GET /v1/wallets/balance expõe como available/pending.


#Operações de pagamento

/v1/payments. Estas rotas operam sobre a mesma cobrança que você criou via /v1/charges, endereçada pelo id cru (sem o prefixo ch_). Cobrem operações que a superfície /v1/charges ainda não expõe — reembolso, cancelamento, estatísticas, comprovantes — além de criar/consultar/listar no formato de fio de transação (ids tx_…, status WAITING_PAYMENT/PAID). Para criar uma cobrança, prefira Cobranças.

#Criar pagamento

POST /payments

Corpo

CampoTipoObrigatórioDescrição
amountinteirosimMenor unidade da moeda, > 0.
currencystring (3–8)nãoPadrão "BRL". Exemplos: BRL, EUR, USD, USDT.
paymentMethodsstring[]simUm ou mais de: PIX, CREDIT_CARD, MBWAY, MULTIBANCO, BOLETO, CRYPTO.
customerIdstringnãoSeu id interno de usuário, ecoado nos webhooks.
customerNamestringnão
customerDocumentstringnãoCPF, CNPJ, NIF ou outro id fiscal.
customerEmailstringnãoValidado como RFC 5322.
metadataobjetonãoLivre. Chave reservada: returnUrl (usada por CREDIT_CARD). Para MBWAY você deve incluir phone (E.164).
webhookUrlstringnãoURL de webhook por transação (sobrepõe a global).
idempotencyKeystringsimÚnica por requisição pretendida. Reenvios devolvem a original.

Resposta 201 Created

json
{
  "id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
  "status": "WAITING_PAYMENT",
  "amount": 24900,
  "currency": "BRL",
  "paymentMethods": ["PIX"],
  "customerName": "Maria Silva",
  "customerDocument": "12345678909",
  "customerEmail": "maria@example.com",
  "metadata": { "orderId": "ORD-7821" },
  "createdAt": "2026-04-25T15:42:11.000Z"
}

Campos específicos de método (pixQrCode, cardRedirectUrl, etc.) são preenchidos pelo GET /payments/{id} depois que a Demo Pay finaliza a cobrança com o adquirente subjacente (normalmente <3s).


#Consultar pagamento

GET /payments/{id}

Resposta 200 OK

json
{
  "id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
  "status": "PAID",
  "amount": 24900,
  "currency": "BRL",
  "paymentMethods": ["PIX"],
  "paidWith": "PIX",
  "pixQrCode": "data:image/png;base64,iVBOR...",
  "pixCopyPaste": "00020126580014br.gov.bcb.pix...",
  "pixExpiresAt": "2026-04-25T16:12:11.000Z",
  "cardRedirectUrl": null,
  "mbEntity": null,
  "mbReference": null,
  "mbExpiresAt": null,
  "boletoBarcode": null,
  "boletoLine": null,
  "boletoPdfUrl": null,
  "boletoExpiresAt": null,
  "cryptoAddress": null,
  "cryptoAmount": null,
  "cryptoNetwork": null,
  "cryptoCurrency": null,
  "providerFee": 75,
  "platformFee": 200,
  "netAmount": 24625,
  "metadata": { "orderId": "ORD-7821" },
  "createdAt": "2026-04-25T15:42:11.000Z",
  "paidAt": "2026-04-25T15:43:08.000Z"
}

Campos vêm null quando não se aplicam aos paymentMethods escolhidos.


#Listar pagamentos

GET /payments

Parâmetros de query

ParâmetroTipoPadrãoDescrição
pageint1
limitint20Máx. 100.
statusenumVeja Enum de status.
startDateISO 8601Limite inferior inclusivo em createdAt.
endDateISO 8601Limite superior inclusivo em createdAt.
sortBystringcreatedAtQualquer campo de topo.
sortOrderenumdescasc ou desc.

Resposta 200 OK

json
{
  "data": [ { "id": "tx_...", "...": "..." } ],
  "total": 142,
  "page": 1,
  "limit": 20
}

#Estatísticas

GET /payments/stats?days=7

Resposta 200 OK

json
{
  "totalTransactions": 142,
  "paidTransactions": 119,
  "todayTransactions": 8,
  "successRate": 84,
  "volumeByCurrency": [
    { "currency": "BRL", "volume": 1245000, "count": 95 },
    { "currency": "EUR", "volume": 89400,   "count": 24 }
  ],
  "todayVolumeByCurrency": { "BRL": 24900, "EUR": 8990 },
  "dailyVolume": [
    { "date": "2026-04-19", "currencies": { "BRL": 89000 } },
    { "date": "2026-04-20", "currencies": { "BRL": 124500, "EUR": 4500 } }
  ],
  "methodBreakdown": [
    { "method": "PIX",         "volume": 980000, "count": 78 },
    { "method": "CREDIT_CARD", "volume": 265000, "count": 34 },
    { "method": "MULTIBANCO",  "volume": 89400,  "count": 7 }
  ]
}

#Métricas

GET /payments/metrics?days=7&currency=BRL

Métricas de funil de conversão e volume da sua conta de lojista. days tem padrão 7; currency é opcional (filtra para uma única moeda). Escopado à sua apikey.


#Reembolsar pagamento

POST /payments/{id}/refund

Reembolsa uma transação liquidada (PAID ou APPROVED), total ou parcial. Ativo em produção. Para PIX isso mapeia para uma devolução BACEN (por endToEndId) ou um cashout PIX-out, conforme strategy.

Corpo

CampoTipoObrigatórioDescrição
idempotencyKeystringsim8–128 caracteres. Reenvios devolvem o reembolso original.
amountinteironãoMenor unidade da moeda, > 0. Omita para reembolso total. Deve ser ≤ ao reembolsável restante.
reasonstringnãoAté 500 caracteres, guardado para seus registros.
strategyenumnãoSó PIX: devolution ou cashout. Padrão cashout.
passFeeToTenantbooleannãoReembolsos por cashout: debita a taxa de PIX-out da sua carteira. Padrão false. (o nome do campo reflete o formato de fio v1 atual — um alias com escopo de merchant chega com a migração da API pública; veja o glossário.)
destinationKeystringnãoReembolsos por cashout: envia para uma chave PIX específica em vez do documento do pagador.

Resposta 201 Created

json
{
  "id": "b2c3d4e5-f6a7-4890-9abc-def012345678",
  "transactionId": "a1b2c3d4-e5f6-4789-9abc-def012345678",
  "amount": 24900,
  "currency": "BRL",
  "status": "PENDING",
  "reason": "customer_request",
  "createdAt": "2026-04-25T15:50:00.000Z"
}

O status do reembolso avança de forma assíncrona (PENDINGIN_PROGRESSREFUNDED/FAILED) conforme o adquirente confirma — assine o webhook payment.refunded. A transação só vira REFUNDED quando o total reembolsado atinge o valor original; reembolsos parciais a deixam em PAID/APPROVED.

O suporte a reembolso depende do provedor: PIX (BrasilCash) e cartão (Stripe) estão ativos. Outros provedores devolvem um erro REFUND_NOT_SUPPORTED.


#Listar reembolsos

GET /payments/{id}/refunds

Devolve todos os reembolsos emitidos contra uma transação (mais recentes primeiro).


#Cancelar pagamento

POST /payments/{id}/cancel

Cancela uma cobrança em andamento — válido só enquanto WAITING_PAYMENT, PENDING ou PROCESSING. Cobranças liquidadas (PAID/APPROVED) devem ser reembolsadas, não canceladas. Devolve a transação atualizada e dispara payment.failed.


#Reenviar webhook

POST /payments/{id}/resend-webhook

Reemite o status atual da transação como uma entrega de webhook nova — útil quando seu endpoint estava fora do ar.

json
{ "resent": true, "status": "PAID" }

#Status no provedor

GET /payments/{id}/provider-status

Status ao vivo direto do adquirente (ignora nosso cache) — para depurar cobranças travadas.

json
{
  "localStatus": "WAITING_PAYMENT",
  "provider": "brasilcash",
  "providerTransactionId": "bc_...",
  "providerStatus": "PENDING",
  "rawResponse": { "...": "..." }
}

Devolve "error": "TRANSACTION_HAS_NO_PROVIDER_REFERENCE" quando a cobrança nunca chegou a um provedor.


#Comprovante

GET /payments/{id}/receipt

Comprovante do provedor (PDF) para uma transação liquidada, onde o adquirente expõe um (ex.: PIX da BrasilCash).

json
{ "contentType": "application/pdf", "base64": "JVBERi0xLjcK..." }

#Webhooks

#Registrar endpoint

POST /webhooks/endpoints

json
{
  "url": "https://merchant.example.com/hooks/demo",
  "events": ["charge.paid", "charge.failed", "charge.expired"]
}

Nomes de evento (relativos a cobrança): charge.created, charge.paid, charge.failed, charge.expired, payout.created, payout.paid, payout.failed. São entregues no envelope versionado evt_ e assinados X-Demo-Signature: t=<unix>,v1=<hex> — veja Webhooks. Assine estes.

O endpoint também aceita uma família de eventos mais antiga (payment.created, payment.completed, payment.failed, payment.expired, payment.refunded, withdrawal.* e os aliases payment.status_changed/withdrawal.status_changed), entregue com o envelope { event, data } e X-Demo-Signature: sha256=<hex>. Integrações novas não precisam dela — use os nomes charge.*/payout.* acima. A lista completa e atual é autoritativa em GET /webhooks/event-catalog.

Resposta 201 Created

json
{
  "id": "e5f6a7b8-c9d0-4123-9ef0-123456789012",
  "url": "https://merchant.example.com/hooks/demo",
  "events": ["charge.paid", "charge.failed", "charge.expired"],
  "secret": "b8f3a9c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1",
  "status": "ACTIVE"
}

O secret é mostrado uma única vez — guarde imediatamente.


#Listar endpoints

GET /webhooks/endpoints

json
{
  "data": [
    {
      "id": "wh_...",
      "url": "https://...",
      "events": ["payment.status_changed"],
      "status": "ACTIVE",
      "createdAt": "...",
      "updatedAt": "..."
    }
  ]
}

O secret nunca é devolvido por este endpoint.


#Rotacionar segredo

POST /webhooks/endpoints/{id}/rotate-secret

json
{ "id": "e5f6a7b8-c9d0-4123-9ef0-123456789012" }

Resposta 200 OK

json
{ "id": "e5f6a7b8-c9d0-4123-9ef0-123456789012", "secret": "<hex de 64 caracteres>" }

O novo segredo é mostrado uma única vez. A rotação é uma troca instantânea no servidornão há janela de sobreposição. Todo webhook assinado depois desta chamada usa o novo segredo, então faça seu verificador aceitar ambos — o antigo e o novo — durante o seu deploy, e depois descarte o antigo (veja webhooks.md).


#Atualizar endpoint

PATCH /webhooks/endpoints/{id}

Atualiza URL, eventos assinados ou status (ACTIVE/INACTIVE). Envie só os campos a mudar.

json
{ "url": "https://merchant.example.com/hooks/v2", "status": "ACTIVE" }

Resposta 200 OK{ id, url, events, status }. O segredo nunca é devolvido.


#Remover endpoint

DELETE /webhooks/endpoints/{id}

Remove o endpoint permanentemente. Todas as entregas pendentes para ele são abandonadas.

Resposta 200 OK{ "deleted": true }.


#Catálogo de eventos

GET /webhooks/event-catalog

Devolve a lista completa e atual de nomes de evento públicos assináveis com descrições (legacy: true nas famílias descontinuadas). Sem autenticação. Trecho relevante para cobrança/saque:

json
[
  { "event": "charge.created", "description": "Cobrança criada (Pix/cartão gerado, aguardando pagamento)." },
  { "event": "charge.paid",    "description": "Cobrança paga e confirmada (Pix/cartão liquidado)." },
  { "event": "charge.failed",  "description": "Cobrança falhou ou foi cancelada." },
  { "event": "charge.expired", "description": "Cobrança expirou sem pagamento." },
  { "event": "payout.created", "description": "Saque solicitado." },
  { "event": "payout.paid",    "description": "Saque liquidado com sucesso." },
  { "event": "payout.failed",  "description": "Saque falhou ou foi rejeitado." },
  { "event": "payment.completed",    "description": "[legado] Cobrança paga — use charge.paid.", "legacy": true },
  { "event": "withdrawal.completed", "description": "[legado] Saque liquidado — use payout.paid.", "legacy": true }
]

#Listar entregas

GET /webhooks/deliveries

ParâmetroDescrição
statusPENDING, PROCESSING, DELIVERED, FAILED, CANCELLED
eventTypeFiltra por nome de evento (payment.completed, …).
endpointIdFiltra por endpoint registrado.
limitPadrão 25, máx. 100.
offsetPadrão 0.
json
{
  "data": [
    {
      "id": "wd_...",
      "endpointId": "wh_...",
      "eventType": "payment.completed",
      "status": "DELIVERED",
      "attempts": 1,
      "maxAttempts": 15,
      "lastStatusCode": 200,
      "lastError": null,
      "nextRetryAt": null,
      "deliveredAt": "2026-04-25T15:43:09.000Z",
      "createdAt": "2026-04-25T15:43:08.000Z",
      "updatedAt": "2026-04-25T15:43:09.000Z",
      "payload": { "event": "payment.completed", "data": { "...": "..." } }
    }
  ],
  "total": 142,
  "limit": 25,
  "offset": 0
}

#Estatísticas de entrega

GET /webhooks/stats

json
{
  "total": 1402,
  "PENDING": 3,
  "PROCESSING": 1,
  "DELIVERED": 1380,
  "FAILED": 12,
  "CANCELLED": 6
}

#Enum de status

A tabela abaixo é o enum de status detalhado devolvido pelas rotas de transação /v1/payments (e eventType/payload.data.status nas entregas de webhook delas). POST/GET /v1/charges nunca emitem esses valores; eles emitem o vocabulário público menor (pending, processing, paid, failed, expired, cancelled, refunded, disputed — veja Primeiros passos §5), no qual o enum abaixo é mapeado.

Status da transaçãoDescriçãocharge.status público
PENDINGInterno — sendo criado. Raramente aparece.pending
WAITING_PAYMENTAguardando ação do cliente.pending
PROCESSINGCartão / 3DS em andamento.processing
PAIDLiquidado — métodos não-cartão.paid
APPROVEDLiquidado — métodos de cartão.paid
REFUSEDAdquirente ou emissor recusou.failed
CANCELLEDCancelado antes de concluir.cancelled
EXPIREDJanela de tempo esgotada.expired
REFUNDEDTotalmente reembolsado.refunded
CHARGEBACKEmissor abriu um chargeback (cartões).disputed
DISPUTEPortador abriu uma disputa (cartões).disputed

payment.completed dispara para PAID e APPROVED; charge.paid dispara para a mesma transição subjacente. payment.failed dispara para REFUSED, CANCELLED, EXPIRED, CHARGEBACK, DISPUTE; charge.failed e charge.expired dividem essa família payment.* mais antiga por desfecho.


#Schema do payload de webhook

#Envelope canônico (charge.* / payout.*)

json
{
  "id": "evt_5f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
  "object": "event",
  "api_version": "2026-07-23",
  "type": "charge.paid",
  "created_at": "2026-07-23T14:31:00.000Z",
  "data": {
    "object": {
      "id": "ch_a1b2c3d4-0000-0000-0000-000000000009",
      "object": "charge",
      "amount": 24900,
      "currency": "BRL",
      "status": "paid",
      "payment_method": "pix",
      "settlement": { "end_to_end_id": "E-END-TO-END-99" }
    }
  }
}
CampoSempre presenteDescrição
idsimevt_… — estável por evento de negócio, idêntico entre retentativas. Deduplique por ele.
objectsimSempre "event".
api_versionsimVersão do contrato, ex. 2026-07-23.
typesimcharge.created | charge.paid | charge.failed | charge.expired | payout.created | payout.paid | payout.failed.
data.objectsimO mesmo objeto público Charge/Payout que a API REST devolve — mesmo serializador, mesmos nomes de campo.

#Envelope payment.* / withdrawal.*

json
{
  "event": "payment.completed",
  "data": {
    "transactionId": "tx_...",
    "amount": 24900,
    "status": "PAID",
    "previousStatus": "WAITING_PAYMENT",
    "paidWith": "PIX",
    "providerFee": 75,
    "platformFee": 200,
    "netAmount": 24625,
    "occurredAt": "2026-04-25T15:43:08.000Z"
  }
}
CampoSempre presenteDescrição
transactionIdsimCasa com o id devolvido na criação.
amountsimMenor unidade da moeda.
statussimStatus atual — veja Enum de status.
previousStatussimStatus antes desta transição.
paidWithem PAID/APPROVEDO método efetivamente usado.
providerFeeem PAID/APPROVEDTaxa do adquirente, menor unidade.
platformFeeem PAID/APPROVEDTaxa da Demo Pay, menor unidade.
netAmountem PAID/APPROVEDamount - providerFee - platformFee.
occurredAtsimISO 8601 UTC.

#Cabeçalhos de webhook

CabeçalhoDescrição
X-Demo-SignatureEventos charge.*/payout.*: t=<unix>,v1=<hex> HMAC de "<t>.<rawBody>". Eventos payment.*/withdrawal.*: sha256=<hex> HMAC do corpo cru.
X-Demo-Delivery-IdÚnico por tentativa de entrega — estável entre retentativas da mesma tentativa; use para deduplicação a nível de transporte.
X-Demo-Event-TypeEspelha type / event.

Veja webhooks.md para exemplos de verificação.

#Códigos de status HTTP

CódigoUsado para
200Leitura bem-sucedida
201Recurso criado
204Sem conteúdo (ex.: logout)
400Erro de validação, ou escrita financeira sem Idempotency-Key
401apikey ausente/inválido
403Barrado pela guarda de fraude / velocidade (código fraud.*)
404Recurso não encontrado
409Conflito de idempotência — error.code: "idempotency_key_reused"
422Rejeição de regra de negócio repassada da config de provedor (ex.: nenhum PSP configurado)
429Limitado por taxa
500Erro de servidor — seguro retentar (a idempotência protege)
503Adquirente upstream indisponível — retente com backoff

Veja Erros para o envelope canônico completo de erro (error.type/error.code/error.message, request_id, X-Request-Id).