Commencez ici : la vue d’ensemble
MeterFlow répond à une seule question pour votre produit : « qui a utilisé combien de quoi — et combien cela lui coûte ? » Tout ce que vous voyez dans le tableau de bord existe pour répondre à cette question.
user-842 ou un e-mail).Comment les pièces s’assemblent
Pourquoi certains boutons « Créer » sont-ils grisés ?
Chaque boîte de dialogue désactive son bouton de confirmation tant que tous les champs obligatoires (marqués *) ne sont pas remplis — p. ex. « Create plan » reste désactivé tant que le plan n’a pas de Nom. Si un bouton semble bloqué, cherchez un champ obligatoire vide plus haut.
Nouvelle organisation conteneur
Le conteneur le plus externe — généralement votre entreprise. Tout le reste (projets, meters, plans…) vit à l’intérieur d’une organisation. Vous en avez reçu une automatiquement à l’inscription.
📍 Dashboard → le bouton « New organization » (proposé aussi à la première connexion, quand vous n’en avez pas encore)
- Name *
Le nom de votre entreprise ou de votre équipe. Une simple étiquette — modifiable plus tard.
- Billing email
Où iraient les factures et avis de facturation de votre compte MeterFlow. Facultatif ; le format est validé, mais rien n’est envoyé pour le vérifier.
finance@acme.dev. Ses deux produits deviendront deux projets à l’intérieur.Nouveau projet conteneur
Un projet = un produit ou un environnement à mesurer. Chaque meter, plan, clé API, solde client et événement d’usage appartient à exactement un projet — les projets ne voient jamais les données les uns des autres.
📍 Dashboard → le bouton « New project » dans l’en-tête du tableau Projects
- Organization *
À quelle organisation appartient le projet. Présélectionnée si vous en avez déjà une active.
- Name *
Le nom du produit, p. ex. « PixelForge AI ». Affiché partout dans le tableau de bord et dans le sélecteur de projet.
- Description
Texte libre, pour votre propre référence.
Générer une clé API accès
L’identifiant que votre application utilise pour parler à MeterFlow. Votre backend le transmet au SDK ; chaque événement d’usage, opération de crédits et appel d’abonnement est authentifié — et limité à un seul projet — par cette clé.
📍 Ouvrez un projet → API Keys → le bouton dans l’en-tête du tableau
- Key name *
Une étiquette pour vous rappeler où la clé est utilisée — « Backend de production », « Staging », « Tests CI ». Aucun effet technique.
- Environment
Les clés Live commencent par
mf_live_, les clés Test parmf_test_— et elles accèdent à deux jeux de données totalement séparés au sein du même projet. Les abonnements, crédits et usages créés avec une clé Test sont invisibles pour les clés Live (et inversement), tandis que vos meters et plans sont partagés : vos tests s’exécutent donc toujours contre votre vraie configuration de facturation. Utilisez des clés Test pour le développement, le staging et la CI ; les clés Live uniquement pour le vrai trafic de production.
mf_live_a1b2… une seule fois, et la placez dans les variables d’environnement de votre serveur : new MeterFlow({ apiKey: process.env.METERFLOW_KEY }). La liste du tableau de bord n’affichera plus jamais que le préfixe et les 4 derniers caractères.Les clés de test partagent-elles les limites de mon forfait MeterFlow ?
Non, le mode test a les siennes. Les événements de test disposent d’un dixième du quota mensuel de votre forfait MeterFlow — Drip 5 000 · Flow 20 000 · Stream 70 000 · Torrent 400 000 — et ne comptent jamais dans le quota live ; les packs d’événements n’augmentent que le quota live. Au-delà (plus la même marge de 10 % qu’en live), les écritures d’usage de test sont refusées avec un 403. Les clés de test font jusqu’à 60 requêtes par minute, les clés live 300. Les données de test expirent : les événements d’usage de test après 30 jours, et un abonnement de test sans usage depuis 90 jours, avec le solde et le registre de test de ce client. La page Billing et la fenêtre Usage de votre organisation affichent les événements de test du mois face à ce quota, à côté des événements live.
Nouveau meter concept clé
Un meter est la définition d’un compteur nommé : il déclare une chose de votre produit qui mérite d’être mesurée, et la façon de transformer les événements bruts en un nombre. Voyez-le comme la création d’une nouvelle colonne dans un rapport d’usage, avant même qu’il n’existe des données.
📍 Ouvrez un projet → Meters → le bouton dans l’en-tête du tableau
- Name *
L’étiquette lisible affichée dans le tableau de bord — « Images générées », « Secondes de rendu vidéo ». Pour les yeux humains uniquement.
- Event name *
La clé machine — et oui, elle est stockée dans la base de données et comparée à l’exactitude près. Quand votre application signale un usage, elle envoie un nom d’événement ; MeterFlow cherche dans ce projet le meter actif dont l’
event_namecorrespond exactement, casse comprise. S’il n’en existe aucun, l’événement est rejeté avec une erreur 404 (« No active meter found for event … ») et rien n’est enregistré. Chaque nom d’événement est unique au sein d’un projet. Convention : minuscules avec des points, p. ex.image.generated. - Aggregation type
Comment de nombreux événements individuels sont combinés en un seul nombre dans les récapitulatifs d’usage. Voir le tableau ci-dessous — c’est le cœur du meter.
- Aggregation field
Obligatoire pour Sum, Max, Min et Unique count ; refusé sur Count, qui ne lit aucune propriété. Il nomme une propriété de vos événements. Pour Sum, Max et Min, c’est là que la quantité est lue quand votre app omet
value— un meter dont le champ estsecondslitproperties.seconds; unvalueenvoyé par votre app l’emporte toujours, et un événement sans l’un ni l’autre compte pour 1. Pour Unique count, c’est la propriété dont on compte les valeurs distinctes —model, pour compter les modèles utilisés par un client. - Description
Texte libre pour votre équipe.
Les types d’agrégation, par l’exemple
Supposons que le client user-842 déclenche 4 événements ce mois-ci avec les valeurs 3, 10, 2, 10. Un seul nombre est rapporté par meter — lequel dépend du type d’agrégation :
| Type | À quelle question il répond | Résultat pour 3, 10, 2, 10 | Usage typique |
|---|---|---|---|
| Count | Combien de fois est-ce arrivé ? (valeurs ignorées) | 4 | Images générées, appels API, exports |
| Sum | Combien au total ? | 25 | Secondes de rendu, tokens consommés, Go transférés |
| Max | Quelle a été la plus grande valeur ? | 10 | Pic de tâches simultanées, plus gros envoi |
| Min | Quelle a été la plus petite valeur ? | 2 | Rarement pour facturer — surtout du diagnostic |
| Unique count | Combien de valeurs distinctes du champ d’agrégation sont apparues ? | 3 (3, 10, 2) | Modèles distincts utilisés, documents distincts touchés |
video.rendered · Agrégation Sum · Aggregation field seconds.Votre app termine le rendu d’un clip de 42 secondes pour
user-842 et signale l’événement video.rendered avec la valeur 42. Répétez quelques fois et la page d’usage du client affichera une ligne : Video render seconds — 3 événements — 117.Le nom d’événement doit-il correspondre à ce qu’envoie mon app ? Que se passe-t-il en cas de faute de frappe ?
Oui — exactement, casse comprise. Le nom d’événement du meter est stocké dans la base de données et sert d’étiquette d’adressage pour les événements entrants. Si votre app envoie video.render alors que le meter dit video.rendered, l’API répond 404 « No active meter found for event 'video.render' in this project » et l’événement n’est pas stocké. C’est voulu : une faute de frappe silencieuse laisserait fuir à jamais de l’usage non facturé. Créez d’abord le meter, puis commencez à envoyer des événements portant le même nom.
Puis-je changer le type d’agrégation plus tard ?
Non — après la création, seuls le nom, la description et l’indicateur actif sont modifiables. L’agrégation définit ce que signifie l’historique stocké ; la changer rétroactivement réécrirait le passé. S’il vous faut un autre calcul, créez un nouveau meter avec un nouveau nom d’événement.
Quand « Aggregation field » est-il obligatoire ?
Cela dépend du type. Le formulaire ne l’affiche que pour Sum, Max, Min et Unique count, et le serveur refuse une création qui le laisse vide pour ces types. Sur un meter Count, le formulaire le masque et le serveur le refuse s’il est envoyé : un comptage ne lit aucune propriété, le champ nommerait donc quelque chose que rien ne lit.
Nouveau plan concept clé
Un plan est un palier tarifaire — « Free », « Pro à 29 $/mois »… Il associe un prix récurrent à un ensemble de limites de meter qui disent quelle quantité de chaque fonction mesurée est incluse et ce qui se passe au-delà. Les clients sont rattachés à un plan via un abonnement.
📍 Ouvrez un projet → Plans → le bouton dans l’en-tête du tableau
- Name *
Le nom du palier — « Free », « Pro », « Enterprise ». Obligatoire ; le bouton de création reste désactivé tant qu’il n’est pas rempli.
- Description
Texte libre, p. ex. la phrase d’accroche marketing du palier.
- Price / Currency / Billing period
L’abonnement récurrent : Price est le montant (0 convient très bien à un palier gratuit), Currency un code comme
USD, et Billing period la fréquence — mensuel, annuel, hebdomadaire ou paiement unique. Figés après la création — modifier le plan ensuite ne peut pas les changer (créez plutôt un nouveau plan, pour que les conditions des abonnés existants ne changent pas en douce). - Trial days
Jours gratuits au début de chaque nouvel abonnement. Avec
14, un nouvel abonné passe 2 semaines au statut « trialing » avant le début de la période payante.0= pas d’essai. - Published
Si le plan existe pour vos clients. Laissé désactivé, c’est un brouillon : vous pouvez en définir le prix, les limites et les clés de fonctionnalité en plusieurs fois, et vos clés d’API ne le voient jamais — il est absent de la liste des plans du SDK, un identifiant divulgué répond
404, et personne ne peut y être abonné. Les nouveaux plans sont publiés ; désactivez-le pour en préparer un tranquillement, puis réactivez-le à la mise en vente. Le désactiver ensuite ferme la porte aux nouveaux abonnés sans toucher à ceux déjà en place. - Features
Les avantages oui/non inclus dans le plan — des clés courtes que vous inventez, comme
ssooupriority-support(minuscules, chiffres,-et_). Votre app demande au SDKentitlements.check(customerId, 'sso')et obtient oui uniquement pour les clients abonnés à un plan qui liste cette clé. Modifiables à tout moment, sur les plans nouveaux comme existants ; pour ce que vous comptez, utilisez plutôt une limite de meter ci-dessous.
Limites de meter — la section « + Add limit »
Chaque ligne de limite relie ce plan à un meter et répond à : quelle quantité de cette chose est incluse, et que se passe-t-il au-delà ?
- Meter *
À quelle grandeur mesurée cette limite s’applique. La liste déroulante affiche les meters que vous avez créés dans ce projet — ni plus, ni moins. Ce n’est pas un catalogue figé : toute nouvelle capacité du produit demande simplement un nouveau meter d’abord, et il apparaît ici aussitôt.
- Included units
Le volume compris dans le prix du plan, par période de facturation. « Pro inclut 500 images par mois » →
500. Sur une ligne Hard ou Soft, un chiffre est obligatoire avant de créer le plan — un volume vide ne plafonnerait rien — sauf si vous cochez Unlimited ci-dessous pour dire que c’était bien l’intention. Sur une ligne Metered, le vide est déjà une réponse : paiement à l’usage dès la première unité. - Unlimited
Uniquement sur les lignes Hard et Soft, et la façon explicite de dire « aucun plafond sur ce meter ». Coché, Included units est désactivé et vidé ; décoché, ce chiffre reste obligatoire. Les lignes Metered n’ont pas l’interrupteur, car le vide y signifie déjà quelque chose.
- Overage rate
Le prix en crédits par unité une fois que le client dépasse les unités incluses —
0.5signifie que chaque unité supplémentaire coûte un demi-crédit sur son solde. Il appartient au seul type Metered : le formulaire le demande sur une ligne Metered et le masque sur Hard et Soft, et l’API refuse un tarif sur une ligne Hard ou Soft (422). Une ligne Metered sans unités incluses ni tarif refuserait chaque unité, donc l’API refuse aussi cette ligne (422). - Limit type
Ce que répond
entitlements.check()du SDK une fois les unités incluses épuisées — l’appel que votre app fait avant d’effectuer le travail. Hard (bloquer) —check()répond non (hard_limit_reached) et votre app refuse l’action ; le client se heurte à un mur jusqu’à la période suivante ou une montée en gamme. Soft (avertir) —check()répond toujours oui, signalésoft_limit_exceeded: votre app laisse passer et incite le client à monter en gamme. Metered (facturer) —check()répond oui tant que les crédits du client couvrent les unités supplémentaires, et chaque unité supplémentaire est prélevée sur son solde au tarif de dépassement ; quand le solde ne suffit plus, la réponse est non (insufficient_credits). Metered est l’option « paiement à l’usage » et la seule qui déplace de l’argent (des crédits) toute seule. Une limite Metered est refusée sur un meter Max ou Min (422) : une valeur maximale ou minimale ne se facture pas à l’unité. Sur une ligne Metered, un plafond de dépenses sur l’abonnement du client peut faire répondre non àcheck()avant que le solde ne s’épuise (spend_cap_reached). Hard et Soft déclenchent le webhooklimit.reachedune fois par période de facturation, la première fois que la ligne est franchie. Dans tous les cas MeterFlow continue d’enregistrer les événements que votre app envoie — la barrière, c’estcheck(), dans votre code.
USD · Mensuel · 14 jours d’essai · Published ✓Limite 1 : meter Images générées, incluses 500, type Hard → après 500 images,
check() répond non et votre app cesse de générer jusqu’au mois suivant ou à une montée en gamme.Limite 2 : meter Secondes de rendu vidéo, incluses 1 000, dépassement 0,02, type Metered → au-delà de 1 000 secondes, chaque seconde supplémentaire coûte en silence 0,02 crédit du portefeuille du client.
Pourquoi « + Add limit » est-il grisé ?
Parce que le projet n’a pas encore de meter — une limite est toujours un plafond sur un meter ; sans meter, il n’y a rien à quoi la rattacher. La boîte de dialogue affiche l’indice « Create meters first to attach limits to this plan. » Allez dans Meters → New meter, créez-en au moins un, puis rouvrez cette boîte de dialogue.
Pourquoi la liste Meter ne montre-t-elle que quelques options ? Et si mon produit a quelque chose de nouveau ?
La liste déroulante, ce sont simplement vos propres meters du projet sélectionné. Dans les données de démonstration, il se trouve que ce sont « Images generated », « Video render seconds », « Upscales processed », « Peak GPU memory » et « Active prompters » — mais cette liste vous appartient et peut grandir. Elle ne restreint pas ce que les clients peuvent faire : les clients ne choisissent jamais de meters ; c’est vous qui définissez des meters pour tout ce que fait votre produit. Une nouvelle fonctionnalité demain ? Créez un meter pour elle et il apparaîtra ici.
Un client a dépassé une limite Hard — pourquoi ses événements sont-ils encore enregistrés ?
Parce que MeterFlow ne décide jamais à la place de votre produit ce qu’un utilisateur peut faire — c’est votre app qui décide, en appelant entitlements.check() avant l’action. Une limite Hard fait répondre non à cet appel ; si votre app saute l’appel et fait le travail quand même, l’événement d’usage est tout de même accepté et stocké, pour que votre historique et toute facturation metered restent honnêtes. Voyez la limite comme la règle et check() comme le videur à la porte : MeterFlow écrit la règle, votre code tient la porte.
Que répond check() quand MeterFlow ne répond pas ?
Depuis meterflow 0.10.0 (npm) / 0.5.0 (PyPI), le SDK continue de répondre. Il réutilise chaque réponse pendant les 15 secondes que l’API autorise, et un enregistrement d’usage, un crédit ou un débit pour un client rend obsolètes les réponses de ce client. Si MeterFlow est injoignable — une erreur réseau, un délai dépassé, ou un 5xx ou 429 après les nouvelles tentatives —, check() donne la dernière réponse, marquée stale: true ; à défaut, la valeur par défaut que vous fixez par fonctionnalité dans entitlementDefaults ('allow' ou 'deny', '*' pour le reste), avec reason: 'offline_default' ; sans l’une ni l’autre, il lève une erreur. Votre hook onError est prévenu en premier. Un 401, 403, 404 ou 422 est une vraie réponse et n’est jamais masqué.
Pourquoi ne puis-je pas modifier le prix ou les limites d’un plan existant ?
C’est voulu : les abonnés existants ont souscrit à ces conditions, donc le prix, la devise, la période de facturation et les limites de meter sont gelés à la création. La modification d’un plan ne peut changer que son nom, sa description, ses jours d’essai, son état de publication, son indicateur actif et ses clés de fonctionnalités. Pour changer les tarifs, créez un nouveau plan (p. ex. « Pro 2026 ») et orientez-y les nouveaux clients.
Nouvel abonnement relie client ⇄ plan
Un abonnement rattache un de vos clients à un plan. À partir de ce moment, son usage est jugé à l’aune des limites de meter de ce plan. En production, c’est généralement votre backend qui le crée via le SDK à l’instant où quelqu’un choisit un palier au paiement — la boîte de dialogue fait la même chose à la main.
📍 Ouvrez un projet → Subscriptions → le bouton dans l’en-tête du tableau
- Customer ID *
Votre propre identifiant du client final — n’importe quelle chaîne de votre choix : un ID utilisateur de votre base (
user-842), un e-mail, un slug de tenant. MeterFlow ne le valide contre rien ; ce que vous envoyez désigne le propriétaire de l’abonnement. Utilisez le même ID partout (abonnements, crédits, usage), sinon les pièces ne se relieront pas. - Plan *
Sur quel palier tarifaire il se trouve — la liste affiche les plans de ce projet. Si le plan a des jours d’essai, l’abonnement démarre en « trialing » ; sinon en « active ».
user-842 clique sur « Passer à Pro » dans votre app → votre backend appelle subscriptions.create({ customer_external_id: 'user-842', plan_id: … }). Chaque événement d’usage de user-842 est désormais confronté aux limites de Pro.Et si un client n’a pas d’abonnement — ses événements sont-ils perdus ?
Non. Les événements sont toujours enregistrés et apparaissent toujours dans les récapitulatifs d’usage. Sans abonnement actif ou en essai, rien n’est facturé, et entitlements.check() répond non avec no_subscription — une app qui demande d’abord ne laissera donc pas passer l’action. La logique de facturation s’enclenche dès qu’un abonnement existe.
Puis-je plafonner ce qu’un client dépense sur une période ?
Oui — définissez spend_cap, en crédits, sur l’abonnement via le SDK ou l’API ; vide signifie aucun plafond. Une fois les dépenses de la période arrivées au plafond, l’usage enregistré cesse de consommer des crédits, un credits.deduct() qui le dépasse est refusé avec un 409, entitlements.check() répond non avec spend_cap_reached avant qu’une action facturée ne le franchisse, et le webhook cap.reached se déclenche une fois sur la période.
Un client a résilié — peut-il revenir ?
Oui, sur le même abonnement. Remettez son statut à active — subscriptions.update(id, { status: 'active' }), ou Reactivate sur sa ligne. Si l’ancienne période est terminée, une nouvelle commence tout de suite, avec les crédits de période de la formule ; un essai résilié avant sa fin reprend en essai. Une formule désactivée ou dépubliée entre-temps ne reprend personne (409), et un abonnement géré par le connecteur de votre fournisseur de paiement revient par le fournisseur, pas ici.
Puis-je retrouver l’abonnement d’un client dans une longue liste ?
Oui. La page Subscriptions a un filtre par client et des puces de statut, et le SDK accepte les deux mêmes : subscriptions.list({ q, status }). q trouve tout ID client qui le contient ; status vaut active, trialing, past_due, paused, canceled ou expired. Le serveur filtre avant de découper la page, donc chaque page ne contient que des correspondances. Dans le SDK depuis meterflow 0.9.0 (npm) / 0.4.0 (PyPI). Depuis 0.12.0 / 0.7.0, il accepte aussi sort — created_at (par défaut), customer_external_id ou status — et order, desc ou asc ; passez les deux avec chaque next_cursor.
La page client un client, en entier
Chaque client pour qui votre app a écrit quelque chose — un abonnement, un solde de crédits ou un événement d’usage — est une ligne de la page Customers. Ouvrez-le et sa page raconte toute l’histoire : qui il est, sa formule, et quatre onglets.
📍 Ouvrez un projet → Customers → la ligne du client
- Credits
Son solde et chaque ligne de registre derrière, avec Grant et Deduct — les fenêtres expliquées plus bas.
- Usage
Ce qu’il a utilisé, meter par meter.
- Subscription
Sa formule et son statut, avec Cancel ou Reactivate.
- Entitlements
Ce que sa formule accorde, fonctionnalité par fonctionnalité : ce qui reste de chaque allocation facturée, et la raison pour laquelle une fonctionnalité est refusée, exactement comme
entitlements.check()la donnerait.
Créditer / Débiter des crédits le portefeuille
Les crédits sont un solde prépayé par client (par projet) — pensez à un portefeuille ou à une carte rechargeable. C’est vous qui décidez de la valeur d’un crédit dans votre tarification. Le dépassement « metered » puise dans ce portefeuille automatiquement ; les deux boîtes de dialogue déplacent des crédits à la main.
📍 Ouvrez un projet → Customers → la ligne du client → onglet Credits → « Grant » / « Deduct »
- Amount *
Combien de crédits ajouter (Grant) ou retirer (Deduct). Doit être supérieur à zéro — la direction est décidée par le bouton qui a ouvert la boîte de dialogue, pas par un signe moins.
- Description
Une note facultative enregistrée sur la ligne du registre — « Bonus de bienvenue », « Remboursement suite à l’incident », « Geste commercial ». Votre futur vous dira merci.
user-842 reçoit un crédit de 100 (« Bonus de bienvenue »). Il rend 2 500 secondes de vidéo sur un plan avec 1 000 incluses et un dépassement metered de 0,02 → 1 500 × 0,02 = 30 crédits débités automatiquement. Solde : 70.L’usage de ce client consommera-t-il son solde ?
Demandez au solde : credits.balance() répond avec usage_draws_credits. true — sa formule facture l’usage au-delà de l’allocation, l’usage enregistré consomme donc des crédits tout seul. false — seul un credits.deduct() explicite le fait bouger. null — il n’a pas d’abonnement actif ou en essai.
Mon app peut-elle recharger un client automatiquement ?
MeterFlow dit à votre app quand et combien ; votre app débite le client, puis accorde les crédits. Donnez à un endpoint de webhook un seuil de solde bas et il reçoit balance.low quand le solde d’un client passe en dessous — par une déduction ou par un usage facturé — et balance.topped_up quand un crédit accordé le fait repasser au-dessus. Définissez topup_amount sur l’abonnement du client et balance.low le transmet comme suggested_topup. Définissez max_topups_per_window et un crédit au-delà de ce nombre sur une même période est refusé avec un 409, pour qu’une boucle dans votre code ne puisse pas recharger sans fin.
Puis-je mettre des crédits de côté pour une longue tâche ?
Oui, à partir de meterflow 0.11.0 (npm) / 0.6.0 (PyPI). credits.reserve() bloque une partie du solde d’un client pendant ttl_seconds — 5 minutes sauf indication contraire, un jour au plus. Le solde ne bouge pas, mais rien d’autre ne peut dépenser ce qui est bloqué : un credits.deduct(), l’usage facturé, un check() qui débiterait et un autre blocage ne voient que les crédits disponibles, c’est-à-dire le solde moins ce qui est bloqué. Une fois la tâche finie, credits.confirmReservation(id, { amount }) prend tout ou partie du blocage en un débit normal dans le registre et libère le reste, et credits.releaseReservation(id) le libère entièrement ; un blocage oublié se libère tout seul à son expiration. credits.balance() affiche reserved et available à côté du solde, et les crédits bloqués comptent aussi dans le plafond de dépenses.
Montrez leur solde à vos clients
MeterFlow héberge une page qui montre à l’un de vos clients ses propres crédits : le solde, les dernières lignes du registre qui le composent, sa formule avec ce qui reste de chaque allocation facturée, et ce qu’il a utilisé hors formule. Vous n’avez ni à la construire ni à l’héberger — votre serveur remet un lien au client.
link.url. Le lien porte son propre jeton de courte durée : votre clé API ne quitte jamais votre serveur. En Python, c’est client.portal.create_session(…), avec les mêmes champs. const link = await client.portal.createSession({
customer_external_id: 'user-842',
topup_url: 'https://acme.dev/billing',
return_url: 'https://acme.dev/app',
expires_in_minutes: 60,
}); 3. Buy more ouvre topup_url — votre propre page de paiement, exactement telle que vous l’avez saisie, sans rien y ajouter. C’est facultatif : sans topup_url, ni sur le lien ni dans les valeurs par défaut du projet, la page n’a pas de bouton Buy more. ← Back mène à return_url, facultatif de la même façon. 4. MeterFlow n’encaisse jamais le paiement : quand votre checkout en signale un, votre serveur appelle credits.grant() et la page affiche le nouveau solde. - Le lien
Il dure 60 minutes, sauf si vous fixez
expires_in_minutes— 24 heures au plus — et ne peut pas être retiré avant. Il ouvre la page d’un seul client, en lecture seule : il ne peut rien modifier ni montrer un autre client. Un lien créé avec une clé de test (mf_test_…) affiche des données de test, sous un badge Test data. - Votre apparence
Ouvrez un projet → Portal : nom de l’entreprise, logo, thème clair / sombre / automatique, couleurs et rayon des coins, ainsi que les valeurs par défaut — URL de Buy more, URL de Back et durée — pour les liens qui ne les précisent pas. Une case à cocher applique l’apparence à tous les projets de l’organisation.
- Un lien à la main
Dans le tableau Customers, l’action de ligne Create a portal link crée un lien pour ce client sans code — tout comme Portal link dans son onglet Credits.
Enregistrer un événement d’usage concept clé
Un événement d’usage = « ce client vient de faire cette chose, dans cette quantité. » En production, votre application les envoie automatiquement via le SDK, des milliers de fois par jour ; la boîte de dialogue existe pour en injecter un à la main, pour les tests et les démos.
📍 Ouvrez un projet → Usage → recherchez un client → « Record event »
- Event name *
Doit correspondre exactement au nom d’événement d’un meter existant et actif dans ce projet (sensible à la casse). C’est cette correspondance qui indique à MeterFlow quel compteur cet événement alimente. Aucun meter correspondant → l’API rejette l’événement avec un 404 et rien n’est stocké. Vérifiez l’orthographe exacte sur la page Meters.
- Customer ID *
Lequel de vos clients l’a fait — la même chaîne d’ID libre que pour les abonnements et les crédits. La cohérence est primordiale :
user-842etUSER-842sont deux clients différents. - Value
La quantité — facultative. Omise, un meter Sum, Max ou Min la lit dans la propriété de l’événement que nomme son champ d’agrégation (votre app l’envoie dans
properties) ; sinon l’événement compte pour1. Son sens dépend de l’agrégation du meter : pour un meter Count la valeur est ignorée (chaque événement compte comme une occurrence) ; pour Sum c’est la quantité à ajouter (42 secondes, 1 300 tokens) ; pour Max/Min c’est la mesure comparée ; un meter Unique count compte les valeurs distinctes de son champ d’agrégation.
video.rendered → « Video render seconds ». 2. L’événement est stocké définitivement (brut — l’agrégation a lieu plus tard, à la lecture). 3. En arrière-plan, MeterFlow vérifie si le client a un abonnement actif et si ce plan a une limite sur ce meter. 4. Si la limite est Metered, les unités au-delà de l’allocation incluse sont prélevées au tarif de dépassement sur le solde de crédits du client et une ligne de registre est écrite — jusqu’au plafond de dépenses de la période, si l’abonnement en a un ; si elle est Hard ou Soft et que cet événement est le premier à franchir les unités incluses sur la période, le webhook limit.reached se déclenche une fois. Ici l’événement n’est jamais refusé — refuser, c’est le rôle de check(), dans votre app. 5. Le récapitulatif d’usage affiché sur cette page est recalculé à partir des événements bruts selon le type d’agrégation du meter.J’ai enregistré un événement et j’ai eu une erreur — pourquoi ?
Presque toujours le nom d’événement : il ne correspond exactement à aucun meter actif de ce projet. L’erreur le dit mot pour mot — « No active meter found for event '…' in this project. » Copiez le nom d’événement depuis la page Meters plutôt que de le retaper. Notez aussi que les meters sont propres à chaque projet : un meter d’un autre projet ne compte pas.
Si mon app rejoue une requête, l’événement sera-t-il compté deux fois ?
Pas si vous utilisez le SDK correctement : chaque écriture accepte une clé d’idempotence — une étiquette unique pour « cette action précise ». Si la même clé arrive deux fois (une nouvelle tentative après un raté réseau), MeterFlow la reconnaît et renvoie le résultat d’origine au lieu de stocker un doublon. La boîte de dialogue manuelle n’en envoie pas : appuyer deux fois sur Record à la main crée donc bel et bien deux événements.
Faut-il un événement par appel d’API ?
Non — et en général mieux vaut éviter. Value est une quantité, et un meter Sum additionne ces quantités : un seul événement avec la valeur 1 300 compte pour un événement sur le quota mensuel de votre forfait et 1 300 unités sur le meter. Un événement par appel d’API, c’est ce qui épuise un forfait : 1 000 utilisateurs faisant 100 appels par jour, cela fait environ 3 millions d’événements par mois.
Agrégez dans votre propre application sur une fenêtre que vous pourriez vous permettre de perdre en cas de plantage — une requête, un traitement, une minute — puis enregistrez un unique événement avec le total. Les envoyer en batch n’est pas la même chose : un batch de 100 économise des requêtes HTTP, mais chaque événement reste un enregistrement à part et continue de compter.
Cela vaut pour les meters Sum. Un meter Count ignore la valeur et compte les occurrences : là, chaque occurrence a bien besoin de son propre événement. Dans les deux cas, la facture ne change pour personne : une limite Metered facture à l’unité.
Puis-je enregistrer un usage survenu il y a un moment ?
Seulement dans les cinq minutes. Le timestamp d’un événement peut être au plus 5 minutes dans le passé et 60 secondes dans le futur ; hors de cette fenêtre, l’API le refuse avec une 422 et n’enregistre rien. Sans timestamp, l’événement porte l’heure de son arrivée. Enregistrez l’usage au moment où il se produit : un usage plus ancien ne peut pas être chargé après coup.
Nouveau webhook notifications
Un webhook est une URL sur votre serveur que MeterFlow appelle quand quelque chose se passe dans votre projet — des crédits accordés, une limite atteinte, un solde qui baisse. Chaque appel est signé, et relancé si votre serveur ne répond pas.
📍 Ouvrez un projet → Webhooks → le bouton dans l’en-tête du tableau
- Endpoint URL *
Où MeterFlow envoie les événements, p. ex.
https://api.acme.dev/meterflow. - Events to deliver
Les événements dont cet endpoint est informé :
usage.recorded,credit.granted,credit.deducted(une déduction, ou un usage Metered facturé — sontransaction_typedit lequel),subscription.created,.updated,.renewedet.canceled,limit.reached,cap.reached,balance.exhausted, et les deux ci-dessous. - Low balance threshold
Un solde, en crédits. Définissez-le et l’endpoint reçoit aussi
balance.lowquand le solde d’un client passe en dessous etbalance.topped_upquand il repasse au-dessus ; effacez-le et les deux s’arrêtent. Les deux événements vont et viennent avec le seuil, car sans ligne on ne peut pas prévenir un endpoint d’un franchissement.
webhooks.list(), webhooks.deliveries(id) pour les 100 plus récents, et webhooks.deliveryPage(id) (en Python delivery_page) pour chaque tentative, une page à la fois, des plus récentes aux plus anciennes. Le journal de livraisons du tableau de bord se pagine de la même façon. Créer et modifier les endpoints se fait ici, dans le tableau de bord.Connecter votre fournisseur de paiement votre facturation
Si vos clients vous paient via Paddle, Polar, Lemon Squeezy, Chargebee ou Razorpay, un connecteur laisse ce compte piloter MeterFlow : votre fournisseur appelle MeterFlow à chaque changement d’abonnement et chaque paiement, et l’abonnement ou le crédit correspondant apparaît ici — sans code dans votre app.
📍 Ouvrez un projet → Connectors → le bouton dans l’en-tête du tableau
- Provider *
Celui des cinq par lequel vos clients paient.
- Which of your accounts
Live — le compte de production de votre fournisseur, qui écrit des données live ; Test — son bac à sable, qui écrit des données de test. Un connecteur par fournisseur et par compte.
- Signing secret *
Le secret avec lequel votre fournisseur signe ses webhooks — pour Chargebee, qui ne signe rien, l’identifiant et le mot de passe qu’il envoie à la place. Il est vérifié à chaque appel et jamais réaffiché : le tableau n’en montre que les quatre derniers caractères.
Une fois créé
- L’URL du webhook
Affichée dès que le connecteur est créé : collez-la dans les réglages webhook de votre fournisseur.
- Correspondances prix → formule
Quel prix de votre fournisseur — un produit sur Polar, une variante sur Lemon Squeezy, une formule sur Chargebee et Razorpay — place un client sur laquelle de vos formules. Un événement pour un prix sans correspondance est enregistré et ne change rien.
- Journal de livraison
Chaque événement reçu par le connecteur, avec ce qu’il en a fait en une phrase : ce qui a été appliqué, et pourquoi le reste a été ignoré.
Membres et invitations accès de l’équipe
La page Members de votre organisation liste qui en fait partie — avec son rôle et qui l’a invité — et les invitations encore en attente. Un owner ou un admin invite par email ; la personne n’a pas encore besoin d’un compte MeterFlow.
📍 Members dans la barre latérale, à côté de Billing → « Invite member » (aussi une action de ligne sur les organisations du Dashboard)
- Email *
Où part l’invitation. MeterFlow envoie un lien qui fonctionne une fois, pendant 7 jours, pour cette adresse seulement : la personne l’ouvre et rejoint — depuis son compte, ou en en créant un via le lien.
- Role
Admin — réglages de l’organisation, invitations, clés API, webhooks, connecteurs, projets et facturation. Member — celui qui travaille au quotidien : meters, formules et les pages Subscriptions, Usage et client. Viewer — lecture seule. Il n’y a volontairement pas d’option « owner » : la propriété ne se donne pas par invitation.
- Invitations en attente
Listées sur la page Members jusqu’à ce qu’elles soient acceptées, révoquées ou expirées. Revoke coupe le lien aussitôt.
- Change role · Remove
Sur la ligne de chaque membre, pour les owners et admins. L’appartenance de l’owner et la vôtre ne se changent pas là. Retirer quelqu’un lui ôte l’accès ; son compte, et ce qu’il a créé, restent.
dana@acme.dev comme Viewer pour que l’équipe finance puisse suivre l’usage et les soldes sans pouvoir changer les tarifs.