Hier starten: das große Ganze
MeterFlow beantwortet für dein Produkt genau eine Frage: „Wer hat wie viel wovon genutzt — und was kostet ihn das?“ Alles im Dashboard existiert, um diese Frage zu beantworten.
user-842 oder eine E-Mail).Wie die Teile zusammenspielen
Warum sind manche „Erstellen“-Buttons ausgegraut?
Jeder Dialog deaktiviert seinen Bestätigen-Button, bis alle Pflichtfelder (mit * markiert) ausgefüllt sind — z. B. bleibt „Create plan“ deaktiviert, bis der Plan einen Namen hat. Wenn ein Button festzuhängen scheint, suche weiter oben nach einem leeren Pflichtfeld.
Neue Organisation Container
Der äußerste Container — normalerweise dein Unternehmen. Alles andere (Projekte, Meter, Pläne…) lebt innerhalb einer Organisation. Eine hast du bei der Registrierung automatisch bekommen.
📍 Dashboard → der Button „New organization“ (wird auch beim ersten Login angeboten, wenn du noch keine hast)
- Name *
Der Name deines Unternehmens oder Teams. Reines Etikett — du kannst ihn später ändern.
- Billing email
Wohin Rechnungen und Abrechnungshinweise für dein MeterFlow-Konto gehen würden. Optional; das Format wird geprüft, aber es wird nichts zur Bestätigung verschickt.
finance@acme.dev. Ihre zwei Produkte werden darin zu zwei Projekten.Neues Projekt Container
Ein Projekt = ein Produkt oder eine Umgebung, die du messen willst. Jeder Meter, Plan, API-Schlüssel, Kundensaldo und jedes Nutzungsereignis gehört zu genau einem Projekt — Projekte sehen niemals die Daten der anderen.
📍 Dashboard → der Button „New project“ im Kopf der Projects-Tabelle
- Organization *
Zu welcher Organisation das Projekt gehört. Vorausgewählt, wenn bereits eine aktiv ist.
- Name *
Der Produktname, z. B. „PixelForge AI“. Erscheint überall im Dashboard und im Projektumschalter.
- Description
Freitext für deine eigene Referenz.
API-Schlüssel erzeugen Zugang
Der Berechtigungsnachweis, mit dem deine Anwendung mit MeterFlow spricht. Dein Backend übergibt ihn dem SDK; jedes Nutzungsereignis, jede Credit-Operation und jeder Abonnement-Aufruf wird durch diesen Schlüssel authentifiziert — und auf genau ein Projekt begrenzt.
📍 Projekt öffnen → API Keys → der Button im Tabellenkopf
- Key name *
Ein Etikett, damit du weißt, wo der Schlüssel verwendet wird — „Produktions-Backend“, „Staging“, „CI-Tests“. Ohne technische Wirkung.
- Environment
Live-Schlüssel beginnen mit
mf_live_, Test-Schlüssel mitmf_test_— und sie greifen auf zwei vollständig getrennte Datensätze im selben Projekt zu. Abonnements, Guthaben und Verbrauch, die mit einem Test-Schlüssel erzeugt wurden, sind für Live-Schlüssel unsichtbar (und umgekehrt), während Meter und Pläne geteilt werden — Tests laufen also immer gegen deine echte Abrechnungskonfiguration. Nutze Test-Schlüssel für Entwicklung, Staging und CI; Live-Schlüssel nur für echten Produktionsverkehr.
mf_live_a1b2… und legst ihn in die Umgebungsvariablen deines Servers: new MeterFlow({ apiKey: process.env.METERFLOW_KEY }). Die Dashboard-Liste zeigt für immer nur das Präfix und die letzten 4 Zeichen.Teilen Test-Keys die Limits meines MeterFlow-Plans?
Nein, der Testmodus hat eigene. Test-Ereignisse bekommen ein Zehntel des monatlichen Kontingents deines MeterFlow-Plans — Drip 5 000 · Flow 20 000 · Stream 70 000 · Torrent 400 000 — und zählen nie zum Live-Kontingent; Event-Pakete erhöhen nur das Live-Kontingent. Darüber hinaus (plus dieselben 10 % Kulanz wie live) werden Test-Nutzungsmeldungen mit einem 403 abgelehnt. Test-Keys stellen bis zu 60 Anfragen pro Minute, Live-Keys 300. Testdaten laufen ab: Test-Nutzungsereignisse nach 30 Tagen, und ein Test-Abonnement ohne Nutzung seit 90 Tagen, zusammen mit Test-Guthaben und Test-Journal dieses Kunden. Die Billing-Seite und der Usage-Dialog deiner Organisation zeigen die Test-Ereignisse des Monats gegen dieses Kontingent, neben den Live-Ereignissen.
Neuer Meter Kernkonzept
Ein Meter ist die Definition eines benannten Zählers: Er erklärt eine Sache in deinem Produkt für messenswert und legt fest, wie rohe Ereignisse in eine Zahl verwandelt werden. Stell ihn dir wie eine neue Spalte in einem Nutzungsbericht vor, bevor es überhaupt Daten gibt.
📍 Projekt öffnen → Meters → der Button im Tabellenkopf
- Name *
Das menschenfreundliche Etikett im Dashboard — „Erzeugte Bilder“, „Video-Render-Sekunden“. Nur für menschliche Augen.
- Event name *
Der Maschinenschlüssel — und ja, er wird in der Datenbank gespeichert und exakt abgeglichen. Wenn deine Anwendung Nutzung meldet, sendet sie einen Ereignisnamen; MeterFlow sucht in dem Projekt den aktiven Meter, dessen
event_nameexakt übereinstimmt, Groß-/Kleinschreibung inklusive. Existiert keiner, wird das Ereignis mit einem 404-Fehler abgelehnt („No active meter found for event …“) und nichts wird erfasst. Jeder Ereignisname ist innerhalb eines Projekts eindeutig. Konvention: klein mit Punkten, z. B.image.generated. - Aggregation type
Wie viele einzelne Ereignisse in den Nutzungsübersichten zu einer Zahl zusammengefasst werden. Siehe Tabelle unten — das ist das Herz des Meters.
- Aggregation field
Pflicht bei Sum, Max, Min und Unique count; bei Count abgelehnt, denn Count liest keine Eigenschaft. Es benennt eine Eigenschaft deiner Ereignisse. Bei Sum, Max und Min kommt die Menge von dort, wenn deine App
valueweglässt — ein Meter mit dem Feldsecondsliestproperties.seconds; ein von deiner App gesendetesvaluehat immer Vorrang, und ein Ereignis ohne beides zählt als 1. Bei Unique count ist es die Eigenschaft, deren verschiedene Werte gezählt werden —model, um die Modelle zu zählen, die ein Kunde genutzt hat. - Description
Freitext für dein Team.
Die Aggregationstypen, an einem Beispiel
Angenommen, der Kunde user-842 löst diesen Monat 4 Ereignisse mit den Werten 3, 10, 2, 10 aus. Pro Meter wird eine Zahl gemeldet — welche, hängt vom Aggregationstyp ab:
| Typ | Welche Frage er beantwortet | Ergebnis für 3, 10, 2, 10 | Typische Verwendung |
|---|---|---|---|
| Count | Wie oft ist es passiert? (Werte ignoriert) | 4 | Erzeugte Bilder, API-Aufrufe, Exporte |
| Sum | Wie viel insgesamt? | 25 | Gerenderte Sekunden, verbrauchte Tokens, übertragene GB |
| Max | Was war der größte Einzelwert? | 10 | Spitze gleichzeitiger Jobs, größter Upload |
| Min | Was war der kleinste Einzelwert? | 2 | Selten zur Abrechnung — eher Diagnose |
| Unique count | Wie viele verschiedene Werte des Aggregationsfelds kamen vor? | 3 (3, 10, 2) | Verschiedene genutzte Modelle, verschiedene bearbeitete Dokumente |
video.rendered · Aggregation Sum · Aggregation field seconds.Deine App rendert einen 42-Sekunden-Clip für
user-842 fertig und meldet das Ereignis video.rendered mit dem Wert 42. Ein paar Mal wiederholt, zeigt die Nutzungsseite des Kunden eine Zeile: Video render seconds — 3 Ereignisse — 117.Muss der Ereignisname zu dem passen, was meine App sendet? Was passiert bei einem Tippfehler?
Ja — exakt, inklusive Groß-/Kleinschreibung. Der Ereignisname des Meters wird in der Datenbank gespeichert und wirkt wie das Adressetikett für eingehende Ereignisse. Sendet deine App video.render, der Meter heißt aber video.rendered, antwortet die API mit 404 „No active meter found for event 'video.render' in this project“ und das Ereignis wird nicht gespeichert. Das ist Absicht: Ein stiller Tippfehler würde für immer unabgerechnete Nutzung durchsickern lassen. Erst den Meter anlegen, dann Ereignisse mit demselben Namen senden.
Kann ich den Aggregationstyp später ändern?
Nein — nach der Erstellung sind nur Name, Beschreibung und Aktiv-Flag änderbar. Die Aggregation definiert, was die gespeicherte Historie bedeutet; sie rückwirkend zu ändern, würde die Vergangenheit umschreiben. Brauchst du eine andere Rechnung, lege einen neuen Meter mit neuem Ereignisnamen an.
Wann ist „Aggregation field“ Pflicht?
Das hängt vom Typ ab. Das Formular zeigt es nur bei Sum, Max, Min und Unique count, und der Server lehnt eine Erstellung ab, die es bei diesen Typen leer lässt. Bei einem Count-Meter blendet das Formular es aus, und der Server lehnt es ab, wenn es mitgeschickt wird: Ein Zählen liest keine Eigenschaft, das Feld würde also etwas benennen, das niemand liest.
Neuer Plan Kernkonzept
Ein Plan ist eine Preisstufe — „Free“, „Pro für 29 $/Monat“… Er bündelt einen wiederkehrenden Preis mit einer Reihe von Meter-Limits, die festlegen, wie viel jeder gemessenen Funktion inklusive ist und was darüber hinaus passiert. Kunden werden über ein Abonnement an einen Plan gebunden.
📍 Projekt öffnen → Plans → der Button im Tabellenkopf
- Name *
Der Name der Stufe — „Free“, „Pro“, „Enterprise“. Pflicht; der Erstellen-Button bleibt deaktiviert, bis er ausgefüllt ist.
- Description
Freitext, z. B. der Marketing-Einzeiler der Stufe.
- Price / Currency / Billing period
Die wiederkehrende Abogebühr: Price ist der Betrag (0 ist für eine Gratis-Stufe völlig in Ordnung), Currency ein Code wie
USD, und Billing period der Rhythmus — monatlich, jährlich, wöchentlich oder einmalig. Nach der Erstellung fest — späteres Bearbeiten des Plans kann sie nicht ändern (lege stattdessen einen neuen Plan an, damit sich die Konditionen bestehender Abonnenten nicht stillschweigend ändern). - Trial days
Gratistage am Anfang jedes neuen Abonnements. Mit
14verbringt ein neuer Abonnent 2 Wochen im Status „trialing“, bevor die bezahlte Periode beginnt.0= keine Testphase. - Published
Ob der Plan für deine Kunden überhaupt existiert. Ausgeschaltet ist er ein Entwurf: Du kannst Preis, Limits und Feature-Keys über mehrere Sitzungen festlegen, und deine API-Schlüssel sehen ihn nie — er fehlt in der Planliste des SDK, eine durchgesickerte Plan-ID antwortet
404, und niemand kann ihn abonnieren. Neue Pläne sind veröffentlicht; schalte es aus, um einen in Ruhe vorzubereiten, und wieder ein, wenn er verkauft wird. Später wieder auszuschalten schließt die Tür für neue Abonnenten, ohne die bestehenden anzutasten. - Features
Die An/Aus-Vorteile, die der Plan enthält — kurze Schlüssel, die du dir ausdenkst, etwa
ssooderpriority-support(Kleinbuchstaben, Ziffern,-und_). Deine App fragt das SDKentitlements.check(customerId, 'sso')und bekommt nur für Kunden auf einem Plan, der den Schlüssel führt, ein Ja. Jederzeit änderbar, bei neuen wie bestehenden Plänen; für Dinge, die du zählst, nimm stattdessen ein Meter-Limit weiter unten.
Meter-Limits — der Abschnitt „+ Add limit“
Jede Limit-Zeile verbindet diesen Plan mit einem Meter und beantwortet: Wie viel davon ist inklusive, und was passiert darüber hinaus?
- Meter *
Auf welche gemessene Größe sich dieses Limit bezieht. Das Dropdown listet die Meter, die du in diesem Projekt angelegt hast — nicht mehr, nicht weniger. Es ist kein fester Katalog: Jede neue Produktfähigkeit braucht nur zuerst einen neuen Meter, und er erscheint hier sofort.
- Included units
Das im Planpreis enthaltene Kontingent, pro Abrechnungszeitraum. „Pro enthält 500 Bilder pro Monat“ →
500. In einer Hard- oder Soft-Zeile ist eine Zahl Pflicht, bevor der Plan angelegt werden kann — ein leeres Kontingent würde nichts begrenzen — es sei denn, du hakst unten Unlimited an und sagst damit, dass genau das gemeint war. In einer Metered-Zeile ist leer bereits eine Aussage: Pay-as-you-go ab der ersten Einheit. - Unlimited
Nur in Hard- und Soft-Zeilen, und der ausdrückliche Weg zu sagen „kein Limit für diesen Meter“. Angehakt wird Included units abgeschaltet und geleert; nicht angehakt bleibt die Zahl Pflicht. Metered-Zeilen haben den Schalter nicht, weil leer dort schon etwas bedeutet.
- Overage rate
Der Preis in Credits pro Einheit, sobald der Kunde die inkludierten Einheiten überschreitet —
0.5heißt: Jede zusätzliche Einheit kostet einen halben Credit von seinem Guthaben. Er gehört nur zum Typ Metered: Das Formular verlangt ihn in einer Metered-Zeile und blendet ihn bei Hard und Soft aus, und die API lehnt einen Satz in einer Hard- oder Soft-Zeile ab (422). Eine Metered-Zeile ohne inkludierte Einheiten und ohne Satz würde jede Einheit ablehnen, deshalb lehnt die API auch diese Zeile ab (422). - Limit type
Was
entitlements.check()des SDK antwortet, sobald die inkludierten Einheiten aufgebraucht sind — der Aufruf, den deine App vor der Arbeit macht. Hard (blockieren) —check()antwortet nein (hard_limit_reached) und deine App lehnt die Aktion ab; der Kunde stößt bis zur nächsten Periode oder einem Upgrade an eine Wand. Soft (warnen) —check()antwortet weiterhin ja, markiert mitsoft_limit_exceeded, deine App lässt es also durch und bewegt den Kunden zum Upgrade. Metered (abrechnen) —check()antwortet ja, solange die Credits des Kunden die zusätzlichen Einheiten decken, und jede zusätzliche Einheit wird zum Mehrverbrauchssatz vom Guthaben abgebucht; reicht das Guthaben nicht, lautet die Antwort nein (insufficient_credits). Metered ist die „Pay-as-you-go“-Option und die einzige, die von selbst Geld (Credits) bewegt. Ein Metered-Limit wird bei einem Max- oder Min-Meter abgelehnt (422): Ein Höchst- oder Tiefstwert lässt sich nicht pro Einheit abrechnen. In einer Metered-Zeile kann ein Ausgabenlimit am Abonnement des Kundencheck()schon mit nein antworten lassen, bevor das Guthaben aufgebraucht ist (spend_cap_reached). Hard und Soft lösen den Webhooklimit.reachedeinmal pro Abrechnungszeitraum aus, beim ersten Überschreiten der Grenze. In jedem Fall zeichnet MeterFlow die Ereignisse, die deine App sendet, weiter auf — das Tor istcheck(), in deinem Code.
USD · Monatlich · 14 Testtage · Published ✓Limit 1: Meter Erzeugte Bilder, inklusive 500, Typ Hard → nach 500 Bildern antwortet
check() nein und deine App stellt die Erzeugung bis zum nächsten Monat oder einem Upgrade ein.Limit 2: Meter Video-Render-Sekunden, inklusive 1 000, Mehrverbrauch 0,02, Typ Metered → jenseits von 1 000 Sekunden kostet jede weitere Sekunde stillschweigend 0,02 Credits aus dem Guthaben des Kunden.
Warum ist „+ Add limit“ ausgegraut?
Weil das Projekt noch keine Meter hat — ein Limit ist immer eine Obergrenze auf einem Meter; ohne Meter gibt es nichts, woran man es hängen könnte. Der Dialog zeigt den Hinweis „Create meters first to attach limits to this plan.“ Gehe zu Meters → New meter, lege mindestens einen an und öffne diesen Dialog erneut.
Warum zeigt das Meter-Dropdown nur wenige Optionen? Was, wenn mein Produkt etwas Neues hat?
Das Dropdown zeigt schlicht deine eigenen Meter des aktuell gewählten Projekts. In den Demo-Daten sind das zufällig „Images generated“, „Video render seconds“, „Upscales processed“, „Peak GPU memory“ und „Active prompters“ — aber diese Liste gehört dir und wächst mit. Sie beschränkt nicht, was Kunden tun können: Kunden wählen nie Meter aus; du definierst Meter für alles, was dein Produkt tut. Morgen ein neues Feature? Lege einen Meter dafür an, und er taucht hier auf.
Ein Kunde ist über einem Hard-Limit — warum werden seine Ereignisse trotzdem aufgezeichnet?
Weil MeterFlow nie anstelle deines Produkts entscheidet, was ein Nutzer darf — das tut deine App, indem sie vor der Aktion entitlements.check() aufruft. Ein Hard-Limit lässt diesen Aufruf nein antworten; überspringt deine App den Aufruf und erledigt die Arbeit trotzdem, wird das Nutzungsereignis dennoch angenommen und gespeichert, damit deine Historie und jede Metered-Abbuchung ehrlich bleiben. Stell dir das Limit als Regel vor und check() als Türsteher: MeterFlow schreibt die Regel, dein Code steht an der Tür.
Was antwortet check(), wenn MeterFlow nicht erreichbar ist?
Ab meterflow 0.10.0 (npm) / 0.5.0 (PyPI) antwortet das SDK weiter. Es verwendet jede Antwort für die 15 Sekunden wieder, die die API erlaubt, und eine Nutzungsmeldung, Gutschrift oder Abbuchung für einen Kunden macht dessen Antworten veraltet. Ist MeterFlow nicht erreichbar — ein Netzwerkfehler, ein Timeout oder ein 5xx bzw. 429 nach den Wiederholungen —, gibt check() die letzte Antwort zurück, markiert mit stale: true; gibt es keine, den Standardwert, den du pro Funktion in entitlementDefaults festlegst ('allow' oder 'deny', '*' für den Rest), mit reason: 'offline_default'; ohne beides wirft es einen Fehler. Dein onError-Hook erfährt es zuerst. Ein 401, 403, 404 oder 422 ist eine echte Antwort und wird nie verdeckt.
Warum kann ich Preis oder Limits eines bestehenden Plans nicht bearbeiten?
Absichtlich: Bestehende Abonnenten haben zu diesen Konditionen abgeschlossen, deshalb werden Preis, Währung, Abrechnungszeitraum und Meter-Limits bei der Erstellung eingefroren. Beim Bearbeiten eines Plans lassen sich nur Name, Beschreibung, Testtage, Veröffentlichungsstatus, Aktiv-Flag und Feature-Schlüssel ändern. Zum Umbepreisen legst du einen neuen Plan an (z. B. „Pro 2026“) und führst neue Kunden dorthin.
Neues Abonnement verbindet Kunde ⇄ Plan
Ein Abonnement bindet einen deiner Kunden an einen Plan. Ab diesem Moment wird seine Nutzung an den Meter-Limits dieses Plans gemessen. In Produktion erstellt dein Backend es üblicherweise per SDK, sobald jemand beim Checkout eine Stufe wählt — der Dialog macht dasselbe von Hand.
📍 Projekt öffnen → Subscriptions → der Button im Tabellenkopf
- Customer ID *
Dein eigener Bezeichner für den Endkunden — eine beliebige Zeichenkette deiner Wahl: eine Nutzer-ID aus deiner Datenbank (
user-842), eine E-Mail, ein Tenant-Kürzel. MeterFlow validiert sie gegen nichts; was du sendest, ist, wem das Abonnement gehört. Verwende überall dieselbe ID (Abonnements, Credits, Nutzung), sonst finden die Teile nicht zueinander. - Plan *
Auf welcher Preisstufe er ist — das Dropdown listet die Pläne dieses Projekts. Hat der Plan Testtage, startet das Abonnement im Status „trialing“, sonst „active“.
user-842 klickt in deiner App auf „Upgrade auf Pro“ → dein Backend ruft subscriptions.create({ customer_external_id: 'user-842', plan_id: … }) auf. Jedes Nutzungsereignis von user-842 wird nun gegen die Limits von Pro geprüft.Was, wenn ein Kunde kein Abonnement hat — gehen seine Ereignisse verloren?
Nein. Ereignisse werden immer gespeichert und erscheinen immer in den Nutzungsübersichten. Ohne aktives Abonnement oder laufende Testphase wird nichts abgerechnet, und entitlements.check() antwortet nein mit no_subscription — eine App, die vorher fragt, lässt die Aktion also nicht durch. Die Abrechnungslogik schaltet sich ein, sobald ein Abonnement existiert.
Kann ich begrenzen, was ein Kunde in einem Zeitraum ausgibt?
Ja — setze spend_cap, in Credits, am Abonnement über das SDK oder die API; leer heißt kein Limit. Erreichen die Ausgaben des Zeitraums es, verbraucht aufgezeichnete Nutzung keine Credits mehr, ein credits.deduct() darüber hinaus wird mit 409 abgelehnt, entitlements.check() antwortet nein mit spend_cap_reached, bevor eine abgerechnete Aktion es überschreiten würde, und der Webhook cap.reached feuert einmal im Zeitraum.
Ein Kunde hat gekündigt — kann er zurückkommen?
Ja, auf demselben Abonnement. Setze seinen Status wieder auf active — subscriptions.update(id, { status: 'active' }) oder Reactivate in seiner Zeile. Ist der alte Zeitraum abgelaufen, beginnt sofort ein neuer, mit den Credits des Plans für den Zeitraum; eine vor ihrem Ende gekündigte Testphase läuft als Testphase weiter. Ein inzwischen deaktivierter oder nicht mehr veröffentlichter Plan nimmt niemanden zurück (409), und ein Abonnement, das der Connector deines Zahlungsanbieters steuert, kommt über den Anbieter zurück, nicht hier.
Kann ich das Abonnement eines Kunden in einer langen Liste finden?
Ja. Die Seite Subscriptions hat einen Kundenfilter und Status-Chips, und das SDK nimmt dieselben zwei: subscriptions.list({ q, status }). q findet jede Kunden-ID, die es enthält; status ist einer von active, trialing, past_due, paused, canceled oder expired. Der Server filtert, bevor er die Seite zuschneidet, also enthält jede Seite nur Treffer. Im SDK ab meterflow 0.9.0 (npm) / 0.4.0 (PyPI). Ab 0.12.0 / 0.7.0 nimmt es außerdem sort — created_at (Standard), customer_external_id oder status — und order, desc oder asc; gib beide mit jedem next_cursor erneut mit.
Die Kundenseite ein Kunde, vollständig
Jeder Kunde, für den deine App etwas geschrieben hat — ein Abonnement, ein Credit-Guthaben oder ein Nutzungsereignis — ist eine Zeile auf der Seite Customers. Öffne ihn, und seine Seite enthält die ganze Geschichte: wer er ist, auf welchem Plan er ist, und vier Tabs.
📍 Projekt öffnen → Customers → die Zeile des Kunden
- Credits
Sein Guthaben und jede Ledger-Zeile dahinter, mit Grant und Deduct — die Dialoge sind weiter unten erklärt.
- Usage
Was er genutzt hat, Meter für Meter.
- Subscription
Sein Plan und dessen Status, mit Cancel oder Reactivate.
- Entitlements
Was sein Plan gewährt, Feature für Feature: was von jedem abgerechneten Kontingent übrig ist, und der Grund, aus dem ein Feature abgelehnt wird, genau wie
entitlements.check()ihn liefern würde.
Credits gutschreiben / abziehen das Guthaben
Credits sind ein vorausbezahltes Guthaben pro Kunde (pro Projekt) — wie ein Portemonnaie oder eine Prepaid-Karte. Du entscheidest, was ein Credit in deiner Preisgestaltung wert ist. „Metered“-Mehrverbrauch bedient sich automatisch aus diesem Guthaben; die beiden Dialoge bewegen Credits von Hand.
📍 Projekt öffnen → Customers → die Zeile des Kunden → Tab Credits → „Grant“ / „Deduct“
- Amount *
Wie viele Credits hinzukommen (Grant) oder abgehen (Deduct). Muss größer als null sein — die Richtung bestimmt der Button, der den Dialog geöffnet hat, nicht ein Minuszeichen.
- Description
Ein optionaler Vermerk auf dem Journaleintrag — „Willkommensbonus“, „Erstattung wegen Ausfall“, „Support-Kulanz“. Dein zukünftiges Ich wird es dir danken.
user-842 erhält eine Gutschrift von 100 („Willkommensbonus“). Er rendert 2 500 Videosekunden auf einem Plan mit 1 000 inklusive und 0,02 Metered-Mehrverbrauch → 1 500 × 0,02 = 30 Credits werden automatisch abgezogen. Guthaben: 70.Verbraucht die Nutzung dieses Kunden sein Guthaben?
Frag das Guthaben: credits.balance() antwortet mit usage_draws_credits. true — sein Plan rechnet Nutzung über das Kontingent hinaus ab, aufgezeichnete Nutzung verbraucht also von selbst Credits. false — nur ein ausdrückliches credits.deduct() bewegt es. null — er hat kein aktives Abonnement und keine laufende Testphase.
Kann meine App einen Kunden automatisch aufladen?
MeterFlow sagt deiner App, wann und wie viel; deine App belastet den Kunden und vergibt dann die Credits. Gib einem Webhook-Endpunkt einen Schwellenwert für niedriges Guthaben, und er erhält balance.low, wenn das Guthaben eines Kunden darunter fällt — durch eine Abbuchung oder durch abgerechnete Nutzung — und balance.topped_up, wenn eine Gutschrift es wieder darüber hebt. Setze topup_amount am Abonnement des Kunden, und balance.low liefert ihn als suggested_topup mit. Setze max_topups_per_window, und eine Gutschrift über diese Anzahl im selben Zeitraum hinaus wird mit 409 abgelehnt, damit eine Schleife in deinem Code nicht weiter auflädt.
Kann ich Credits für einen langen Job zurückhalten?
Ja, ab meterflow 0.11.0 (npm) / 0.6.0 (PyPI). credits.reserve() hält einen Teil des Guthabens eines Kunden für ttl_seconds zurück — 5 Minuten, wenn du nichts anderes angibst, höchstens einen Tag. Das Guthaben bewegt sich nicht, aber nichts anderes kann das Zurückgehaltene ausgeben: ein credits.deduct(), abgerechnete Nutzung, ein check(), das abbuchen würde, und eine weitere Reservierung sehen nur die verfügbaren Credits, also das Guthaben abzüglich des Zurückgehaltenen. Ist der Job fertig, nimmt credits.confirmReservation(id, { amount }) die Reservierung ganz oder teilweise als eine normale Abbuchung im Journal und gibt den Rest frei, und credits.releaseReservation(id) gibt sie ganz frei; eine vergessene Reservierung gibt sich beim Ablauf selbst frei. credits.balance() zeigt reserved und available neben dem Guthaben, und zurückgehaltene Credits zählen auch gegen ein Ausgabenlimit.
Zeig deinen Kunden ihr Guthaben
MeterFlow hostet eine Seite, die einem deiner Kunden sein eigenes Guthaben zeigt: den Stand, die letzten Journalzeilen dahinter, seinen Plan mit dem, was von jedem abgerechneten Kontingent übrig ist, und was er außerhalb des Plans genutzt hat. Du baust und hostest sie nicht — dein Server gibt dem Kunden einen Link.
link.url. Der Link trägt sein eigenes kurzlebiges Token, dein API-Schlüssel verlässt deinen Server also nie. In Python heißt es client.portal.create_session(…), mit denselben Feldern. 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 öffnet topup_url — deine eigene Checkout-Seite, genau so, wie du sie eingetragen hast, ohne Zusätze. Das ist optional: Ohne topup_url, weder am Link noch in den Standardwerten des Projekts, hat die Seite keinen Buy-more-Button. ← Back führt zu return_url, ebenso optional. 4. MeterFlow nimmt nie die Zahlung entgegen: Meldet dein Checkout eine, ruft dein Server credits.grant() auf, und die Seite zeigt das neue Guthaben. - Der Link
Gilt 60 Minuten, sofern du nicht
expires_in_minutessetzt — höchstens 24 Stunden — und lässt sich vorher nicht zurückziehen. Er öffnet die Seite eines einzigen Kunden, nur lesend: Er kann nichts ändern und keinen anderen Kunden zeigen. Ein mit einem Testschlüssel (mf_test_…) erzeugter Link zeigt Testdaten, unter einem Badge Test data. - Dein Look
Projekt öffnen → Portal: Firmenname, Logo, helles / dunkles / automatisches Theme, Farben und Eckenradius, dazu die Standardwerte — Buy-more-URL, Back-URL und Gültigkeitsdauer — für Links, die sie weglassen. Ein Häkchen überträgt den Look auf alle Projekte der Organisation.
- Ein Link von Hand
In der Tabelle Customers erzeugt die Zeilenaktion Create a portal link ohne Code einen Link für diesen Kunden — ebenso Portal link in seinem Tab Credits.
Nutzungsereignis erfassen Kernkonzept
Ein Nutzungsereignis = „Dieser Kunde hat gerade diese Sache getan, in dieser Menge.“ In Produktion sendet deine Anwendung sie automatisch über das SDK, tausende Male am Tag; der Dialog existiert, damit du eins von Hand einspeisen kannst — für Tests und Demos.
📍 Projekt öffnen → Usage → einen Kunden nachschlagen → „Record event“
- Event name *
Muss exakt dem Ereignisnamen eines existierenden, aktiven Meters in diesem Projekt entsprechen (Groß-/Kleinschreibung zählt). Über diese Übereinstimmung weiß MeterFlow, welchen Zähler dieses Ereignis speist. Kein passender Meter → die API lehnt das Ereignis mit 404 ab und nichts wird gespeichert. Die exakte Schreibweise findest du auf der Meters-Seite.
- Customer ID *
Welcher deiner Kunden es getan hat — dieselbe frei wählbare ID-Zeichenkette wie bei Abonnements und Credits. Konsistenz ist alles:
user-842undUSER-842sind zwei verschiedene Kunden. - Value
Die Menge — optional. Lässt du sie weg, liest ein Sum-, Max- oder Min-Meter sie aus der Ereigniseigenschaft, die sein Aggregationsfeld benennt (deine App schickt sie unter
properties); sonst zählt das Ereignis1. Die Bedeutung hängt von der Aggregation des Meters ab: Bei einem Count-Meter wird der Wert ignoriert (jedes Ereignis zählt als ein Vorkommen); bei Sum ist es die zu addierende Menge (42 Sekunden, 1 300 Tokens); bei Max/Min der verglichene Messwert; ein Unique count-Meter zählt die verschiedenen Werte seines Aggregationsfelds.
video.rendered → „Video render seconds“. 2. Das Ereignis wird dauerhaft gespeichert (roh — aggregiert wird später, beim Lesen). 3. Im Hintergrund prüft MeterFlow, ob der Kunde ein aktives Abonnement hat und ob dieser Plan ein Limit auf diesem Meter führt. 4. Ist das Limit Metered, werden die Einheiten über dem Inklusivkontingent zum Mehrverbrauchssatz vom Credit-Guthaben des Kunden abgebucht und eine Ledger-Zeile geschrieben — bis zum Ausgabenlimit des Zeitraums, falls das Abonnement eines hat; ist es Hard oder Soft und überschreitet dieses Ereignis als erstes die inkludierten Einheiten im Zeitraum, feuert der Webhook limit.reached einmal. Abgelehnt wird das Ereignis hier nie — ablehnen ist die Aufgabe von check(), in deiner App. 5. Die Nutzungsübersicht auf dieser Seite wird aus den Rohereignissen mit dem Aggregationstyp des Meters neu berechnet.Ich habe ein Ereignis erfasst und einen Fehler bekommen — warum?
Fast immer liegt es am Ereignisnamen: Er stimmt mit keinem aktiven Meter dieses Projekts exakt überein. Der Fehler sagt es wörtlich — „No active meter found for event '…' in this project.“ Kopiere den Ereignisnamen von der Meters-Seite, statt ihn neu zu tippen. Beachte auch: Meter gelten pro Projekt — ein Meter aus einem anderen Projekt zählt nicht.
Wenn meine App eine Anfrage wiederholt, wird das Ereignis doppelt gezählt?
Nicht bei korrekter SDK-Nutzung: Jeder Schreibvorgang akzeptiert einen Idempotenzschlüssel — eine eindeutige Markierung für „genau diese Aktion“. Kommt derselbe Schlüssel zweimal an (ein Retry nach einem Netzwerkschluckauf), erkennt MeterFlow ihn und liefert das ursprüngliche Ergebnis zurück, statt ein Duplikat zu speichern. Der manuelle Dialog sendet keinen — zweimal von Hand auf Record zu drücken erzeugt also wirklich zwei Ereignisse.
Brauche ich ein Event pro API-Aufruf?
Nein — und meistens solltest du das auch nicht. Value ist eine Menge, und ein Sum-Meter addiert diese Mengen: Ein einzelnes Event mit dem Wert 1 300 ist ein Event auf das Monatskontingent deines Tarifs und 1 300 Einheiten auf dem Meter. Ein Event pro API-Aufruf ist das, was einen Tarif aufbraucht: 1 000 Nutzer mit je 100 Aufrufen pro Tag ergeben rund 3 Millionen Events im Monat.
Aggregiere in deiner eigenen Anwendung über ein Fenster, dessen Verlust du bei einem Absturz verschmerzen könntest — eine Anfrage, ein Job, eine Minute — und erfasse dann ein einziges Event mit der Summe. Sie als Batch zu senden ist nicht dasselbe: Ein Batch von 100 spart HTTP-Anfragen, aber jedes Event bleibt ein eigener Datensatz und zählt weiterhin.
Das gilt für Sum-Meter. Ein Count-Meter ignoriert den Wert und zählt Vorkommnisse — dort braucht jedes Vorkommnis sein eigenes Event. In beiden Fällen ändert sich an niemandes Rechnung etwas: Ein Metered-Limit rechnet pro Einheit ab.
Kann ich Nutzung erfassen, die schon länger zurückliegt?
Nur innerhalb von fünf Minuten. Der timestamp eines Events darf höchstens 5 Minuten in der Vergangenheit und 60 Sekunden in der Zukunft liegen; außerhalb dieses Fensters lehnt die API es mit 422 ab und speichert nichts. Ohne timestamp bekommt das Event den Zeitpunkt seines Eintreffens. Erfasse Nutzung, während sie passiert: Ältere Nutzung lässt sich nachträglich nicht laden.
Neuer Webhook Benachrichtigungen
Ein Webhook ist eine URL auf deinem Server, die MeterFlow aufruft, wenn in deinem Projekt etwas passiert — Credits gutgeschrieben, ein Limit erreicht, ein Guthaben geht zur Neige. Jeder Aufruf ist signiert und wird wiederholt, wenn dein Server nicht antwortet.
📍 Projekt öffnen → Webhooks → der Button im Tabellenkopf
- Endpoint URL *
Wohin MeterFlow die Ereignisse sendet, z. B.
https://api.acme.dev/meterflow. - Events to deliver
Von welchen Ereignissen dieser Endpunkt erfährt:
usage.recorded,credit.granted,credit.deducted(eine Abbuchung oder eine abgerechnete Metered-Nutzung — seintransaction_typesagt, welche),subscription.created,.updated,.renewedund.canceled,limit.reached,cap.reached,balance.exhausted, dazu die beiden unten. - Low balance threshold
Ein Guthaben, in Credits. Setzt du ihn, erhält der Endpunkt auch
balance.low, wenn das Guthaben eines Kunden darunter fällt, undbalance.topped_up, wenn es wieder darüber steigt; löschst du ihn, enden beide. Die zwei Ereignisse kommen und gehen mit dem Schwellenwert, denn ohne Linie lässt sich einem Endpunkt kein Überschreiten melden.
webhooks.list(), webhooks.deliveries(id) für die neuesten 100 und webhooks.deliveryPage(id) (in Python delivery_page) für jeden Versuch, Seite für Seite, die neuesten zuerst. Das Zustellprotokoll im Dashboard blättert genauso. Endpunkte anlegen und ändern bleibt hier, im Dashboard.Deinen Zahlungsanbieter verbinden deine Abrechnung
Wenn deine Kunden dich über Paddle, Polar, Lemon Squeezy, Chargebee oder Razorpay bezahlen, lässt ein Connector dieses Konto MeterFlow steuern: Dein Anbieter ruft MeterFlow bei jeder Abo-Änderung und Zahlung auf, und das passende Abonnement oder die passende Credit-Gutschrift erscheint hier — ohne Code in deiner App.
📍 Projekt öffnen → Connectors → der Button im Tabellenkopf
- Provider *
Über welchen der fünf deine Kunden zahlen.
- Which of your accounts
Live — das Produktivkonto deines Anbieters, das Live-Daten schreibt; Test — seine Sandbox, die Testdaten schreibt. Ein Connector pro Anbieter und Konto.
- Signing secret *
Das Geheimnis, mit dem dein Anbieter seine Webhooks signiert — bei Chargebee, das nichts signiert, Benutzername und Passwort, die es stattdessen mitschickt. Es wird bei jedem Aufruf geprüft und nie wieder angezeigt: Die Tabelle zeigt nur seine letzten vier Zeichen.
Sobald er existiert
- Die Webhook-URL
Wird angezeigt, sobald der Connector angelegt ist: Füge sie in die Webhook-Einstellungen deines Anbieters ein.
- Preis → Plan-Zuordnungen
Welcher Preis deines Anbieters — ein Produkt bei Polar, eine Variante bei Lemon Squeezy, ein Plan bei Chargebee und Razorpay — einen Kunden auf welchen deiner Pläne setzt. Ein Ereignis zu einem Preis ohne Zuordnung wird protokolliert und ändert nichts.
- Zustellprotokoll
Jedes Ereignis, das der Connector empfangen hat, mit dem, was er damit tat, in einem Satz: was angewendet wurde und warum der Rest ignoriert wurde.
Mitglieder und Einladungen Team-Zugriff
Die Seite Members deiner Organisation zeigt, wer dazugehört — mit Rolle und wer eingeladen hat — und die noch offenen Einladungen. Ein Owner oder Admin lädt per E-Mail ein; die Person braucht noch kein MeterFlow-Konto.
📍 Members in der Seitenleiste, neben Billing → „Invite member“ (auch als Zeilenaktion bei den Organisationen im Dashboard)
- Email *
Wohin die Einladung geht. MeterFlow schickt einen Link, der einmal funktioniert, 7 Tage lang, nur für diese Adresse: Die Person öffnet ihn und tritt bei — mit ihrem Konto oder indem sie über den Link eines anlegt.
- Role
Admin — Organisationseinstellungen, Einladungen, API-Schlüssel, Webhooks, Connectoren, Projekte und Abrechnung. Member — wer täglich arbeitet: Meter, Pläne und die Seiten Subscriptions, Usage und Kunde. Viewer — nur lesen. Eine Option „Owner“ gibt es absichtlich nicht: Eigentümerschaft wird nicht per Einladung vergeben.
- Offene Einladungen
Stehen auf der Seite Members, bis sie angenommen, widerrufen werden oder ablaufen. Revoke stoppt den Link sofort.
- Change role · Remove
In der Zeile jedes Mitglieds, für Owner und Admins. Die Mitgliedschaft des Owners und deine eigene lassen sich dort nicht ändern. Wer entfernt wird, verliert den Zugang; sein Konto und was er angelegt hat, bleiben.
dana@acme.dev als Viewer ein, damit das Finanzteam Nutzung und Salden beobachten kann, ohne Preise ändern zu können.