Pular para o conteúdo
LeztyPay docs
Painel

Produtos e links de pagamento

Um link de pagamento é uma página pública de cobrança que a Lezty Pay hospeda por você. Você cadastra um produto (nome, preço), cria um link que aponta para ele e divulga a URL. Cada comprador que abre o link informa os próprios dados e recebe uma cobrança PIX nova, a página confirma o pagamento sozinha, e o seu sistema fica sabendo pelo mesmo webhook de sempre.

Não há nada para integrar do lado do comprador. A API serve para quem quer criar produtos e links por código; o painel oferece as mesmas operações na tela Checkout.

O que existe hoje: produto e link em BRL (PIX e cripto) e em euro, dólar e libra (cartão), limite de uso, validade, taxa por conta do comprador e endereço de retorno. Ainda não estão disponíveis: imagem do produto e entrega automática de arquivo, listados no fim desta página, em "Em breve".

Criar um produto

O produto é o que se vende: nome, descrição opcional e preço em centavos. A moeda é BRL, EUR, USD ou GBP; os links em euro, dólar e libra estão na seção "Links em euro, dólar e libra", mais abaixo.

#!/usr/bin/env bash
# Cria um produto. Precisa de LM_API_URL e LM_API_KEY no ambiente.
#   export LM_API_URL=https://api.leztypay.com
#   export LM_API_KEY=sk_test_...
# Criar produto não é operação financeira: sem Idempotency-Key.
set -euo pipefail

curl --fail-with-body -sS "$LM_API_URL/v1/products" \
  -H "Authorization: Bearer $LM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Curso X",
    "description": "Acesso ao curso completo",
    "price": 10000
  }'

A resposta é o objeto product, com id no formato prd_.... Produto não é apagado: para tirar de venda, edite com Edita um produto (chave de API) e mande "for_sale": false. Os links dele passam a responder que o produto não está à venda. A moeda não muda depois de criado.

Em produção, o preço precisa ficar acima da taxa que a sua conta paga, senão a criação responde 400 amount_too_small. As taxas da sua conta estão na tela de taxas do painel.

Criar um link

O link aponta para um produto da mesma conta e do mesmo ambiente. Só product_id é obrigatório.

#!/usr/bin/env bash
# Cria um link de pagamento para um produto seu (o id vem da resposta de links-create-product.sh).
# Precisa de LM_API_URL e LM_API_KEY no ambiente. Sem Idempotency-Key: não é operação financeira.
set -euo pipefail

curl --fail-with-body -sS "$LM_API_URL/v1/payment-links" \
  -H "Authorization: Bearer $LM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_01j0000000000000000000000",
    "return_url": "https://loja.exemplo.com/obrigado",
    "buyer_pays_fee": false,
    "max_uses": 100,
    "expires_at": "2027-01-31T23:59:59-03:00"
  }'

Criar produto e link não é operação financeira, então não leva Idempotency-Key. Criar duas vezes cria dois objetos.

A resposta é o objeto payment_link. Os campos que importam:

  • url: o endereço pronto para divulgar. O slug (10 caracteres) é gerado por nós e não pode ser escolhido nem alterado.
  • active: false tira o link do ar sem apagar nada. Não existe DELETE.
  • title e description: o que a página mostra. Se você não mandar, valem o nome e a descrição do produto.
  • product: um resumo do produto (id, name, currency, price, for_sale).
  • stats: os números do link (abaixo).

Edita um link de pagamento (chave de API) muda qualquer campo menos product_id. Para vender outro produto, crie outro link: assim o total de um link sempre quer dizer a mesma coisa. Enviar null em return_url, max_uses ou expires_at limpa o campo.

stats

Aparece sempre em GET /v1/payment-links/{id} e, na listagem, com with_stats=1.

Campo O que é
paid_count Cobranças pagas do link
paid_amount_total Soma do que os compradores pagaram, em centavos
paid_net_total Soma do líquido que ficou para você, em centavos
pending_count Cobranças aguardando pagamento
remaining_uses Vagas livres. null se o link é ilimitado; pode ficar negativo se você baixar max_uses depois
over_limit_count Vendas que passaram do limite (ver abaixo)

A listagem aceita os filtros active, product_id e q (título ou slug), além da paginação por cursor de Paginação.

O que o comprador vê

O comprador abre a URL, vê o nome, a descrição e o valor, preenche nome, e-mail e documento e confirma. A página cria uma cobrança PIX nova só para ele, mostra o QR Code e fica consultando o status até o pagamento entrar. Se o link aceita cripto, o comprador escolhe entre PIX e cripto (a moeda, USDT ou USDC, e a rede) antes de pagar; ver Link com cripto. Pagou, a página mostra a confirmação e, se o link tem return_url, oferece o botão de voltar para a sua loja.

Quem define o valor é o link, nunca o comprador. O que ele informa é só quem ele é.

Se o link não puder vender, a página diz o motivo: desativado, expirado, esgotado ou produto fora de venda. Quem tenta criar a cobrança nesses casos recebe 409 com o code payment_link_inactive, payment_link_expired, payment_link_sold_out ou product_not_for_sale.

Link com cripto

Por padrão o link aceita só PIX. Para aceitar também USDT e USDC, marque accepted_methods: ["pix", "crypto"] ao criar ou editar o link. pix precisa continuar na lista, e cripto vale só para produto em BRL e link sem buyer_pays_fee; fora disso é 400 validation_failed com param: accepted_methods. A opção só aparece para o comprador quando você tem carteira utilizável (bsc ou polygon, que também vale em arbitrum e optimism, fora da carência de 48 h) e o preço do produto é de pelo menos US$ 5; abaixo disso o link mostra só PIX. No link, o documento do comprador é opcional em cripto. A cobrança criada pelo link segue as regras de Cobrança em cripto: taxa de 4% + US$ 0,50, repasse direto, sem estorno.

A moeda não é configurada no link: o comprador escolhe entre as que estiverem prontas. Quem monta a própria página lê o bloco crypto de GET /pay/v1/links/{slug}:

"crypto": {
  "coins": ["usdt", "usdc"],
  "offers": [
    { "coin": "usdt", "networks": ["bsc", "polygon", "arbitrum"], "min_usdt": 500, "amount_usdt_estimate": 1852, "price_brl_per_usdt": "5.400000" },
    { "coin": "usdc", "networks": ["polygon", "arbitrum", "optimism"], "min_usdt": 100, "amount_usdt_estimate": 1853, "price_brl_per_usdt": "5.400000" }
  ],
  "networks": ["bsc", "polygon", "arbitrum"],
  "min_usdt": 500,
  "amount_usdt_estimate": 1852,
  "price_brl_per_usdt": "5.400000"
}
  • coins lista só as moedas oferecidas agora; uma moeda cuja cotação ou cujo mínimo da rede não atendem some da lista.
  • offers traz, por moeda, as redes prontas, o piso e a estimativa. Use offers: os campos planos (networks, min_usdt, amount_usdt_estimate, price_brl_per_usdt) descrevem só a primeira moeda pronta (o USDT, quando ele está pronto) e ficam por compatibilidade.
  • Os campos *_usdt são centavos de dólar da moeda do item (USDC vale US$ 1, como o USDT).
  • Para criar a cobrança, envie crypto.network e, se for USDC, crypto.coin: "usdc" em POST /pay/v1/links/{slug}/charges. Sem coin a cobrança é em USDT.

Links em euro, dólar e libra

Crie o produto com currency em EUR, USD ou GBP e o preço em centavos dessa moeda. O link desse produto cobra por cartão. MB WAY, Apple Pay e Google Pay (carteiras, só em euro) ainda não estão disponíveis. Em moeda estrangeira não há PIX no link.

  • accepted_methods do link é ["card"]. wallet só vale em EUR e ainda não está disponível; fora disso é 400 validation_failed com param: accepted_methods.
  • A página mostra só os métodos que estão ligados na sua conta naquela moeda. Sem nenhum disponível, o link responde que não pode vender agora (payment_method_unavailable), em vez de quebrar.
  • O comprador informa nome, e-mail, telefone, país e documento. O cartão é digitado na página da Lezty Pay e vai direto ao adquirente: você não integra nada. Se o banco pedir 3DS, a página leva o comprador até ele e volta sozinha.
  • buyer_pays_fee e splits[] não valem em moeda estrangeira.
  • A cobrança criada pelo link segue as regras de Cartão internacional: confirmação só pelo webhook, saldo internacional em reais e saque em USDT, sem estorno pela API.

Quem monta a própria página lê payment_methods, wallets, card_session_required e country_required em GET /pay/v1/links/{slug}, abre a tokenização com POST /pay/v1/links/{slug}/card-session (atrás do mesmo token anti-robô da cobrança) e cria a cobrança com payment_method: "card" e card.token.

Limite de uso e validade

  • expires_at é a validade do link. Depois dela, a página mostra "expirado" e a criação de cobrança é recusada. Quem já estava pagando uma cobrança criada antes não é cortado.
  • max_uses limita pagamentos, não aberturas da página. Uma cobrança aguardando pagamento reserva uma vaga enquanto estiver aguardando. Se ela expirar sem pagar, a vaga volta.
  • Estorno e chargeback não devolvem a vaga: você vendeu. Se quiser vender mais, suba max_uses.
  • A cobrança de um link vale, no máximo, 30 minutos, ou menos se o processador de pagamentos expirar antes.

O limite não estoura por concorrência: dois compradores disputando a última vaga resultam em um pagamento e um 409 payment_link_sold_out.

Pagamento tardio é a exceção. O PIX de uma cobrança que já expirou pode ainda ser pago, e nesse caso a venda vale: o dinheiro entrou. Se isso acontecer com o link já cheio, a transação fica marcada como acima do limite (payment_link.over_limit é true, e stats.over_limit_count conta quantas) e você decide se estorna ou honra a venda.

Taxa por conta do comprador

Com buyer_pays_fee: true, o valor cobrado do comprador sobe o suficiente para cobrir a taxa, e você recebe líquido igual ao preço do produto, com no máximo 1 centavo de sobra, que fica com você.

Quanto é a taxa, não está nesta página: ela depende das condições da sua conta, que estão na tela de taxas do painel. A resposta de criação da cobrança já traz fee, net e o valor final.

A cobrança carrega as duas parcelas em items, que é o que você vê no painel e no webhook:

"items": [
  { "name": "Curso X", "quantity": 1, "unit_amount": 10000 },
  { "name": "Taxa de serviço", "quantity": 1, "unit_amount": 99 }
]

(O segundo valor é só ilustrativo.) amount da cobrança é a soma das duas linhas.

buyer_pays_fee só vale em BRL. Se o preço mais a taxa passar do teto de uma cobrança, a criação ou a edição do link responde 400 amount_too_large.

O retorno não é prova de pagamento

Se o link tem return_url, depois do pagamento a página mostra o botão "Voltar para" com o domínio de destino. Ao clicar, o comprador chega na sua loja com transaction_id e status=paid na URL.

Trate isso como uma conveniência de navegação, nunca como confirmação. Qualquer pessoa pode digitar essa URL na barra do navegador. A prova de que o pagamento aconteceu é:

Libere o pedido por um dos dois. Use o transaction_id da URL só para saber qual cobrança consultar.

A return_url precisa ser https, com um domínio público (nada de IP, localhost ou endereço interno), sem usuário e senha e sem #. Fora disso a resposta é 400 invalid_url. A página nunca redireciona sozinha antes do pagamento, e no ambiente de teste não redireciona sozinha em momento nenhum.

payment_link na cobrança e nos webhooks

Toda cobrança que nasceu de um link traz o campo payment_link; as demais trazem null. Ele aparece em Consulta uma cobrança, nas listagens e no data.object dos webhooks transaction.*.

"payment_link": {
  "id": "plk_...",
  "slug": "7k3m9qx2ab",
  "product_id": "prd_...",
  "over_limit": false
}

É um campo novo e aditivo: integrações que não o conhecem continuam funcionando. Use product_id para saber o que foi vendido e id para saber por qual link. O metadata da cobrança não é usado pelos links.

Para listar só as vendas de um link:

#!/usr/bin/env bash
# Lista só as cobranças que nasceram de um link de pagamento.
#   LM_PAYMENT_LINK_ID=plk_01j... ./links-list-transactions.sh
set -euo pipefail

curl --fail-with-body -sS "$LM_API_URL/v1/transactions?payment_link_id=$LM_PAYMENT_LINK_ID" \
  -H "Authorization: Bearer $LM_API_KEY"

Um payment_link_id malformado é 400 validation_failed.

Ambiente de teste e prévia

Com uma chave sk_test_, produto e link nascem no ambiente de teste e só geram cobrança de teste, paga pelos gatilhos. Mas a URL pública de um link de teste não abre para qualquer pessoa: sem um token de prévia ela responde 404, igual a um slug que não existe. Isso impede que alguém use uma conta de teste para montar uma página de cobrança com a nossa marca.

O token de prévia sai do painel, no botão "Abrir prévia" do link (vale 1 hora, só para quem está logado na conta). A API que o emite, POST /v1/me/payment-links/{id}/preview, só aceita sessão do painel, não chave de API. A prévia é a forma de ver o fluxo inteiro sem dinheiro.

Limites e erros

As rotas de gestão seguem os limites de Limites: 60 requisições por minuto em escrita e 600 em leitura, por chave. O envelope de erro é o de Erros. Os code próprios dos links:

Quando Resposta
Corpo ou campo inválido 400 validation_failed
return_url fora da regra 400 invalid_url
Preço fora da faixa da moeda 400 amount_too_small ou 400 amount_too_large
buyer_pays_fee não calculável para o preço 400 buyer_fee_not_computable
Conta sem permissão de cobrar neste ambiente 403 seller_not_allowed
Criação e edição suspensas temporariamente (as consultas seguem funcionando) 403 feature_disabled
Produto, link ou id de outra conta ou de outro ambiente 404 resource_not_found
Link desativado, expirado, esgotado ou produto fora de venda 409, com o code correspondente
Muitas cobranças em aberto no mesmo link 429 payment_link_busy, com Retry-After

Erro de validação não cria nada: corrija e repita.

Uso avançado: a API que a página consome

A página de pagamento é um cliente comum de uma API pública, sem autenticação, em /pay/v1/*. Ela está na referência sob a tag "Página de pagamento (público)" e existe para quem precisa montar a própria tela. Para quase todo mundo, a URL do link resolve.

  • Carrega o link de pagamento: carrega o link e devolve só o que a página precisa (nome, valor, taxa do comprador, estado, nome de exibição do vendedor). Fora do estado active, devolve só o estado.
  • Cria a cobrança do link: cria a cobrança do comprador. Exige Idempotency-Key e um token de verificação anti-robô no header X-Captcha-Response. O corpo aceita apenas customer e tracking: valor, moeda e itens vêm sempre do link, e qualquer outro campo é 400.
  • Acompanha a cobrança: acompanha a cobrança, com o header X-Pay-Token recebido na criação. Nunca devolve dados do comprador nem taxa.

Esses endpoints têm limites por IP e por link, e usam um token que só serve para acompanhar aquela cobrança. Não os use como substituto da API com chave: para saber se pagou, o caminho continua sendo o webhook.

Em breve

Estes recursos ainda não estão disponíveis. Quando forem, cada um ganha a própria página:

  • Imagem do produto
  • Entrega automática de arquivo depois do pagamento

Referência: Cria um produto (chave de API), Cria um link de pagamento (chave de API) e Cria uma cobrança (PIX, voucher, cripto, cartão ou carteira) para a cobrança direta, sem link.