Ir para o conteúdo

Guias

Vender créditos

Créditos pré-pagos para uma API ou um serviço de IA: os compradores recarregam por conta própria e seu servidor gasta por chamada. Nada é tirado de uma recarga.

Ver como Markdown

Créditos servem para tudo o que se vende por uso: tokens, imagens, minutos, buscas. O comprador paga um pacote em cripto; você gasta dele a cada chamada; quando os créditos acabam, ele recarrega na própria página. Nada é cobrado automaticamente (o comprador sempre paga ele mesmo) e a Perly não fica com nada da recarga.

Configuração

  1. 1

    Crie um produto e os pacotes dele

    Dashboard → Products → New, depois New price → Credit pack: por exemplo, 1.000 créditos por $10, 5.000 por $40. Ou pay.prices.create({ product, model: "credit_pack", unit_amount: 1000, credits: 1000 }).

  2. 2

    Escolha quando o comprador fica sabendo do saldo

    Na página do produto, em Credits: o limite de aviso, um e-mail ao comprador e Any amount (N de um pacote), para o comprador poder recarregar $25 e não só um pacote fixo.

  3. 3

    Dê a cada comprador um cliente

    Crie um por usuário com o seu id: pay.customers.create({ email, external_id: user.id }). A partir daí, o SDK aceita esse id.

Gastar, consultar, recarregar

import { PerlyPay, InvalidRequestError } from "perly-pay";
const pay = new PerlyPay(process.env.PERLY_PAY_SECRET_KEY);

// Before the work: enough left?
const { balance, top_up_url } = await pay.credits.balance(user.id);

// After it: spend. The same idempotencyKey never spends twice.
try {
  await pay.credits.consume(user.id, 3, { action: "chat", idempotencyKey: request.id });
} catch (e) {
  if (e instanceof InvalidRequestError && e.code === "insufficient_credits") {
    return { error: "Out of credits", topUp: await pay.credits.topUpUrl(user.id) };
  }
  throw e;
}
  • O cliente é um id cus_…, um e-mail ou o seu próprio id para ele (external_id). Informe product se você vende créditos para vários produtos.
  • O gasto é atômico e nunca fica abaixo de zero: dois gastos simultâneos não passam com os mesmos créditos. Se não for suficiente, retorna insufficient_credits (409) e nada é gasto.
  • Passe o id da sua requisição como chave de idempotência. Uma nova tentativa (após um timeout, uma falha, até no dia seguinte) devolve o primeiro gasto em vez de gastar de novo.
  • action é o seu rótulo (chat, image.hd, api/search). A página do produto soma o gasto por ação e por cliente.

A página de recarga

top_up_url é a página do próprio comprador, sempre a mesma: mostra o saldo e os seus pacotes com o visual do seu checkout, e abre uma fatura normal quando o comprador escolhe um pacote. Assim que é paga, os créditos entram no saldo uma única vez. Mostre o link no seu app ou no erro de “sem créditos”, ou envie: o portal do comprador também tem um botão Recarregar.

Quando os créditos acabam

EventoQuando
credits.lowO saldo caiu até o limite do produto. Uma vez por cruzamento: só chega de novo depois que uma recarga o levar para cima do limite.
credits.depletedO saldo chegou a zero. Uma vez por cruzamento.

Os dois trazem o cliente como data.object, além de data.product e data.balance. Se houver limite e o e-mail estiver ativado, o comprador também recebe um e-mail com o link de recarga, no máximo uma vez por dia. No modo de teste, os e-mails vão só para a sua equipe.

Os créditos de vários pacotes se somam; o gasto usa primeiro o pacote mais antigo.