Skip to main content

Visão geral

O Checkout Session é o modelo recomendado quando o pagamento é iniciado no frontend (browser, app mobile). Em vez de expor sua X-API-Key no cliente, o fluxo funciona em duas etapas:
  1. Backend cria uma sessão com X-Client-ID + X-API-Key — recebe um token de curta duração
  2. Frontend usa esse token para submeter o pagamento — sem contato com a API key
Backend                              Frontend
   │                                    │
   │  POST /checkout/sessions           │
   │  X-Client-ID + X-API-Key  ────►   │  (token, expires_at, saved_cards)
   │                                    │
   │                            ◄────  │  POST /checkout/payments/card
   │                                    │  X-Checkout-Token: cs_live_...
Campos críticos como amount, currency e merchant_order_id são travados na sessão pelo backend — o frontend não pode alterá-los, o que elimina a possibilidade de manipulação de preço pelo cliente.

Criar sessão

POST /api/v1/checkout/sessions — requer X-Client-ID + X-API-Key. Chamada exclusivamente pelo backend da empresa.
POST /api/v1/checkout/sessions
Content-Type: application/json
X-Client-ID: client_...
X-API-Key: sk_...
{
  "amount": 15000,
  "currency": "BRL",
  "merchant_order_id": "ORD-2026-12345",
  "payment_method": "card",
  "gateway_first_try": "pagarme",
  "expires_in": 1800,
  "success_url": "https://meusite.com/pedido/sucesso",
  "cancel_url": "https://meusite.com/pedido/cancelado",
  "metadata": {
    "order_ref": "ORD-2026-12345",
    "user_id": "usr_789"
  },
  "customer": {
    "token": "cus_7556..."
  }
}
CampoTipoObrigatórioDescrição
amountinteiro (centavos)simValor da cobrança — imutável após criação
currencyBRL|USDsimMoeda
merchant_order_idstring (max 255)simReferência do pedido no seu sistema — imutável após criação
payment_methodcard|pixnãoRestringe o método aceito. Omitir permite cartão e PIX
gateway_first_trystringnãoGateway prioritário para essa sessão. Sobrepõe qualquer valor enviado pelo frontend
expires_ininteiro (60–86400)nãoDuração da sessão em segundos. Padrão: 1800 (30 min). Máx: 86400 (24h)
success_urlURL (max 2048)nãoRedirecionamento em caso de pagamento aprovado
cancel_urlURL (max 2048)nãoRedirecionamento em caso de falha ou cancelamento
metadataobjetonãoDados livres repassados ao frontend na resposta da sessão
customer.tokenstringnãoToken do cliente — carrega os cartões salvos dele na resposta
customer.emailstringnãoAlternativa ao token: busca o cliente pelo e-mail
customer.documentstringnãoAlternativa ao token: busca o cliente pelo CPF/CNPJ
success_url e cancel_url passam por validação SSRF: IPs privados e intervalos reservados (10.x, 192.168.x, 127.x) são rejeitados com 422.
Resposta 201:
{
  "token": "cs_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6",
  "amount": 15000,
  "currency": "BRL",
  "merchant_order_id": "ORD-2026-12345",
  "payment_method": "card",
  "gateway_first_try": "pagarme",
  "metadata": {
    "order_ref": "ORD-2026-12345",
    "user_id": "usr_789"
  },
  "success_url": "https://meusite.com/pedido/sucesso",
  "cancel_url": "https://meusite.com/pedido/cancelado",
  "expires_at": "2026-06-25T12:30:00+00:00",
  "saved_cards": [
    {
      "holder_name": "JOAO SILVA",
      "token": "card_86123...",
      "brand": "visa",
      "first_6_digits": "411111",
      "last_4_digits": "1111",
      "expire_month": "12",
      "expire_year": "2028",
      "status": "active",
      "created_at": "2026-01-10T08:00:00+00:00",
      "updated_at": "2026-01-10T08:00:00+00:00"
    }
  ]
}
O array saved_cards é preenchido quando o campo customer é informado e o cliente possui cartões salvos. Use-o para exibir uma lista de cartões ao usuário sem que o frontend precise consultar outra rota.

Submeter pagamento

O token recebido na criação da sessão é enviado no header X-Checkout-Token. Ele é de uso único — ao iniciar uma tentativa de pagamento, a sessão é marcada como usada e não pode ser reutilizada, mesmo que a cobrança falhe.

Cartão

POST /api/v1/checkout/payments/card — requer X-Checkout-Token.
POST /api/v1/checkout/payments/card
Content-Type: application/json
X-Checkout-Token: cs_live_a1b2c3...
Idempotency-Key: ORD-2026-12345  (opcional, mas recomendado)
Com cartão novo:
{
  "payment_method": "card",
  "customer": {
    "name": "João Silva",
    "email": "joao@example.com",
    "document": "12345678909"
  },
  "card": {
    "number": "4111111111111111",
    "cvv": "123",
    "expiration_month": "12",
    "expiration_year": "2028",
    "installments": 1,
    "holder": "Fulano da Silva",
    "holder_birthdate": "1990-05-25",
    "holder_document": "12345678909",
    "holder_phone": "11987542563",
    "save_card": true
  },
  "billing_address": {
    "street": "Rua dos Advogados",
    "number": "321",
    "neighborhood": "Jardim",
    "zip_code": "35900000",
    "city": "Belo Horizonte",
    "state": "MG",
    "country": "Brasil"
  }
}
Com cartão salvo (token de saved_cards):
{
  "payment_method": "card",
  "customer": {
    "token": "cus_7556..."
  },
  "card": {
    "token": "card_86123...",
    "installments": 1
  }
}
Ao usar um cartão salvo, billing_address e os dados do titular não são necessários — eles já estão no vault.

PIX

POST /api/v1/checkout/payments/pix — requer X-Checkout-Token.
POST /api/v1/checkout/payments/pix
Content-Type: application/json
X-Checkout-Token: cs_live_a1b2c3...
{
  "customer": {
    "name": "Maria Santos",
    "email": "maria@example.com",
    "document": "98765432100"
  }
}
O payment_method não é necessário no PIX via checkout — a rota já define o método. O amount, currency e merchant_order_id são injetados automaticamente da sessão.

Campos travados pela sessão

O middleware de checkout injeta automaticamente os valores abaixo no corpo da requisição, sobrescrevendo qualquer valor que o frontend tente enviar:
CampoOrigem
amountSessão (imutável)
currencySessão (imutável)
merchant_order_idSessão (imutável)
gateway_first_trySessão (se definido; caso contrário, o frontend pode sugerir)

Resposta do pagamento

Idêntica ao pagamento direto — mesmos campos, mesmas regras de status HTTP:
HTTPSignificado
201 CreatedAprovado dentro do time_to_wait_sync
202 AcceptedProcessando — aguarde via webhook ou polling
500Falhou em todas as tentativas

Ciclo de vida da sessão

EstadoCondição
Válidaused_at nulo e expires_at no futuro
Expiradaexpires_at no passado → 401
Usadaused_at preenchido (pagamento iniciado) → 409 Conflict
A sessão é marcada como usada antes de o pagamento ser processado. Se a cobrança falhar (gateway recusa, timeout), a sessão continua consumida e não pode ser reutilizada. Crie uma nova sessão para uma nova tentativa.

Referência rápida de rotas

MétodoRotaAuthQuem chama
POST/api/v1/checkout/sessionsX-Client-ID + X-API-KeyBackend
POST/api/v1/checkout/payments/cardX-Checkout-TokenFrontend
POST/api/v1/checkout/payments/pixX-Checkout-TokenFrontend