Checkout Transparente

Gerar cobrança Cartão 3DS

Para gerar uma cobrança no cartão de crédito com autenticação 3DS é necessário fazer a autenticação com o SDK @validapay/3ds (Os detalhes podem ser consultados em Autenticação do cartão). Depois disso, o frontend tokeniza o cartão com o SDK @validapay/tokenize (Tokenização de cartão). Esta etapa garante que os dados sensíveis (PAN e CVV) nunca passam pelo seu servidor. O SDK de tokenização retorna o cardToken e o deviceId usados na cobrança. O fluxo autentica o portador no banco emissor antes da cobrança, transferindo a responsabilidade de chargeback por fraude do lojista para o emissor (liability shift).

POST/v1/charges
Base URL Produção:https://api.validapay.com.br
Base URL Sandbox:https://sandbox.validapay.com.br

Visão geral

ℹ️ Esta rota é a autorização (após o 3DS). A autenticação do comprador com o banco acontece no navegador via authenticate(...) antes de chamar a API. O paymentMethod continua creditcard — a ValidaPay não usa um método threeDs separado.

O fluxo completo tem quatro passos:

  1. Tokenizar o dispositivocollectDevice(...) devolve o deviceId.
  2. Autenticar o compradorauthenticate(...) no @validapay/3ds abre o desafio do banco (quando necessário) e devolve authenticationId (e opcionalmente cardId).
  3. Tokenizar o cartãotokenize(...) com o mesmo authentication, gerando um cardToken de 5 minutos vinculado ao cartão autenticado.
  4. Autorizar o pagamento (esta rota)POST /v1/charges com paymentMethod: "creditcard", cardToken, deviceId e authentication.

Para cobrança sem 3DS, use Gerar cobrança Cartão.

Campos do cartão

  • cardToken (obrigatório) — vem de tokenize(...) no pacote @validapay/tokenize, gerado depois do authenticate. Vale 5 minutos, é de uso único e só funciona na conta que o gerou.
  • deviceId (obrigatório) — vem de collectDevice(...). Identifica o dispositivo e alimenta o antifraude.
  • authentication (obrigatório nesta sessão) — resultado de authenticate(...) no @validapay/3ds. Envie exatamente o objeto devolvido:
    • authenticationId (obrigatório)
    • cardId (opcional)

SEU_ID_PUBLICO está no painel em Gerenciamento > Minha Conta > Id Público. É público: pode ficar no código da página.

O valor enviado em amount (ou o total resolvido via items) deve ser o mesmo amount usado no authenticate.

Detalhes do fluxo no front-end: Autenticação do dono do cartão (3DS) e Tokenização de cartão.

Idempotência

Envie externalId como chave de idempotência do pedido. Se duas cobranças forem enviadas com o mesmo valor, a segunda é recusada com 409 DUPLICATE_CHARGE e o corpo traz o chargeId da cobrança original em error.details.chargeId.

⚠️ O cardToken expira em 5 minutos. A idempotência não devolve a resposta da cobrança original: a segunda chamada com o mesmo externalId é recusada com 409 DUPLICATE_CHARGE e o cartão não é reprocessado. Para cobrar de novo, gere um cardToken novo e use outro externalId.

Use externalTxid só para identificar a loja, o caixa ou o vendedor. Ele não entra na idempotência.

Correlação com o pedido: use externalId — ele é persistido e devolvido. O campo metadata é aceito nesta rota, mas não é gravado na cobrança nem volta no webhook.

Produto, valor e parcelas

  • Envie items com os produtos ou amount para uma cobrança avulsa — nunca os dois.
  • O valor autenticado no 3DS deve bater com o valor cobrado.
  • Dá para parcelar com installments e, se quiser, repassar as taxas ao comprador.

Notificações por e-mail

Use notifications para escolher quais e-mails saem nesta cobrança:

  • oneoff.payment.success — confirmação ao comprador quando o cartão é aprovado
  • oneoff.payment.failed — aviso ao comprador quando o cartão é recusado
  • new.sale — avisa você (vendedor) da venda paga

Eventos destinados ao comprador exigem customer.email.

Resposta

  • 200 — cartão aprovado: success: true, chargeId, customerId, status: "paid".
  • 402 — cartão recusado pelo banco ou adquirente (inclui falha de autenticação 3DS): success: false, status: "failed" e o motivo em error (texto).

Erros comuns

  • 400 MISSING_CARD_DATA — faltou o cardToken
  • 400 CARD_TOKEN_EXPIRED — passou dos 5 minutos: gere outro na página
  • 404 CARD_TOKEN_NOT_FOUND — token inexistente ou de outra conta
  • 404 PRICE_NOT_FOUND — o priceId de algum item não existe
  • 409 DUPLICATE_CHARGE — o externalId já foi usado; use o chargeId retornado
  • 402 — pagamento recusado (card_declined, failed_authentication, insufficient_funds, etc.)

No front-end, erros do SDK 3DS (THREE_DS_FAILED, THREE_DS_TIMEOUT, etc.) ocorrem antes desta chamada — veja Autenticação do dono do cartão (3DS).

Cartões de teste (sandbox)

Em conta de sandbox nenhuma cobrança é cobrada de verdade — o número digitado na tokenização define o resultado:

  • 4111111111111111 — aprovado
  • 4000000000000002 — recusado (card_declined)
  • 4000000000000004 — saldo insuficiente (insufficient_funds)
  • 4000000000000006 — cartão expirado (expired_card)
  • 4000000000000008 — CVV inválido (invalid_cvv)
  • 4000000000000010 — suspeita de fraude (fraud_suspected)

Qualquer outro número de 16 dígitos é aprovado. Em produção o número não muda nada: quem decide é o banco emissor.

Boas práticas

  • Sempre autentique e tokenização na sequência, imediatamente antes desta rota. O cardToken expira em 5 minutos.
  • Passe o mesmo authentication ao tokenize e à cobrança — assim a ValidaPay guarda o cartão que o banco autenticou (útil em assinaturas).
  • Envie deviceId sempre.
  • Não confunda falha no SDK com 402. Se authenticate falhar, não chame esta rota.
  • Não use metadata para correlacionar o pedido nesta rota — use externalId.

Authorizations

bearer

Authorization

string obrigatório

Cabeçalho de autenticação Bearer no formato Bearer {{token}} onde {{token}} é o seu token OAuth2.

Escopos requeridos

charges/write

Body

application/json

Content-Type:application/json
JSON
{
  "paymentMethod": "creditcard",
  "externalId": "pedido-2026-0001",
  "externalTxid": "loja-01-caixa-03",
  "customer": {
    "name": "João da Silva",
    "email": "joao@email.com",
    "documentNumber": "12345678901",  
    "metadata": { "origem": "site" },
    "phone": "+5511999998888",  
    "cep": "01310100",
    "address": {
      "type": "BILLING",
      "street": "Av. Paulista",
      "number": "1000",
      "complement": "Apto 52",
      "neighborhood": "Bela Vista",
      "city": "Sao Paulo",
      "state": "SP",
      "zipCode": "01310100",
      "country": "BR",
      "cityCode": "3550308"
    }
  },
  "cardToken": "ctk_9f8s7d6f5g4h3j2k1l0",
  "deviceId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "authentication": {
    "authenticationId": "9WDHbW3Mipl6pFQ2LnM2",
    "cardId": "card_p7s6je7w90uomjkgn1siy2xkw"
  },
  "amount": 10.00,
  "items": [
    {
      "priceId": "price_abc123",
      "quantity": 1,
      "isOrderBump": false
    }
  ],
  "installments": 1,
  "freeInstallments": 1,
  "passFeesToCustomer": false,
  "couponCode": "PROMO10",
  "metadata": { "referencia": "pedido-001" },
  "description": "Assinatura Premium",
  "allowedPaymentMethods": ["pix", "creditcard"],
  "nfConfigId": "nfc_1788364755079_psuecwgdc",
  "notifications": ["oneoff.payment.success", "oneoff.payment.failed", "new.sale"],
  "discounts": [
    {
      "type": "percentage",
      "value": 10,
      "paymentMethod": "creditcard",
      "couponCode": "PROMO10"
    }
  ],
  "cartId": "cart_2026_0001",
  "productId": "prod_123456_example"
}

Schema

paymentMethodstringobrigatório
Forma de pagamento (fixo: creditcard). Com 3DS o método continua creditcard
Valores aceitos:pixcreditcardboletopix_automatico
customerobjectobrigatório
Dados do comprador
cardTokenstringobrigatório
Token do cartão, gerado no navegador pelo SDK @validapay/tokenize depois do authenticate. Vale 5 minutos e só funciona na conta que o gerou
deviceIdstringobrigatório
Identificação do dispositivo do comprador, devolvida pelo collectDevice. Envie sempre
authenticationobjectobrigatório
Resultado de authenticate(...) no pacote @validapay/3ds. Envie exatamente o que o SDK devolveu
externalIdstringopcional
Identificador único do pedido no seu sistema; usado como idempotencyKey (evita cobrança duplicada)
Regra:até 100 caracteres
externalTxidstringopcional
Identifica a loja, o caixa ou o vendedor responsável pela cobrança
Regra:até 100 caracteres
amountnumberopcional
Valor total em reais para cobrança avulsa. Ignorado quando items é enviado. Deve ser o mesmo amount usado no authenticate
Regra:0.01
itemsarray[1]opcional
Produtos da compra (ou use amount para cobrança avulsa)
installmentsnumberopcional
Parcelas no cartão, de 1 a 12
Regra:1 a 12
freeInstallmentsnumberopcional
Parcelas sem juros para o comprador, de 0 a 12
Regra:0 a 12
passFeesToCustomerbooleanopcional
Repassa a taxa de parcelamento ao comprador
couponCodestringopcional
Código de cupom de desconto
metadataobjectopcional
Aceito mas NÃO persistido nesta rota; para correlacionar o pedido use externalId
descriptionstringopcional
Descrição livre da cobrança
allowedPaymentMethodsarray[2]opcional
Métodos aceitos quando a cobrança vira link
Valores aceitos:pixcreditcardboletopix_automatico
nfConfigIdstringopcional
Emite nota fiscal com esta configuração. Exige customer.address
notificationsarray[3]opcional
E-mails disparados nesta cobrança
Valores aceitos:oneoff.pix.generatedoneoff.boleto.generatedoneoff.payment.successoneoff.payment.failednew.saleseller.charge.pending
discountsarray[1]opcional
Descontos aplicados a cobrança
cartIdstringopcional
Agrupa numa única compra as assinaturas criadas juntas e deduplica o evento de conversão
productIdstringopcional
Cria a cobrança a partir de um produto
Regra:^prod_

Headers

Content-Typeopcional
application/json
const url = 'https://sandbox.validapay.com.br/v1/charges';

const options = {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer {{token}}',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
  "paymentMethod": "creditcard",
  "externalId": "pedido-2026-0001",
  "externalTxid": "loja-01-caixa-03",
  "customer": {
    "name": "João da Silva",
    "email": "joao@email.com",
    "documentNumber": "12345678901",  
    "metadata": { "origem": "site" },
    "phone": "+5511999998888",  
    "cep": "01310100",
    "address": {
      "type": "BILLING",
      "street": "Av. Paulista",
      "number": "1000",
      "complement": "Apto 52",
      "neighborhood": "Bela Vista",
      "city": "Sao Paulo",
      "state": "SP",
      "zipCode": "01310100",
      "country": "BR",
      "cityCode": "3550308"
    }
  },
  "cardToken": "ctk_9f8s7d6f5g4h3j2k1l0",
  "deviceId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "authentication": {
    "authenticationId": "9WDHbW3Mipl6pFQ2LnM2",
    "cardId": "card_p7s6je7w90uomjkgn1siy2xkw"
  },
  "amount": 10.00,
  "items": [
    {
      "priceId": "price_abc123",
      "quantity": 1,
      "isOrderBump": false
    }
  ],
  "installments": 1,
  "freeInstallments": 1,
  "passFeesToCustomer": false,
  "couponCode": "PROMO10",
  "metadata": { "referencia": "pedido-001" },
  "description": "Assinatura Premium",
  "allowedPaymentMethods": ["pix", "creditcard"],
  "nfConfigId": "nfc_1788364755079_psuecwgdc",
  "notifications": ["oneoff.payment.success", "oneoff.payment.failed", "new.sale"],
  "discounts": [
    {
      "type": "percentage",
      "value": 10,
      "paymentMethod": "creditcard",
      "couponCode": "PROMO10"
    }
  ],
  "cartId": "cart_2026_0001",
  "productId": "prod_123456_example"
})
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

Response Examples

200
JSON
{
  "success": true,
  "customerId": "cus_xxx",
  "chargeId": "cha_abc123",
  "status": "paid"
}
402
JSON
{
    "success": false,
    "chargeId": "cha_1784065113577_5dw2oyfic",
    "status": "failed",
    "error": "Cartão recusado"
}
400MISSING_CARD_DATA
JSON
{
  "error": {
    "message": "cardToken é obrigatório na cobrança com cartão; gere um com o SDK @validapay/tokenize",
    "code": "MISSING_CARD_DATA"
  }
}
404PRICE_NOT_FOUND
JSON
{
  "error": {
    "message": "Preço não encontrado",
    "code": "PRICE_NOT_FOUND"
  }
}
409DUPLICATE_CHARGE
JSON
{
  "error": {
    "message": "Cobrança duplicada: já existe uma cobrança para este pedido",
    "code": "DUPLICATE_CHARGE",
    "details": {
      "chargeId": "cha_1784065113577_5dw2oyfic"
    },
    "timestamp": "2026-07-14T21:39:36.322Z"
  }
}