Vai al contenuto

Guide

Vendere crediti

Crediti prepagati per un’API o un servizio di AI: gli acquirenti ricaricano da soli e il tuo server consuma a chiamata. Dalla ricarica non tratteniamo nulla.

Vedi come Markdown

I crediti vanno bene per tutto ciò che si vende a consumo: token, immagini, minuti, ricerche. L’acquirente paga un pacchetto in crypto; tu consumi da lì a ogni chiamata; quando i crediti finiscono, ricarica dalla sua pagina. Non viene mai addebitato nulla in automatico (l’acquirente paga sempre di persona) e Perly non trattiene nulla della ricarica.

Configurazione

  1. 1

    Crea un prodotto e i suoi pacchetti

    Dashboard → Products → New, poi New price → Credit pack: per esempio 1.000 crediti per $10, 5.000 per $40. Oppure pay.prices.create({ product, model: "credit_pack", unit_amount: 1000, credits: 1000 }).

  2. 2

    Scegli quando l’acquirente scopre il suo saldo

    Nella pagina del prodotto, sotto Credits: la soglia di avviso, un’email all’acquirente e Any amount (N di un pacchetto), così l’acquirente può ricaricare $25 e non solo un pacchetto fisso.

  3. 3

    Dai a ogni acquirente un cliente

    Creane uno per utente con il tuo id: pay.customers.create({ email, external_id: user.id }). Da lì l’SDK accetta quell’id.

Consumare, consultare, ricaricare

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;
}
  • Il cliente è un id cus_…, un’email o il tuo id per lui (external_id). Indica product se vendi crediti per più prodotti.
  • Il consumo è atomico e non scende mai sotto zero: due consumi simultanei non passano con gli stessi crediti. Se non bastano, restituisce insufficient_credits (409) e non viene consumato nulla.
  • Passa l’id della tua richiesta come chiave di idempotenza. Un nuovo tentativo (dopo un timeout, un crash, perfino il giorno dopo) restituisce il primo consumo invece di consumare di nuovo.
  • action è la tua etichetta (chat, image.hd, api/search). La pagina del prodotto somma il consumo per azione e per cliente.

La pagina di ricarica

top_up_url è la pagina dell’acquirente, sempre la stessa: mostra il saldo e i tuoi pacchetti con l’aspetto del tuo checkout, e apre una normale fattura quando l’acquirente sceglie un pacchetto. Appena è pagata, i crediti si aggiungono al saldo una sola volta. Mostra il link nella tua app o nell’errore «crediti esauriti», oppure invialo: anche il portale acquirenti ha un pulsante Ricarica.

Quando i crediti finiscono

EventoQuando
credits.lowIl saldo è sceso alla soglia del prodotto. Una volta per attraversamento: torna solo dopo che una ricarica lo ha riportato sopra.
credits.depletedIl saldo è arrivato a zero. Una volta per attraversamento.

Entrambi portano il cliente come data.object, più data.product e data.balance. Se c’è una soglia e l’email è attiva, l’acquirente riceve anche un’email con il link di ricarica, al massimo una volta al giorno. In modalità test le email vanno solo al tuo team.

I crediti di più pacchetti si sommano; il consumo usa prima il pacchetto più vecchio.