Aller au contenu

Guides

Recette : crédits API

Vendez des crédits prépayés pour une API ou une fonction d’IA, et consommez-en un par requête. Un solde insuffisant répond 402 avec un lien de recharge.

Voir en Markdown

Les acheteurs prépaient un pack de crédits ; chaque requête en consomme. Perly Pay tient le registre : consommer est un appel atomique qui refuse tout découvert, et chaque acheteur a sa propre page de recharge. Rien n’est jamais débité tout seul — quand les crédits sont épuisés, l’acheteur recharge. Toute la fonction crédits est dans Vendre des crédits ; ceci est la recette autour.

Avec un assistant : le skill sell-credits du plugin Perly Pay réalise cette recette dans votre projet. L’exemple exécutable est examples/api-credits (MIT) dans le dépôt du plugin.

Comment ça marche

  1. 1

    Un pack de crédits

    Un produit et un prix avec model: "credit_pack", unit_amount en centimes et credits. Créé une fois par mode.

  2. 2

    Vos utilisateurs sont des clients

    Créés une fois avec external_id (votre id utilisateur) ; ensuite, credits.* acceptent cet id.

  3. 3

    Recharge

    credits.topUpUrl(userId) est la page propre à l’acheteur : il choisit un pack et paie. Chaque pack payé ajoute des crédits.

  4. 4

    Consommer par requête

    credits.consume(userId, cost, { idempotencyKey }) d’abord, puis le travail. Une nouvelle tentative avec la même clé renvoie la première consommation : votre serveur crée donc la clé pour chaque requête et ne la prend jamais de l’appelant.

  5. 5

    Solde insuffisant ?

    insufficient_credits (409) ne consomme rien : répondez 402 avec la page de recharge, pas une 500.

Spend one request's credits
try {
  await pay.credits.consume(userId, cost, { product: PRODUCT, action: "api", idempotencyKey: `req-${userId}-${requestId}` });
} catch (e) {
  if (e.code !== "insufficient_credits") throw e;
  return reply(402, { top_up: await pay.credits.topUpUrl(userId, { product: PRODUCT }) });
}
// now do the work

Lancez l’exemple

  1. 1

    Installez

    npm install dans examples/api-credits (Node 20.12+).

  2. 2

    Clé

    Copiez .env.example vers .env et mettez une clé de test (sk_test_…) dans PERLY_PAY_SECRET_KEY.

  3. 3

    Préparez

    npm run setup crée le produit et le prix avec votre clé et affiche leurs ids pour .env.

  4. 4

    Lancez

    npm start (ou npm run dev), comme l’indique son README.

  5. 5

    Payez sans portefeuille

    Appelez POST /v1/shout (402), ouvrez la page que donne POST /top-up, choisissez le pack, touchez Simulate payment sur la facture, rappelez : 200 et X-Credits-Remaining: 499.

Pièges

  • Consommer sans clé d’idempotence : une requête relancée est facturée deux fois.
  • Baser la clé de consommation sur un id envoyé par l’appelant (un en-tête Idempotency-Key) : la même clé renvoie la première consommation comme un succès, et l’appelant obtient à nouveau le travail sans payer.
  • Vérifier le solde, puis consommer, en deux étapes. consume refuse à lui seul tout découvert ; le solde sert à l’affichage.
  • Faire le travail avant de consommer. Consommez d’abord.
  • Des ids de test avec une clé réelle. Produits, prix et endpoints de webhook appartiennent à un seul mode : refaites la mise en place avec sk_live_… au passage en réel.