Pular para o conteúdo
LeztyPay docs
Painel

Cartão internacional (EUR, USD e GBP)

Com payment_method: "card" você cobra compradores de fora do Brasil em euro, dólar ou libra. Você cobra na moeda do comprador e recebe em reais, no saldo internacional.

Hoje só o cartão está disponível. MB WAY, Apple Pay e Google Pay ainda não estão (veja a seção "Carteiras", mais abaixo). Se o par de método e moeda não puder ser oferecido, a criação responde 503 payment_method_unavailable, com o motivo em details.reason.

Moedas e métodos

Método Moedas O que o comprador faz
card EUR, USD, GBP Digita o cartão de crédito, à vista, na sua página. Pode passar por 3DS
wallet só EUR Ainda não disponível. Escolheria MB WAY, Apple Pay ou Google Pay (wallet.kind)

Para saber o que você pode oferecer agora, consulte GET /v1/payment-methods: cada item traz available e, quando falso, o reason.

  • Só à vista: não há parcelamento em moeda estrangeira, installments ausente ou 1. Outro valor é 400 installments_not_supported.
  • splits[] não vale aqui: é 400 splits_unsupported_for_payment_method.
  • amount é em centavos da moeda cobrada (2500 são 25,00 euros), com mínimo de 500 (5,00 na moeda).

Passo a passo do cartão

O número do cartão nunca passa pelo seu servidor nem pela Lezty Pay. Ele sai do navegador do comprador direto para o adquirente, que devolve um token de uso único. São quatro passos.

1. Peça o token público ao seu servidor

O seu servidor chama GET /v1/card-tokenization com a chave de API e entrega ao navegador só a resposta. A chave nunca vai para o navegador.

#!/usr/bin/env bash
# Pede ao SEU servidor o token público para tokenizar o cartão no navegador do comprador.
# Precisa de LM_API_URL e LM_API_KEY no ambiente. A chave fica no servidor, nunca no navegador.
#   export LM_API_URL=https://api.leztypay.com
#   export LM_API_KEY=sk_test_...
set -euo pipefail

curl --fail-with-body -sS "$LM_API_URL/v1/card-tokenization" \
  -H "Authorization: Bearer $LM_API_KEY"
{
  "public_token": "ptok_...",
  "tokenization_url": "https://api.scalefypay.com/api/v2/public/tokenization",
  "is_active_3ds": true,
  "expires_at": "2026-11-03T15:00:00.000Z"
}

O public_token só serve para tokenizar. Se a tokenização responder 401 ou 403, ele venceu: peça outro com ?refresh=1 (até 10 por hora). A chamada tem limite de 60 por minuto por chave. Sem cartão liberado para a sua conta, a resposta é 503 payment_method_unavailable.

2. Tokenize no navegador do comprador

A sua página envia o cartão para o tokenization_url, com o public_token no header, e recebe unique_token. Esse é o único dado de cartão que sobe para o seu servidor.

// Roda no NAVEGADOR do comprador, na sua página de pagamento. O número do cartão vai direto para
// a Scalefy (o adquirente) e nunca passa pelo seu servidor nem pela Lezty Pay. Só o token volta.
//
// `session` é o que o SEU servidor devolveu depois de chamar GET /v1/card-tokenization:
//   { public_token, tokenization_url, is_active_3ds, expires_at }
export async function tokenizeCard(session, card) {
  const res = await fetch(session.tokenization_url, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${session.public_token}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      card_holder: card.holder,
      card_number: card.number,
      cvv: card.cvv,
      expiration_date: card.expiration,
    }),
  });

  // 401 ou 403: o token público venceu. Peça outro ao seu servidor
  // (GET /v1/card-tokenization?refresh=1) e tente de novo uma vez.
  if (res.status === 401 || res.status === 403) {
    return { expired: true };
  }
  if (!res.ok) {
    return { error: true };
  }

  const body = await res.json();
  // O token vale para UMA cobrança. Mande só ele ao seu servidor e apague os campos do formulário.
  return { token: body.unique_token };
}

Guarde o número do cartão só na memória da página: não grave em localStorage, em log, em parâmetro de URL nem em ferramenta de analytics, e limpe o formulário depois da tokenização. O token vale para uma cobrança. Se a cobrança falhar, tokenize de novo.

3. Crie a cobrança

#!/usr/bin/env bash
# Cria uma cobrança de cartão em euro. Precisa de LM_API_URL e LM_API_KEY no ambiente.
# O "token" é o que a tokenização no navegador devolveu (intl-tokenize-browser.mjs).
#   export LM_API_URL=https://api.leztypay.com
#   export LM_API_KEY=sk_test_...
set -euo pipefail

curl --fail-with-body -sS "$LM_API_URL/v1/transactions" \
  -H "Authorization: Bearer $LM_API_KEY" \
  -H "Idempotency-Key: pedido-B456-tentativa-1" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_method": "card",
    "currency": "EUR",
    "amount": 2500,
    "card": { "token": "TOKEN_DE_USO_UNICO" },
    "customer": {
      "name": "Anna Keller",
      "email": "[email protected]",
      "phone": "+4915112345678",
      "document": "DE123456789",
      "country": "DE"
    },
    "return_url": "https://loja.exemplo.com/obrigado",
    "metadata": { "order_id": "B456" }
  }'
  • card.token é obrigatório e card não aceita nenhuma outra chave. Mandar número de cartão aqui é 400 validation_failed, e o valor nunca é devolvido na resposta.
  • Idempotency-Key é obrigatório, como no PIX.
  • customer pede name, email, phone (formato E.164, com + e DDI), country (duas letras, ISO alpha-2) e document (texto livre de 4 a 40 caracteres). Se country for BR, o documento precisa ser um CPF ou CNPJ válido.
  • return_url é opcional e precisa ser https: é para onde o comprador volta depois do 3DS ou da carteira. A volta não prova pagamento; confirme pelo webhook.

4. Leve o comprador ao 3DS, se houver, e espere o webhook

A autorização do cartão é imediata, mas a cobrança só vira paid quando o webhook chega. A resposta traz o bloco intl:

{
  "status": "pending",
  "payment_method": "card",
  "amount": 14270,
  "intl": {
    "method": "card",
    "wallet": null,
    "currency": "EUR",
    "local_amount": 2500,
    "provider_status": "authorized",
    "refusal_reason": null,
    "next_action": { "type": "redirect_3ds", "url": "https://acs.banco.example/..." },
    "fx": { "rate": "5.707600", "date": "2026-11-03", "kind": "venda" },
    "amount_brl_estimated": true,
    "refundable": false
  }
}
Situação Como reconhecer O que fazer
Precisa de 3DS status: "pending" e intl.next_action.type: "redirect_3ds" Redirecione o comprador para next_action.url (navegação normal da página inteira)
Autorizado sem 3DS status: "pending" e next_action ausente ou nulo Mostre "estamos confirmando" e espere transaction.paid
Cartão recusado 201 com status: "failed" e intl.refusal_reason Peça outro cartão: tokenize de novo e crie outra cobrança com outra Idempotency-Key
Parceiro sem resposta 202 com status: "pending" e sem next_action Veja abaixo

next_action só aparece enquanto a cobrança está pending, na criação e na consulta feita por você. Ele nunca vai no webhook.

Carteiras (ainda não disponível)

MB WAY, Apple Pay e Google Pay ainda não estão disponíveis. Não ofereça carteira ao comprador por enquanto. O que segue é o contrato da API para quando forem liberadas, e hoje não vale como fluxo de produção.

wallet não usa tokenização. Você manda wallet.kind (mbway, apple_pay ou google_pay), currency: "EUR" e o customer, e redireciona o comprador para a página hospedada da carteira.

#!/usr/bin/env bash
# Cria uma cobrança com carteira (MB WAY) em euro. Precisa de LM_API_URL e LM_API_KEY no ambiente.
# A resposta traz intl.next_action.url: leve o comprador até ele para concluir o pagamento.
#   export LM_API_URL=https://api.leztypay.com
#   export LM_API_KEY=sk_test_...
set -euo pipefail

curl --fail-with-body -sS "$LM_API_URL/v1/transactions" \
  -H "Authorization: Bearer $LM_API_KEY" \
  -H "Idempotency-Key: pedido-B457-tentativa-1" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_method": "wallet",
    "currency": "EUR",
    "amount": 2500,
    "wallet": { "kind": "mbway" },
    "customer": {
      "name": "Joao Ferreira",
      "email": "[email protected]",
      "phone": "+351912345678",
      "document": "123456789",
      "country": "PT"
    },
    "return_url": "https://loja.exemplo.com/obrigado",
    "metadata": { "order_id": "B457" }
  }'

A resposta traz intl.next_action com type: "redirect" e a url da carteira. A cobrança com carteira vale por 1 hora; a de cartão, por 15 minutos. O pagamento é confirmado pelo webhook, igual ao cartão.

Resposta 202: não recrie a cobrança

Se o adquirente não respondeu a tempo, a resposta é 202: a cobrança fica pending, sem next_action, e pode existir do lado dele. O token de cartão pode ter sido consumido e a carteira pode ter sido criada.

  1. Não crie outra cobrança com outra Idempotency-Key: você arrisca cobrar duas vezes.
  2. Consulte Consulta uma cobrança a cada poucos segundos até o status mudar, e escute o webhook.
  3. Repetir a mesma Idempotency-Key devolve a mesma cobrança.

Cobrança que não se resolve sozinha expira e vira expired.

O webhook

Os eventos são os de sempre: transaction.paid, transaction.failed, transaction.expired. Decida a entrega do pedido só em transaction.paid. O objeto da cobrança traz o mesmo bloco intl, sem next_action.

Estorno e contestação de cartão chegam como transaction.refunded e transaction.chargeback, que o adquirente decide e a Lezty Pay registra.

Valor em reais, saldo internacional e saque

O comprador paga na moeda dele; o seu saldo é em reais.

  • amount, fee e net da cobrança vêm em reais. Enquanto a cobrança está pending, amount é uma estimativa pela cotação PTAX de venda do dia da criação (intl.amount_brl_estimated: true). Ao pagar, o valor é recalculado pela PTAX do dia do pagamento, e o amount_brl_estimated passa a false. intl.fx mostra a cotação usada. O valor na moeda do comprador fica em intl.local_amount.
  • O dinheiro entra no saldo internacional, separado do saldo PIX, e é liberado 30 dias depois da venda. Desse valor, 10% ficam retidos por mais 90 dias e são liberados sozinhos, como na cobrança LATAM.
  • Para tirar o dinheiro, você saca em USDT, com taxa de US$ 2,00 por saque, mínimo de 20 USDT e máximo de 2.000 USDT por pedido e 5.000 USDT por dia. Ver Saques.

Estorno

Cobrança de cartão não tem estorno pela API: POST /v1/transactions/{id}/refund responde 409 refund_unsupported_for_payment_method, e intl.refundable é sempre false. Para devolver um valor ao comprador, fale com o suporte.

Taxa e valor mínimo

A taxa é de 20% por venda, sem valor fixo. A taxa vigente da sua conta está em GET /v1/rates e no painel, e é congelada na criação. A venda mínima é de 5,00 na moeda cobrada (amount de 500).

Veja também Limites.

Link de pagamento

No link de pagamento o comprador digita o cartão na página hospedada pela Lezty Pay, e você não integra nada.

Checkout hospedado

Para cobrar um pedido seu sem tokenizar nada no seu site, crie uma sessão de checkout: você manda valor, metadata e postback_url, e o comprador paga com cartão na página da Lezty Pay.

Erros

Resposta Quando
400 validation_failed Corpo inválido, card com chave além de token, ou customer incompleto
400 unsupported_currency Moeda fora de EUR, USD e GBP
400 installments_not_supported installments diferente de 1
400 splits_unsupported_for_payment_method splits[] em cobrança internacional
403 seller_not_allowed Conta sem KYC aprovado
409 card_charge_in_progress Já existe um cartão em andamento para esse comprador: espere alguns minutos
409 fx_rate_unavailable Sem cotação recente da moeda: repita depois
409 refund_unsupported_for_payment_method Pedido de estorno
409 idempotency_conflict Mesma Idempotency-Key com corpo diferente
503 payment_method_unavailable O par de método e moeda não está disponível para você agora (details.reason)
503 acquirer_timeout O adquirente demorou: espere 60 s e repita com a mesma chave

O details.reason do 503 payment_method_unavailable é um destes: paused, fee_not_configured, pair_not_enabled, pair_not_in_account, seller_disabled ou no_acquirer. Todos significam "não oferecer esse método agora"; nada foi criado.

Próximo passo

Webhooks para confirmar o pagamento, e Saques para sacar o saldo internacional.

Referência: Cria uma cobrança (PIX, voucher, cripto, cartão ou carteira).