FIM One intègre un pipeline de facturation Stripe complet contrôlé par un drapeau de fonctionnalité administrateur. Les déploiements privés sans besoin de paiement le laissent désactivé et ne voient jamais l’interface utilisateur. Les opérateurs SaaS basculent un seul paramètre et obtiennent immédiatement la Checkout hébergée, le Portail Client, le cycle de vie des abonnements piloté par webhook et l’application des quotas.Documentation Index
Fetch the complete documentation index at: https://docs.fim.ai/llms.txt
Use this file to discover all available pages before exploring further.
La facturation est désactivée par défaut. Les nouvelles installations et les déploiements autonomes existants commencent avec
system_settings.billing_enabled = FALSE. Aucune interface de facturation n’apparaît tant qu’un administrateur ne l’active pas explicitement.Ce que vous obtenez
- Niveaux Free + Pro avec quotas de tokens mensuels (par défaut : Free 1M / Pro 5M ; tous deux ajustables après activation)
- Stripe Checkout hébergé — les utilisateurs passent à la version payante sans que votre code ne touche jamais aux données de carte
- Portail client — les utilisateurs mettent à jour les méthodes de paiement, téléchargent les factures, annulent — tout sur l’interface de Stripe
- Cycle de vie piloté par webhooks — les abonnements se provisionnent et se renouvellent automatiquement ; les abonnements annulés rétrogradent à Free à la fin de la période
- Application des quotas — utilisation des tokens suivie par période ; arrêt en cours de flux avec une invite de mise à niveau structurée
- Pages d’administration pour la gestion des plans et la surveillance des abonnements
Prérequis
- Compte Stripe avec le mode Live activé. Les entreprises constituées à Singapour doivent compléter la vérification KYC (UEN commercial, ID du directeur, compte bancaire). L’approbation prend généralement 1 à 3 jours.
- Clé API Stripe Live de type Restricted (recommandée plutôt que Standard
sk_live_***— plus facile à révoquer, permissions limitées). - Point de terminaison webhook accessible publiquement à
<your-domain>/api/webhooks/stripe. - Compte bancaire pour les versements. Le règlement multi-devises (par ex. versement en USD vers un compte USD) est recommandé pour les comptes Stripe non-USD par défaut afin d’éviter une fuite de change de 1,5 à 2 % par transaction.
Configuration
1. Tableau de bord Stripe
Créer le produit Pro
- Catalog → Products → + Add product
- Name:
Pro, description:5M tokens / month, priority support - Pricing: Recurring, monthly, $20.00 USD (adjust to your pricing strategy)
- Save → copy the resulting
price_***ID (you will UPDATE the localbilling_planstable with this value after activation)
Créer une clé API restreinte
- Developers → API keys → + Create restricted key
- Name:
fim-one production - Permissions (minimum):
- Customers: Write
- Subscriptions: Write
- Checkout Sessions: Write
- Customer portal: Write
- Prices: Read
- Products: Read
- Save → copy
rk_live_***
Enregistrer le point de terminaison du webhook
- Developers → Webhooks → + Add endpoint
- URL:
https://<your-domain>/api/webhooks/stripe - Événements à recevoir:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
- Après l’enregistrement, cliquez sur “Reveal signing secret” → copiez
whsec_***
Configurer le règlement multi-devises (recommandé)
Si la devise par défaut de votre compte Stripe diffère de la devise de prix que vous facturez (cas courant : compte SGD facturant en USD) :- Paramètres → Comptes bancaires et devises → Ajouter une devise de règlement
- Sélectionnez la devise de prix (par ex. USD)
- Attachez le compte bancaire correspondant (par ex. un compte virtuel Aspire USD)
- Enregistrez — Stripe achemine les frais USD directement vers les versements USD, sans conversion de change
2. Backend .env
Définissez ces trois clés dans votre .env de production :
.env pour que les clés soient prises en compte :
3. Activate in Admin
- Log in as an admin
- Admin → System Settings → Billing
- Toggle Enable Stripe Billing ON
- The backend validates that both
STRIPE_SECRET_KEYandSTRIPE_WEBHOOK_SECRETare present — if either is missing it returns 400 and the toggle stays OFF - On first activation only, the backend runs an idempotent setup:
- Seeds Free + Pro plans (skipped if already present)
- Sets
system_settings.default_plan_idto the Free plan id - Backfills
users.plan_id = free.idfor any user without a plan - Syncs
default_token_quota→ Free planmonthly_token_quotaso the existing admin-controlled global quota carries over
- Subsequent toggle off/on is a pure flag flip with no data side effects
4. Mettez à jour le plan Pro avec votre prix en direct
Après l’activation, mettez à jour le plan Pro pré-configuré pour pointer vers votre prix Stripe en direct :- Admin → Billing → Plans → Pro → Edit
- Collez votre
price_1***(de l’étape 1) dansStripe Price ID - Enregistrez
5. Test de fumée
- Ouvrez
/settings?tab=billingen tant qu’utilisateur ordinaire - Cliquez sur Switch to Pro
- Stripe Checkout s’ouvre ; complétez avec une vraie carte à faible montant (remboursement après)
- Le webhook doit se déclencher — vérifiez dans Stripe Dashboard → Webhooks → les événements récents affichent des réponses 2xx
- Une ligne d’abonnement apparaît dans la table
subscriptions;users.plan_idbascule àpro - L’interface affiche maintenant le plan Pro + le bouton « Manage subscription »
Désactiver la facturation
Basculez le commutateur Enable Stripe Billing sur OFF dans Admin → System Settings → Billing. Lorsque désactivé :- Tous les points de terminaison
/api/billing/*retournent 503 - Le point de terminaison webhook retourne 503 (Stripe réessaiera, puis s’affichera dans Dashboard comme défaillant — c’est normal, vous pouvez désactiver le webhook dans Stripe Dashboard à la place si la facturation est définitivement désactivée)
- L’onglet Plan & Billing destiné aux utilisateurs disparaît
- Le groupe de navigation Admin → Billing est masqué
- La chaîne de quota ignore le niveau de plan et revient directement à
default_token_quota
subscriptions, billing_plans et users.plan_id existantes restent inchangées. La réactivation reprend à partir du même état sans migration.
Référence de calcul — mathématiques des quotas et des jetons
Ceci est la référence faisant autorité pour chaque règle numérique qui décide ce qu’un utilisateur est autorisé à consommer, quand son compteur se réinitialise, et comment la chaîne de résolution se compose. Lisez ceci avant de modifier la tarification, d’ajuster les quotas, de créer des tableaux de bord d’utilisation, ou de planifier les travaux v2/v3. Les règles futures non encore déployées sont documentées dans leur emplacement réservé afin que les contributeurs sachent où s’intègre la nouvelle logique.Glossaire
| Variable | Stockage | Sémantique | Plage |
|---|---|---|---|
users.token_quota | par utilisateur (remplacement) | Remplacement à trois états ; voir la sémantique ci-dessous | NULL, 0, ou entier positif |
users.tokens_used_this_period | par utilisateur (compteur) | Tokens cumulatifs depuis la dernière réinitialisation | entier non-négatif |
users.quota_reset_at | par utilisateur (ancre) | Reflète Subscription.current_period_end pour les utilisateurs payants | timestamp |
users.plan_id | par utilisateur (FK) | Plan actif | FK billing_plans.id |
billing_plans.monthly_token_quota | par plan | Limite maximale pour les utilisateurs de ce plan | entier non-négatif |
system_settings.default_token_quota | singleton | Secours défensif quand aucun plan ne s’applique | entier non-négatif |
system_settings.default_plan_id | singleton | Pointeur de plan gratuit pour les utilisateurs nouveaux/non assignés | FK ou NULL |
system_settings.billing_enabled | singleton | Commutateur maître — contrôle l’étape 2 de la chaîne | booléen |
Ce qui compte comme un token
La consommation de tokens est comptabilisée au niveau de l’appel LLM, provenant de l’objetusage de LiteLLM sur chaque completion.
- Comptabilisé : tokens de prompt + tokens de completion sur chaque appel de modèle
- Comptabilisé : chaque aller-retour dans un flux d’agent multi-étapes / tool-use (chaque appel de modèle est son propre débit)
- Comptabilisé : demandes d’embedding (ingestion KB, scoring de récupération)
- Non comptabilisé : entrée préparée mais jamais envoyée à un modèle (par exemple, fichiers téléchargés que l’utilisateur abandonne)
- Non comptabilisé : demandes qui échouent avant d’atteindre le fournisseur (erreur d’authentification, pré-vérification de limite de débit)
- Entrée en cache : comptabilisée au prix complet en v1 (aucune remise de cache du fournisseur n’est affichée). v2 peut créditer les tokens de prompt en cache séparément.
Sémantique de remplacement à trois états
users.token_quota est le remplacement administratif par utilisateur. Il porte trois significations dans une seule colonne :
| Valeur | Signification | Cas d’usage |
|---|---|---|
NULL | Non défini — déférer au plan / défaut | État par défaut pour tous les utilisateurs normaux |
0 | Illimité | Comptes administrateur / internes ; « cadeau VIP » |
N > 0 | Limite stricte à N | Bloquer un contrevenant sans annuler son abonnement payant ; allocation d’entreprise prépayée |
Chaîne de résolution des quotas — v1 (actuelle)
Pour toute requête authentifiée, le plafond est calculé de haut en bas — la première correspondance gagne :users.plan_id pour chaque utilisateur. Elle existe comme une défense en profondeur pour qu’un plan mal configuré ne lève jamais silencieusement le plafond d’un utilisateur.
Réinitialisation de la période
- Pour les utilisateurs payants,
quota_reset_atreflèteSubscription.current_period_end. Le gestionnaire webhookinvoice.payment_succeededdéfinittokens_used_this_period = 0et avancequota_reset_atà la fin de la nouvelle période à chaque renouvellement réussi. - Pour les utilisateurs Free (sans abonnement Stripe), un cron horaire réinitialise
tokens_used_this_periodà 0 à la limite d’un mois calendaire ancrée à la date d’attribution du plan. - Les changements de plan en cours de période ne réinitialisent pas le compteur — seuls les renouvellements le font. Cela prévient les exploits de recyclage de quota (« s’abonner → utiliser le quota Pro → annuler → s’abonner à nouveau »).
Application de la limite en cours de flux
- Vérification préalable à l’entrée de l’appel de chat : chemin le moins coûteux, bloque les demandes que l’utilisateur ne peut pas se permettre de démarrer.
- Pendant le streaming, le nombre de tokens en cours est réévalué à chaque chunk. Le dépassement du plafond ferme le flux avec un cadre terminateur structuré, et non une erreur réseau.
- Le frontend interprète le terminateur et affiche
<QuotaExceededDialog>avec un lien profond vers/settings?tab=billing. - Les réponses non-streaming retournent HTTP
402avec le corps{ code: "QUOTA_EXCEEDED", reset_at, upgrade_url }.
Fallback avec facturation désactivée
Quandsystem_settings.billing_enabled = FALSE :
- L’étape 2 de la chaîne est ignorée — la chaîne se réduit à
override → default → unlimited. /api/billing/*et/api/webhooks/striperetournent503.- L’onglet utilisateur
Plan & Billinget le groupe de navigation Admin → Billing sont masqués. - Toutes les données de facturation (abonnements, plans,
users.plan_id) sont conservées — la réactivation reprend à partir du même état sans migration.
Réservé : chaîne de quota v2 — Sièges d’équipe
Pas encore livré. Documenté ici pour que le travail v2 ait un point de destination connu.
Subscription.quantityporte le nombre de sièges (natif Stripe).- Le plan effectif d’un utilisateur se résout via l’appartenance à l’équipe avant de revenir à son plan personnel :
- Le quota est par siège (chaque membre de l’équipe obtient un
monthly_token_quotacomplet), et non un pool partagé. Les pools partagés créent un épuisement au premier arrivé, premier servi et sont contraires aux intérêts des clients. - La sémantique des remplacements reste inchangée — les administrateurs d’équipe peuvent toujours plafonner fortement les membres individuels via
users.token_quota = N, qui se situe au-dessus du plan d’équipe dans la chaîne.
Réservé : chaîne de quota v3 — allocation native Org (sans Stripe)
Pas encore livré. Réservé pour les déploiements sur site / entreprise qui allouent le quota en interne sans payer Stripe par utilisateur.
- Nouvelle table
org_quota_allocations(user_id, monthly_token_quota, org_id)distribue un budget parent entre les membres. - Les allocations sont par utilisateur, pas un pool partagé — chaque membre a un SLA individuel clair.
- Chaîne mise à jour :
max(), passum(). Un utilisateur Pro payant n’obtient jamais moins que ce qu’il a payé, même si son administrateur Org définit une allocation basse. Le quota payé via Stripe est sacrosaint.
Réservé : solde de crédits à l’usage (dimension v3 séparée)
Pas encore livré. Un axe distinct de la chaîne ci-dessus — les crédits sont un rechargement unique, pas un niveau d’abonnement.
- Nouvelle table
user_credits(user_id, balance_cents, currency)— financée via Stripe Checkoutmode='payment'. - Ordre de consommation : quota d’abonnement en premier, puis solde de crédits (la décrémentation des crédits ne commence qu’après l’épuisement de l’abonnement).
- Le solde de crédits n’est pas remboursable (standard industriel pour les prépayés).
- L’interface expose les deux barres :
Quota d'abonnement : 4,2M / 5M utilisés+Crédits : 7,40 $ restants.
Valeurs par défaut
Valeurs par défaut au moment du déploiement — toutes ajustables après installation sauf indication contraire.| Variable | Défaut | Ajustable via |
|---|---|---|
billing_plans.monthly_token_quota (Free) | 1,000,000 | Admin → Billing → Plans → Free → Edit |
billing_plans.monthly_token_quota (Pro) | 5,000,000 | Admin → Billing → Plans → Pro → Edit |
system_settings.default_token_quota | 1,000,000 (synchronisé avec Free à l’activation) | Admin → System Settings → Quotas |
system_settings.billing_enabled | FALSE | Admin → System Settings → Billing |
| Prix catalogue Pro | $20.00 USD / mois | Stripe Dashboard (objet price) |
| Événements webhook Stripe abonnés | 6 | Stripe Dashboard → Webhooks |
| TTL cache prix Stripe | 5 minutes | codé en dur dans stripe_client.py |
| Cron cycle de vie abonnement | toutes les heures | APScheduler dans web/main.py |
| Cron réinitialisation niveau gratuit | toutes les heures (limite calendaire mensuelle) | APScheduler dans web/main.py |
Modèle de tarification
V1 est un abonnement forfaitaire. Gratuit + Pro, facturation mensuelle, USD uniquement. Hors du champ d’application pour v1 (intentionnel, reporté à la feuille de route) :- Plan d’équipe (sièges Stripe /
subscription.quantity) - Facturation annuelle
- Présentation multi-devises
- Coupons / codes promotionnels
- Gestion des taxes (intégration Stripe Tax — nécessite un examen de conformité distinct)
- Mesure basée sur l’utilisation / frais de dépassement
- Solde de crédit à l’usage (recharge unique)
Dépannage
Le bouton bascule ne s'active pas — erreur 400
Le bouton bascule ne s'active pas — erreur 400
Le point de terminaison d’activation nécessite que
STRIPE_SECRET_KEY et STRIPE_WEBHOOK_SECRET soient définis. Confirmez qu’ils sont présents dans .env et que le backend a été redémarré après la modification.Le webhook retourne 503
Le webhook retourne 503
Soit la facturation est désactivée (le bouton bascule est OFF), soit la vérification de la signature de la requête a échoué (clé
STRIPE_WEBHOOK_SECRET non concordante). Consultez Stripe Dashboard → Webhooks → événements récents pour voir le corps d’erreur réel.L'utilisateur s'est abonné mais voit toujours le plan gratuit
L'utilisateur s'est abonné mais voit toujours le plan gratuit
Le webhook
checkout.session.completed n’a pas atteint votre backend. Vérifiez que l’URL du point de terminaison dans Stripe Dashboard correspond exactement à <your-domain>/api/webhooks/stripe, y compris le chemin de fin. Consultez les livraisons récentes du webhook pour les défaillances.L'utilisateur Pro voit l'ID de prix en mode test
L'utilisateur Pro voit l'ID de prix en mode test
La migration de seed écrit un ID de prix en mode test. Après l’activation de la facturation en production, mettez à jour le plan Pro pour utiliser votre
price_1*** en direct via Admin → Billing → Plans → Pro → Edit, ou via une UPDATE SQL directe.Les reçus sont marqués avec les paramètres par défaut de Stripe
Les reçus sont marqués avec les paramètres par défaut de Stripe
Configurez votre image de marque commerciale dans Stripe Dashboard → Settings → Branding. Ajoutez votre logo, le nom de votre entreprise (par exemple « FIM Labs Pte. Ltd. ») et votre adresse. Stripe applique ces paramètres à tous les reçus et factures générés automatiquement.
Pertes de change sur les versements
Pertes de change sur les versements
Si la devise par défaut de votre compte Stripe diffère de votre devise de facturation, Stripe convertit à chaque versement (écart de 1,5-2 %). Ajoutez une devise de règlement correspondante sous Settings → Bank accounts and currencies, attachez un compte bancaire dans la même devise, et Stripe acheminera les paiements dans la même devise sans conversion.