Pular para o conteúdo
BLINKYPAYdocs
PTEN
Ir para o painel

Pagamentos com cartão

Aceite Visa, Mastercard, American Express, Elo, Hipercard e as outras grandes bandeiras por uma página de pagamento hospedada pela BlinkyPay — nenhum dado de cartão passa pelos seus servidores, e o 3D Secure é tratado automaticamente.

#O fluxo, de relance

text
1. POST /v1/payments  ──────▶  a BlinkyPay devolve transactionId + status WAITING_PAYMENT
2. GET  /v1/payments/{id} ───▶  em ~1 s, o cardRedirectUrl vem preenchido
3. Redirecione o cliente (ou abra num iframe) para o cardRedirectUrl
4. O cliente digita os dados do cartão e conclui o desafio 3DS na página segura da BlinkyPay
5. O cliente volta para o seu returnUrl (com sucesso ou com falha)
6. O webhook payment.completed (ou payment.failed) confirma o resultado — confie no webhook, não no redirect

Por que um redirect? Ele mantém os dados do portador do cartão totalmente fora da sua infraestrutura. A sua aplicação — backend ou frontend — nunca vê PAN, CVV nem validade. O processador da BlinkyPay cuida do 3DS, da tokenização e da análise antifraude do nosso lado.

#1. Criar a cobrança

Endpoint POST /v1/payments

bash
curl -X POST https://pay.blinkyapi.com/v1/payments \
  -H "apikey: $BLINKYPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 8990,
    "currency": "EUR",
    "paymentMethods": ["CREDIT_CARD"],
    "customerName": "João Costa",
    "customerEmail": "joao@example.com",
    "metadata": {
      "orderId": "ORD-9821",
      "returnUrl": "https://shop.example.com/orders/9821/return"
    },
    "idempotencyKey": "ORD-9821"
  }'
CampoObservação
amountMenor unidade (centavos). 8990 = € 89,90.
currencyBRL, EUR ou USD (outras moedas sob pedido).
paymentMethods["CREDIT_CARD"]
metadata.returnUrlPara onde mandar o cliente quando ele terminar (com sucesso ou com falha).
customerEmailMuito recomendado — usado no comprovante, nos sinais de fraude e como prova na contestação de chargeback.

Resposta 201 Created

json
{
  "id": "b2c3d4e5-f6a7-4890-9bcd-ef0123456789",
  "status": "WAITING_PAYMENT",
  "amount": 8990,
  "currency": "EUR",
  "paymentMethods": ["CREDIT_CARD"],
  "createdAt": "2026-04-25T15:50:11.000Z"
}

#2. Redirecionar o cliente

Consulte a transação quando o cardRedirectUrl estiver preenchido (normalmente em menos de 1 s):

bash
curl https://pay.blinkyapi.com/v1/payments/b2c3d4e5-f6a7-4890-9bcd-ef0123456789 \
  -H "apikey: $BLINKYPAY_API_KEY"
json
{
  "id": "b2c3d4e5-f6a7-4890-9bcd-ef0123456789",
  "status": "WAITING_PAYMENT",
  "amount": 8990,
  "currency": "EUR",
  "cardRedirectUrl": "https://checkout.pay.blinkyapi.com/c/b2c3d4e5-f6a7-4890-9bcd-ef0123456789",
  "createdAt": "2026-04-25T15:50:11.000Z"
}

Mande o cliente para o cardRedirectUrl:

html
<a href="{{ cardRedirectUrl }}">Pagar com cartão</a>

Ou faça um 302 Found no servidor:

js
res.redirect(303, transaction.cardRedirectUrl);

Quando o cliente conclui o fluxo (ou desiste), ele volta para o metadata.returnUrl que você informou — com ?transactionId=...&status=... no final. Não confie nesses parâmetros de query. Eles são só informativos — espere o webhook antes de liberar o pedido.

#3. Confirmar pelo webhook

json
{
  "event": "payment.completed",
  "data": {
    "transactionId": "b2c3d4e5-f6a7-4890-9bcd-ef0123456789",
    "amount": 8990,
    "status": "APPROVED",
    "previousStatus": "PROCESSING",
    "paidWith": "CREDIT_CARD",
    "providerFee": 280,
    "platformFee": 90,
    "netAmount": 8620,
    "occurredAt": "2026-04-25T15:52:34.000Z"
  }
}

No cartão, o status de sucesso é APPROVED (não PAID). Os dois eventos chegam como payment.completed, então um handler só cobre os dois.

Recusas de cartão chegam como payment.failed, com data.status ∈ REFUSED, EXPIRED, CANCELLED. Os motivos de recusa mais comuns (quando o emissor informa) vêm repetidos em data.declineReason.

#Ciclo de vida

text
WAITING_PAYMENT  ──▶  PROCESSING  ──▶  APPROVED    ✓ libere o pedido
                                  ──▶  REFUSED     o emissor recusou
                                  ──▶  CANCELLED   o cliente desistiu
                                  ──▶  EXPIRED     o link de redirect venceu (24h)

Depois da liquidação (D+1 a D+30, conforme a bandeira e o seu contrato), você também pode ver:

text
APPROVED  ──▶  CHARGEBACK   o emissor abriu um chargeback
APPROVED  ──▶  DISPUTE      o portador do cartão abriu uma disputa
APPROVED  ──▶  REFUNDED     você (ou a BlinkyPay) fez um reembolso

Cada um dispara um webhook, para você sincronizar o estado do pedido.

#Cartões de teste

No sandbox, a página de redirect aceita estes números determinísticos (qualquer validade futura, qualquer CVV):

NúmeroResultado
4111 1111 1111 1111Sempre APPROVED
4000 0000 0000 0002Sempre REFUSED — recusa genérica
4000 0000 0000 0069Sempre REFUSED — cartão vencido
4000 0000 0000 9995Sempre REFUSED — saldo insuficiente
4000 0000 0000 3220Dispara o desafio 3DS e depois APPROVED

Veja a lista completa em Sandbox.

#Perguntas frequentes

P: Dá para manter o cliente no meu domínio? R: Na fase 2 vamos lançar um widget incorporável (iframe + tokenizador) que mantém a sua marca e continua deixando os dados do portador do cartão fora da sua infraestrutura. Por enquanto: redirect hospedado.

P: Vocês aceitam cartão salvo? R: Sim, mas isso exige que o seu lado tenha a própria certificação de conformidade de segurança de dados de cartão. Escreva para suporte@pay.blinkyapi.com para habilitar a Vault API.

P: Qual versão do 3DS é usada? R: 3DS 2.x, com fluxo sem fricção quando o emissor permite. A Autenticação Forte do Cliente (SCA) é obrigatória em EUR — isso é imposto no servidor.

P: E reembolso? R: Tem — POST /v1/payments/{id}/refund, total ou parcial. Reembolso de cartão liquida pela Stripe. Veja a Referência da API.

P: Meu cliente foi cobrado, mas o webhook nunca chegou. R: Confira GET /v1/webhooks/deliveries — provavelmente tentamos e o seu endpoint respondeu algo fora de 2xx. Fazemos até 10 retentativas. Depois disso, fale com o suporte para reenviar.

#Próximo

→ MB WAY · Multibanco · Referência da API