💳 DexCard — Cartão Pré-pago em Dólar
Esta página explica como um usuário pede, recebe e usa um cartão pré-pago denominado em dólar, recarregado com o saldo que ele já tem na conta DEX.
Funciona assim: o usuário verifica se pode pedir, envia três documentos, aceita os termos e solicita. A solicitação passa por duas análises — a nossa e a do emissor — e, aprovada, o cartão nasce ativo. A partir daí ele recarrega a partir de BRT, USDC ou USDT, gasta em dólar, resgata o que sobrou de volta para a conta, congela e descongela quando quiser, e acompanha tudo pelo extrato.
> Liberado caso a caso. O DexCard é habilitado por participante — a empresa parceira à qual a conta do usuário pertence. Sem essa liberação, todas as chamadas desta página devolvem 403 CARD_CONFIG_MODULE_DISABLED; fale com seu gerente de conta.
1. As Seis Fases
| Fase | O que acontece | Endpoints |
|---|---|---|
| 1. Elegibilidade | Descobrir se a pessoa pode pedir, e quanto custa emitir | GET /cards/eligibility · GET /cards/issuance-fee/preview |
| 2. Documentos | Enviar os três documentos do titular | GET /cards/documents/requirements · POST /cards/documents/upload · GET /cards/documents |
| 3. Solicitação | Aceitar os termos e pedir o cartão | POST /cards/request |
| 4. Análise | Acompanhar: nossa análise → análise do emissor → cartão emitido | GET /cards/application-status |
| 5. Cartão ativo | Ver dados, saldo, limites e credenciais | GET /cards/my-cards · GET /cards/{id} · GET /cards/{id}/balance · GET /cards/{id}/limits · GET /cards/{id}/secure-credentials |
| 6. Movimentação | Recarregar, resgatar, congelar, extrato | …/load/* · …/redeem/* · …/freeze · …/transactions |
As fases 1 a 4 acontecem uma vez. A fase 6 é o dia a dia.
2. Quem Pode Usar
| Requisito | Como saber |
|---|---|
| Conta com verificação completa (KYC aprovado) | GET /v1/profile → accountStatus: FULL |
| Telefone e e-mail confirmados | Confirmação pelo app/onboarding |
| Data de nascimento e endereço no cadastro | GET /v1/profile · GET /v1/profile/address |
| PIN de 4 dígitos cadastrado | Exigido para recarregar e resgatar (seção 3) |
| Não ser Sub Usuário | Sub Usuário não tem cartão (veja Sub Usuário) |
| Cota de emissão disponível | Cada participante contrata um número de cartões. Esgotada a cota, ninguém mais emite até ela aumentar |
Tudo isso é conferido de uma vez em GET /cards/eligibility — não é preciso checar item a item.
3. Credencial Necessária
Todas as chamadas desta página usam o token do próprio usuário: o JWT do app, ou um token gerado com a credencial pessoal dele em POST /v1/auth/api-key.
A credencial de participante (client_id/client_secret da empresa) não opera cartão de usuário. Ela nem sequer resolve para um usuário — a chamada falha. O que o participante faz sozinho está na página DexCard para o Participante.
> Recarga e resgate exigem o PIN de 4 dígitos da conta no corpo da requisição. Isso é deliberado: são as duas operações que movem dinheiro do usuário. Na prática significa que quem integra precisa de uma tela onde a pessoa digita o PIN na hora — não há como recarregar um cartão de forma inteiramente server-to-server. PIN errado devolve 401 CARD_INVALID_PIN.
4. Unidades: o Erro Mais Caro desta API
Ele nunca aparece como erro. Aparece como valor errado que passa.
| Sufixo do campo | Unidade | USD 20,00 / 100,00 USDT fica |
|---|---|---|
…UsdCents |
centavos de dólar, inteiro em string | "2000" |
…SourceAmount / …TargetAmount |
centésimos da moeda citada ao lado, inteiro em string | "10000" |
exchangeRate |
decimal em string | "5.49800000" |
"Centésimos" é o valor multiplicado por cem, sem casa decimal — a mesma ideia de centavos, valendo para qualquer moeda:
| O usuário digita | Você envia |
|---|---|
| 100,00 USDT | "10000" |
| 1,00 USDT | "100" |
| 12,34 USDC | "1234" |
| 250,00 BRT | "25000" |
> Valor com casa decimal não é recusado — é reinterpretado. Enviar "100.00" achando que são cem USDT passa na validação e é entendido como 100 centésimos, ou seja, 1,00 USDT: a recarga acontece, cem vezes menor, e ninguém recebe erro nenhum. Cem USDT se escreve "10000".
O servidor devolve os dois lados de cada cálculo (moeda de origem e dólar) justamente para a sua tela não precisar converter nada.
5. Fase 1 — Elegibilidade e Custo
5.1 Pode pedir?
curl https://api.dexkey.finance/v1/cards/eligibility \
-H "Authorization: Bearer $TOKEN"
{
"canRequest": false,
"hasCard": false,
"blockers": [
{
"code": "ACCOUNT_NOT_FULL",
"message": "Conclua a verificação de identidade da sua conta para solicitar o cartão",
"isResolvableByHolder": true
},
{
"code": "ADDRESS_MISSING",
"message": "Cadastre seu endereço para solicitar o cartão",
"isResolvableByHolder": true
}
]
}
| Campo | O que é |
|---|---|
canRequest |
true só quando blockers está vazio |
hasCard |
A pessoa já tem cartão. Só ofereça o DexCard na tela quando vier hasCard: false e canRequest: true |
blockers[].code |
Código estável — trate por ele, não pelo texto |
blockers[].message |
Texto pronto para exibir ao usuário |
blockers[].isResolvableByHolder |
true = leve a pessoa à tela que resolve. false = não há o que ela faça |
Os bloqueadores possíveis: MODULE_DISABLED, SUB_USER_RESTRICTED, PROFILE_MISSING, ACCOUNT_NOT_FULL, PHONE_NOT_VERIFIED, EMAIL_NOT_VERIFIED, BIRTH_DATE_MISSING, ADDRESS_MISSING, PREVIOUSLY_REJECTED, QUOTA_EXHAUSTED, ALREADY_HAS_CARD, DUPLICATE_PHONE.
Os impedimentos vêm todos de uma vez, de propósito: assim a pessoa resolve tudo numa passada, em vez de corrigir um, tentar de novo e descobrir o seguinte.
5.2 Quanto custa emitir
curl https://api.dexkey.finance/v1/cards/issuance-fee/preview \
-H "Authorization: Bearer $TOKEN"
{
"hasFee": true,
"totalUsdCents": "1500",
"totalFormatted": "US$ 15.00",
"canAfford": true,
"missingUsdCents": "0",
"slices": [
{ "currency": "USDT", "nativeAmount": "12500000", "usdCents": "1250" },
{ "currency": "BRT", "nativeAmount": "1375", "usdCents": "250" }
],
"canRequest": true,
"blockers": []
}
| Campo | O que é |
|---|---|
hasFee |
false significa emissão gratuita, não erro de configuração a investigar |
totalUsdCents |
Preço em centavos de dólar. O preço é sempre em dólar |
slices |
De quais moedas o valor sairia e quanto de cada uma, na ordem em que serão consumidas. O usuário não precisa trocar de moeda antes: o sistema junta o valor sozinho |
canAfford |
false = a emissão seria recusada por saldo; missingUsdCents diz quanto falta |
> A tarifa é cobrada quando a pessoa pede o cartão (POST /cards/request), e não quando ele é aprovado. Quem é recusado pelo emissor recebe o dinheiro de volta — exatamente o valor que pagou, mesmo que a tarifa tenha mudado nesse meio-tempo.
Esta consulta é uma simulação: o saldo é lido no instante da pergunta, e o valor que vale é o conferido de novo na hora da cobrança.
6. Fase 2 — Documentos
São três, e todos obrigatórios:
documentType |
O que o titular envia |
|---|---|
IDENTITY_FRONT |
Foto da frente do documento físico, tirada na horizontal |
IDENTITY_BACK |
Foto do verso do documento físico, tirada na horizontal |
SELFIE_WITH_DOCUMENT |
Uma selfie do rosto. Apesar do nome do campo, o titular não precisa segurar o documento |
> Tem que ser foto tirada do documento físico. Documento digital não é aceito — CNH digital, e-Título, carteirinha em aplicativo, print de tela, foto da tela de outro aparelho e PDF são recusados na análise. A pessoa precisa estar com o documento em mãos e fotografá-lo.
> A foto do documento é na horizontal (paisagem). O documento ocupa a largura do enquadramento, inteiro, sem cortar cantos. Foto na vertical costuma sair com o documento pequeno e as bordas fora, e é a causa mais comum de devolução.
SELFIE_WITH_DOCUMENT** é só o rosto.** O nome do campo vem do emissor e engana: peça uma selfie comum, com o rosto enquadrado e bem iluminado, sem documento na mão. Instruir a pessoa a segurar o documento não invalida o envio, mas atrapalha o enquadramento do rosto.
> Apenas JPG e PNG, até 5 MB. PDF e HEIC são recusados pela API — o emissor não os aceita. Foto de iPhone costuma sair em HEIC: nos ajustes da câmera, "Mais compatível", ou converta antes de enviar.
Quem usa CNH como identidade fotografa a CNH física e envia em IDENTITY_FRONT e IDENTITY_BACK — a versão digital do aplicativo não serve. Comprovante de residência é documento do cadastro (KYC), não do cartão.
Frente e verso são envios separados porque cada um é analisado por conta própria: se o verso sair ilegível, a pessoa reenvia só o verso.
Estas regras são de análise, não de validação automática: um documento digital ou uma foto na vertical sobe com 201 e só volta como rejected na análise, com o motivo em rejectionReason. Mostrá-las na tela de captura é o que evita o ciclo de envio e devolução.
6.1 Situação documental
curl https://api.dexkey.finance/v1/cards/documents/requirements \
-H "Authorization: Bearer $TOKEN"
{
"requirements": [
{
"documentType": "IDENTITY_FRONT",
"status": "approved",
"rejectionReason": null,
"documentId": "fe84c527-d719-4372-b1c2-7ab1df757923",
"previewUrl": "https://s3.amazonaws.com/…?X-Amz-Signature=…",
"fileName": "rg-frente.jpg",
"submittedAt": "2026-09-01T12:11:26.285Z"
},
{
"documentType": "IDENTITY_BACK",
"status": "rejected",
"rejectionReason": "A foto corta o canto inferior direito do documento",
"documentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"previewUrl": "https://s3.amazonaws.com/…?X-Amz-Signature=…",
"fileName": "rg-verso.jpg",
"submittedAt": "2026-09-01T12:12:03.117Z"
},
{
"documentType": "SELFIE_WITH_DOCUMENT",
"status": "missing",
"rejectionReason": null,
"documentId": null,
"previewUrl": null,
"fileName": null,
"submittedAt": null
}
],
"hasPendingAdjustment": true
}
| Campo | O que é |
|---|---|
status |
missing → pending → approved ou rejected |
rejectionReason |
Motivo da recusa, escrito por quem analisou. É o texto que diz ao usuário o que corrigir |
previewUrl |
Link temporário (vale 1 hora) para a pessoa rever a foto que mandou. Pode vir null mesmo com documento enviado — nesse caso mostre a situação sem a miniatura, em vez de esconder o item |
hasPendingAdjustment |
Há documento recusado esperando reenvio |
6.2 Enviar um documento
Uma chamada só: o arquivo vai para a API, que confere o conteúdo, guarda o arquivo e registra o envio para análise.
curl -X POST https://api.dexkey.finance/v1/cards/documents/upload \
-H "Authorization: Bearer $TOKEN" \
-F "file=@rg-frente.jpg" \
-F "documentType=IDENTITY_FRONT" \
-F "userComment=Reenvio com a foto centralizada"
{
"id": "fe84c527-d719-4372-b1c2-7ab1df757923",
"documentType": "IDENTITY_FRONT",
"status": "pending",
"fileName": "rg-frente.jpg",
"userComment": "Reenvio com a foto centralizada",
"rejectionReason": null,
"createdAt": "2026-09-01T12:11:26.285Z",
"reviewedAt": null
}
O conteúdo é validado antes de subir: arquivo vazio, danificado por conversão, ou cujos bytes não batem com o tipo declarado (HEIC enviado como image/jpeg) é recusado com 400 CARD_DOCUMENT_CONTENT_INVALID e orientação de correção em message.
Um envio do mesmo tipo substitui o anterior, que passa a constar como superseded em vez de sumir.
6.3 Histórico
GET /cards/documents devolve todos os envios, incluindo os substituídos e os recusados.
7. Fase 3 — Solicitar o Cartão
curl -X POST https://api.dexkey.finance/v1/cards/request \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"holderDocumentType": "CPF",
"holderDocumentNumber": "12345678900",
"holderNationality": "BRA",
"termsVersion": "v1.0",
"termsSignatureHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}'
{
"message": "Solicitação de cartão criada com sucesso. Status 202 Accepted.",
"cardId": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"status": "pending"
}
| Campo | Regras |
|---|---|
holderDocumentType |
CPF, CNPJ, PASSPORT ou NATIONAL_ID |
holderDocumentNumber |
Só dígitos, sem pontuação |
holderNationality |
ISO 3166-1 alpha-3 (BRA, USA). Omitido, assume BRA |
termsVersion |
Versão dos termos apresentada ao usuário |
termsSignatureHash |
Hash do aceite. Gravado na auditoria junto com IP e user agent |
O que essa chamada faz, em ordem: confere os bloqueadores da fase 1 → exige os três documentos presentes → cobra a tarifa de emissão → abre a solicitação em análise → consome uma unidade da cota do participante → grava o aceite dos termos.
> Repetir é seguro. Enquanto houver solicitação em curso, a chamada devolve exatamente a mesma resposta da primeira, sem abrir uma segunda e sem cobrar de novo.
Recusas possíveis: 400 (telefone ou e-mail não confirmado, dados incompletos), 403 (cota esgotada, DexCard não liberado, recusa anterior definitiva), 422 (falta documento — CARD_DOCUMENTS_INCOMPLETE; saldo não cobre a tarifa — CARD_ISSUANCE_FEE_INSUFFICIENT_BALANCE).
8. Fase 4 — Acompanhar a Análise
curl https://api.dexkey.finance/v1/cards/application-status \
-H "Authorization: Bearer $TOKEN"
{
"steps": [
{ "step": "DOCUMENTS", "label": "Envio de documentos", "state": "DONE" },
{ "step": "COMPLIANCE_REVIEW", "label": "Análise documental", "state": "CURRENT" },
{ "step": "ISSUER_REVIEW", "label": "Análise do emissor", "state": "PENDING" },
{ "step": "CARD_ISSUED", "label": "Cartão emitido", "state": "PENDING" }
],
"currentStep": "COMPLIANCE_REVIEW",
"currentState": "CURRENT",
"reason": null,
"canReapply": false
}
Sem solicitação em curso, a resposta é 204 No Content, sem corpo. Não é erro.
state |
Significa |
|---|---|
DONE |
Etapa concluída |
CURRENT |
Onde a solicitação está agora |
PENDING |
Ainda não chegou |
ACTION_REQUIRED |
Documento devolvido. É a única situação em que o usuário precisa agir — leve-o à fase 2 |
FAILED |
A solicitação parou definitivamente. reason traz o motivo |
O acompanhamento volta uma etapa quando um documento é devolvido: currentStep retorna para DOCUMENTS, porque a próxima coisa a acontecer é o reenvio. É o comportamento correto — não trate como inconsistência nem trave a tela na etapa anterior.
canReapply diz se, após uma recusa, o usuário pode tentar de novo. Recusa por fraude é definitiva.
Não existe aviso automático (webhook) de eventos de cartão. O andamento é descoberto consultando este endpoint: a cada poucos minutos enquanto a tela estiver aberta, e sempre que a pessoa voltar ao aplicativo. A emissão leva de algumas horas a alguns dias úteis.
9. Fase 5 — Cartão Ativo
9.1 Listar e detalhar
curl https://api.dexkey.finance/v1/cards/my-cards -H "Authorization: Bearer $TOKEN"
curl https://api.dexkey.finance/v1/cards/{id} -H "Authorization: Bearer $TOKEN"
{
"id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"status": "active",
"lastFour": "4821",
"expirationDate": "07/29",
"balanceUsdCents": "23450",
"pendingHoldUsdCents": "1200",
"termsAccepted": true,
"termsAcceptedAt": "2026-09-01T12:20:00.000Z",
"activatedAt": "2026-09-03T09:14:00.000Z",
"cancelledAt": null,
"createdAt": "2026-09-01T12:20:00.000Z",
"frozenBy": null,
"frozenAt": null,
"freezeReason": null,
"canUnfreeze": false
}
status |
Significa |
|---|---|
pending · activating |
Emissão em curso |
active |
Pronto para uso e recarga |
frozen |
Congelado — pelo titular ou pela equipe (veja frozenBy) |
blocked |
Bloqueado permanentemente |
cancelled |
Cancelado |
rejected |
Titular recusado pelo emissor; cartão nenhum chegou a existir |
9.2 Saldo
curl "https://api.dexkey.finance/v1/cards/{id}/balance?displayCurrency=BRL" \
-H "Authorization: Bearer $TOKEN"
{
"availableUsdCents": "23450",
"pendingHoldUsdCents": "1200",
"approximateValue": { "currency": "BRL", "amount": "128975", "exchangeRate": "5.49800000" }
}
displayCurrency aceita BRL ou EUR, e é opcional — sem ele vem só o dólar.
> availableUsdCents** já é o saldo que a pessoa pode gastar.** As compras aprovadas e ainda não cobradas pelo estabelecimento já foram descontadas dele. pendingHoldUsdCents mostra quanto está nessa situação, apenas como informação — não subtraia um do outro, ou a tela mostrará um saldo menor que o real.
O valor aproximado é apoio visual e nunca base de operação: quem decide quanto sai é sempre o valor em dólar.
9.3 Limites
curl https://api.dexkey.finance/v1/cards/{id}/limits -H "Authorization: Bearer $TOKEN"
{
"perTransactionUsdCents": "500000",
"dailyUsdCents": "1000000",
"monthlyUsdCents": "5000000",
"maxVelocityPerMinute": 5
}
Hoje apenas maxVelocityPerMinute é verificado antes de uma operação. Os três valores monetários são configuração exibida: nenhuma operação é recusada por causa deles. Exiba-os como informação, não como validação de formulário.
9.4 Credenciais do cartão (PAN, CVV, validade)
curl https://api.dexkey.finance/v1/cards/{id}/secure-credentials \
-H "Authorization: Bearer $TOKEN"
Duas formas de entrega, e a integração precisa tratar as duas:
{ "deliveryMode": "hosted", "url": "https://provedor…/card/…", "expiresAt": "2026-09-15T14:35:00.000Z" }
{
"deliveryMode": "direct",
"pan": "5375420000004821",
"securityCode": "123",
"expiryMonth": "07",
"expiryYear": "2029",
"expirationDate": "07/29"
}
deliveryMode |
O que fazer |
|---|---|
hosted |
Abra a url do provedor numa janela interna do app (webview) ou iframe. Os dados do cartão não passam pelo seu sistema |
direct |
Os dados vêm na resposta. Exiba só quando a pessoa tocar para ver, não grave em log, não guarde em cache e não salve em lugar nenhum |
Todo acesso a este endpoint é gravado em auditoria imutável com o IP de origem. Exibir o PAN coloca sua aplicação no escopo PCI-DSS — prefira hosted quando o provedor oferecer.
GET /cards/{id}/wallet-provisioning devolve o mesmo conteúdo no formato que Apple Wallet e Google Wallet esperam, e só funciona quando a entrega é direct.
10. Fase 6 — Recarga
Três chamadas, nesta ordem: valor mínimo → simulação → confirmação. Moedas de origem aceitas: BRT, USDC e USDT.
10.1 O valor mínimo, antes de a pessoa digitar
curl "https://api.dexkey.finance/v1/cards/load/limits?sourceCurrency=USDT" \
-H "Authorization: Bearer $TOKEN"
{
"sourceCurrency": "USDT",
"minimumSourceAmount": "1156",
"minimumUsdCents": "1000",
"exchangeRate": "1.00000000",
"feeFixedSourceAmount": "150",
"feePercentageRate": "0.5"
}
minimumSourceAmount vem na **mesma unidade de **sourceAmount (centésimos) e já inclui a taxa vigente. Use este número para abrir a tela e para validar o campo de valor.
Não escreva um mínimo fixo na tela ("a partir de 10 USDT"). O mínimo muda junto com a taxa: se a taxa subir, a pessoa digita o valor anunciado e a recarga é recusada; se cair, ela recebe no cartão menos do que esperava. Pergunte o número a cada abertura de tela.
A cotação devolvida aqui é só indicativa. A que vale na operação é a da simulação (passo 10.2).
10.2 Simulação
curl -X POST https://api.dexkey.finance/v1/cards/load/preview \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "sourceCurrency": "USDT", "sourceAmount": "10000" }'
{
"sourceCurrency": "USDT",
"sourceAmount": "10000",
"grossUsdCents": "10000",
"chargedFeeSourceAmount": "200",
"chargedFeeUsdCents": "200",
"netLoadedUsdCents": "9800",
"exchangeRate": "1.00000000",
"quoteToken": "eyJhbGciOi…",
"expiresInSeconds": 120,
"limits": { "minimumSourceAmount": "1156", "minimumUsdCents": "1000" }
}
> Não envie cardId neste corpo. Campo desconhecido é rejeitado com 400. O cartão só entra na confirmação.
| Campo | O que é |
|---|---|
grossUsdCents |
O que sai da conta DEX, em dólar |
chargedFeeUsdCents / chargedFeeSourceAmount |
A taxa, nos dois lados |
netLoadedUsdCents |
O que entra no cartão. É este número que o usuário confere |
quoteToken |
Cotação travada por 120 segundos |
10.3 Confirmação
curl -X POST https://api.dexkey.finance/v1/cards/load/confirm \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"cardId": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"sourceCurrency": "USDT",
"sourceAmount": "10000",
"quoteToken": "eyJhbGciOi…",
"pin": "1234"
}'
{
"message": "Recarga concluída",
"loadId": "7b1f9c52-3f6a-4f2c-8f0b-2d5e7a9c1b34",
"status": "completed",
"netLoadedUsdCents": "9800",
"chargedFeeUsdCents": "200"
}
status |
Significa |
|---|---|
completed |
Saldo já disponível no cartão |
awaiting_approval |
Retida para análise da nossa equipe — alguns participantes pedem essa conferência. O valor já saiu da conta DEX e ainda não entrou no cartão |
processing |
Ainda não se sabe se o provedor aplicou a recarga. Consulte o status |
failed |
Recusada. O valor e a taxa já voltaram para a conta DEX |
> O 202 é o caso que exige mais cuidado. Ele vem com CARD_INTEGRATION_OUTCOME_UNKNOWN e significa que o provedor não confirmou nem negou: a recarga pode ter sido aplicada. Não repita a operação — consulte GET /cards/{id}/load/{loadId} até o status sair de processing. Uma rotina automática confere com o provedor e resolve sozinha.
> Esta chamada não tem proteção contra envio repetido. Não existe cabeçalho de idempotência aqui: se a requisição der timeout e você reenviar, o sistema entende como uma segunda recarga e debita de novo. Diante de qualquer resposta inconclusiva, consulte o status — nunca reenvie.
10.4 Status de uma recarga
curl https://api.dexkey.finance/v1/cards/{id}/load/{loadId} \
-H "Authorization: Bearer $TOKEN"
{
"id": "7b1f9c52-3f6a-4f2c-8f0b-2d5e7a9c1b34",
"cardId": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"sourceCurrency": "USDT",
"sourceAmount": "10000",
"amountUsdCents": "9800",
"chargedFeeUsdCents": "200",
"exchangeRate": "1.00000000",
"status": "completed",
"createdAt": "2026-09-15T14:30:00.000Z"
}
11. Fase 6 — Resgate
Devolve saldo do cartão para a conta DEX, na moeda escolhida.
curl -X POST https://api.dexkey.finance/v1/cards/redeem/preview \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "cardId": "a0eebc99-…", "amountUsdCents": "5000", "targetCurrency": "USDT" }'
{
"cardId": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"amountUsdCents": "5000",
"chargedFeeUsdCents": "100",
"targetCurrency": "USDT",
"grossTargetAmount": "5000",
"chargedFeeTargetAmount": "100",
"targetAmount": "4900",
"exchangeRate": "1.00000000",
"usdToTargetRate": "1.00000000",
"limits": { "minimumUsdCents": "1000", "maximumUsdCents": "21105", "availableUsdCents": "23450" }
}
A confirmação é o mesmo corpo **mais o **pin, em POST /cards/redeem/confirm.
> O máximo resgatável é uma porcentagem do saldo, então ele cai quando o saldo cai. Se a pessoa fizer uma compra entre a simulação e a confirmação, maximumUsdCents diminui e a confirmação é recusada — o sistema não resgata um valor menor por conta própria. Trate 422 CARD_REDEEM_ABOVE_PROVIDER_CEILING como "refaça a simulação", e não como falha do sistema.
status na confirmação |
Significa |
|---|---|
completed |
Valor já creditado na conta DEX |
pending · provider_confirmed |
Ainda em andamento — consulte de novo em instantes |
failed |
Nada se moveu |
settlement_failed |
O valor saiu do cartão e ainda não entrou na conta DEX. Uma rotina automática recoloca o crédito sozinha. O usuário não deve repetir a operação — avise que já está sendo regularizado |
12. Fase 6 — Congelar e Descongelar
curl -X POST https://api.dexkey.finance/v1/cards/{id}/freeze -H "Authorization: Bearer $TOKEN"
curl -X POST https://api.dexkey.finance/v1/cards/{id}/unfreeze -H "Authorization: Bearer $TOKEN"
{
"id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"status": "frozen",
"frozenBy": "HOLDER",
"frozenAt": "2026-09-15T14:32:00.000Z",
"freezeReason": null,
"canUnfreeze": true,
"message": "Cartão congelado com sucesso"
}
Congelar bloqueia novas compras imediatamente, sem encerrar o cartão: número, validade e saldo continuam os mesmos, e o próprio titular desfaz quando quiser.
> Só quem congelou pode descongelar. Se o bloqueio foi aplicado pela nossa equipe, a chamada devolve 403 CARD_FREEZE_ADMIN_LOCKED e só o suporte reverte. Decida pelo campo canUnfreeze se mostra o botão de descongelar ou o contato do suporte — o status sozinho não diz quem congelou.
Um 503 significa que o emissor está fora do ar e que nada foi alterado: o cartão continua exatamente como estava. Não mostre o cartão como congelado nesse caso.
13. Fase 6 — Extrato
curl "https://api.dexkey.finance/v1/cards/{id}/transactions?limit=20&offset=0&operation=PURCHASE" \
-H "Authorization: Bearer $TOKEN"
{
"entries": [
{
"id": "c9d8e7f6-a5b4-4c3d-9e2f-1a0b9c8d7e6f",
"operation": "PURCHASE",
"status": "COMPLETED",
"description": "SPOTIFY BR",
"beneficiary": "SPOTIFY BR",
"amountUsdCents": "1990",
"originalCurrency": "BRL",
"originalAmount": "10940",
"occurredAt": "2026-09-14T20:11:00.000Z",
"declineReason": null,
"declineReasonCode": null,
"exchangeRate": "5.49800000",
"usdToOriginalRate": "5.49800000",
"feeUsdCents": null,
"feeOriginalAmount": null
}
],
"total": 134,
"limit": 20,
"offset": 0
}
Compras, recargas e resgates vêm na mesma lista, do mais recente para o mais antigo.
| Filtro | Valores |
|---|---|
operation |
PURCHASE, CARD_LOAD, CARD_REDEEM, WITHDRAWAL, REFUND, REVERSAL, ADJUSTMENT |
status |
COMPLETED, PROCESSING, DECLINED, CANCELLED, REVERSED |
currency |
BRT, USDC, USDT |
startDate / endDate |
ISO-8601 |
search |
Busca por nome do estabelecimento ou pela moeda (até 120 caracteres) |
limit / offset |
limit máximo 100, padrão 20 |
GET /cards/{id}/transactions/{txId}devolve uma linha específica, no mesmo formato da lista.GET /cards/{id}/statement/exportdevolve o extrato em PDF (application/pdf), aceitando os mesmos filtros. Se o período tiver mais de mil movimentos, o PDF traz os mais recentes.
14. Erros Desta Área
| Código | HTTP | Significa |
|---|---|---|
CARD_CONFIG_MODULE_DISABLED |
403 | DexCard não liberado para o participante do usuário |
CARD_CONFIG_LOAD_DISABLED / CARD_CONFIG_REDEEM_DISABLED |
403 | Recarga ou resgate desativados para o participante |
CARD_NOT_ELIGIBLE |
403 | Há impedimentos — consulte GET /cards/eligibility para saber quais |
CARD_QUOTA_EXCEEDED |
403 | Cota de emissões do participante esgotada |
CARD_POLICY_CANNOT_REAPPLY |
403 | Recusa anterior definitiva |
CARD_AUTHZ_ACCESS_DENIED |
403 | O cartão é de outro titular |
CARD_FREEZE_ADMIN_LOCKED |
403 | Bloqueio da equipe; só o suporte reverte |
CARD_RESOURCE_NOT_FOUND |
404 | Cartão, recarga ou movimento inexistente |
CARD_DOCUMENT_CONTENT_INVALID |
400 | Arquivo vazio, danificado, ou de formato diferente do declarado |
CARD_DOCUMENTS_INCOMPLETE |
422 | Falta algum dos três documentos |
CARD_HOLDER_DATA_INCOMPLETE |
422 | Falta perfil, endereço ou data de nascimento |
CARD_ISSUANCE_FEE_INSUFFICIENT_BALANCE |
422 | Saldo não cobre a tarifa de emissão |
CARD_STATE_NOT_ACTIVE |
400 | O cartão não está ativo para a operação |
CARD_FREEZE_INVALID_STATUS |
409 | Congelar o que já está congelado, ou descongelar o que não está |
CARD_INVALID_PIN |
401 | PIN incorreto |
CARD_QUOTE_EXPIRED / CARD_QUOTE_MISMATCH |
422 | Cotação vencida ou diferente da simulada — simule de novo |
CARD_AMOUNT_BELOW_FEE |
422 | Valor menor que a taxa aplicável |
CARD_AMOUNT_BELOW_PROVIDER_MINIMUM |
422 | Abaixo do mínimo do provedor |
CARD_LOAD_INSUFFICIENT_BALANCE |
422 | Saldo da conta DEX não cobre a recarga |
CARD_REDEEM_INSUFFICIENT_BALANCE |
422 | Saldo do cartão não cobre o resgate |
CARD_REDEEM_ABOVE_PROVIDER_CEILING |
422 | Acima do teto percentual do saldo |
CARD_VELOCITY_LIMIT_EXCEEDED |
429 | Operações por minuto acima do permitido |
CARD_INTEGRATION_OUTCOME_UNKNOWN |
202 | Não se sabe se a operação foi aplicada — consulte o status, não repita |
CARD_INTEGRATION_FABRIC_UNAVAILABLE |
503 | Emissor fora do ar. Nada foi alterado |
CARD_EXCHANGE_RATE_UNAVAILABLE |
503 | Nenhum provedor de cotação respondeu |
CARD_CREDENTIALS_UNAVAILABLE |
422 | O provedor não devolveu as credenciais completas |
Todo erro segue o formato padrão da API. Trate pelo errorCode, nunca pelo texto.
15. Detalhes de Contrato que Importam na Integração
- Não há aviso automático (webhook) de cartão. Emissão, recarga, resgate e compras são descobertos por consulta. Planeje quando perguntar:
application-statusdurante a análise,my-cardsebalanceao abrir a tela,load/{loadId}enquanto uma recarga estiver sem desfecho. - Recarga e resgate exigem o PIN do usuário. Não dá para fazer essas duas operações apenas de servidor para servidor: é preciso uma tela onde a pessoa digita o PIN na hora.
- Não existe
Idempotency-Keynesta API. Reenviarload/confirmcria uma segunda recarga. Diante de qualquer resposta inconclusiva, consulte o status em vez de reenviar. - Todo valor é inteiro dentro de aspas.
…UsdCentsem centavos de dólar;…SourceAmounte…TargetAmountem centésimos da moeda. Nunca converta um no outro por conta própria — o servidor já devolve os dois. - A tarifa de emissão é cobrada no pedido, não na aprovação. Recusa gera estorno do valor pago.
availableUsdCents** já vem descontado** das compras aprovadas e ainda não cobradas. Não subtraiapendingHoldUsdCentsdele.- Cancelar cartão não é operação do titular. Não existe endpoint de cancelamento nesta API — o pedido passa pelo suporte.
- Use exatamente os caminhos documentados. Qualquer coisa depois de
/cards/que não esteja nesta página é lida como identificador de cartão:/cards/qualquer-coisaviraGET /cards/{id}e devolve400por não ser um identificador válido.

