FIM One は、管理者が制御する機能フラグの背後に完全な Stripe 請求パイプラインを搭載しています。支払い機能が不要なプライベート デプロイメントはこれをオフのままにし、UI は表示されません。SaaS オペレーターは 1 つのトグルを切り替えるだけで、ホストされた Checkout、カスタマー ポータル、webhook 駆動のサブスクリプション ライフサイクル、およびクォータ強制が すぐに利用できます。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.
請求はデフォルトで無効です。新規インストールと既存のセルフホスト デプロイメントの両方は、
system_settings.billing_enabled = FALSE で開始されます。管理者が明示的に有効にするまで、請求 UI は表示されません。提供内容
- Free + Pro ティア(月次トークンクォータ付き、デフォルト:Free 1M / Pro 5M、アクティベーション後にカスタマイズ可能)
- Stripe ホスト型チェックアウト — ユーザーはアップグレード時にカード情報があなたのコードに触れることなく完了
- カスタマーポータル — ユーザーが支払い方法の更新、請求書のダウンロード、キャンセルをすべて Stripe UI で実行
- Webhook 駆動ライフサイクル — サブスクリプションは自動的にプロビジョニングおよび更新され、キャンセルされたサブスクリプションは期間終了時に Free に降格
- クォータ強制実行 — トークン使用量を期間ごとに追跡、ストリーム中のカットオフと構造化されたアップグレードプロンプト
- 管理ページ — プラン CRUD とサブスクリプション監視用
前提条件
- Stripe アカウント(ライブモード有効化済み)。シンガポール法人の場合は KYC(事業 UEN、取締役 ID、銀行口座)の完了が必須です。承認には通常 1~3 日かかります。
- Stripe ライブ API キー(制限付きタイプ推奨。標準の
sk_live_***より取り消しやすく、権限がスコープされています)。 - Webhook エンドポイント(
<your-domain>/api/webhooks/stripeで公開アクセス可能)。 - 銀行口座(支払い用)。USD 以外がデフォルトの Stripe アカウントの場合、マルチ通貨決済(例:USD 口座への USD 支払い)を推奨します。これにより、トランザクションあたり 1.5~2% の為替損失を回避できます。
セットアップ
1. Stripe ダッシュボード
Pro製品を作成する
- Catalog → Products → + Add product
- Name:
Pro、description:5M tokens / month, priority support - Pricing: Recurring、monthly、$20.00 USD(ご自身の価格戦略に合わせて調整してください)
- Save → 結果の
price_***IDをコピーします(アクティベーション後、ローカルのbilling_plansテーブルをこの値で更新します)
制限付きAPIキーを作成する
- 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_***
Webhookエンドポイントを登録する
- Developers → Webhooks → + Add endpoint
- URL:
https://<your-domain>/api/webhooks/stripe - 受け取るイベント:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
- 保存後、「Reveal signing secret」をクリック →
whsec_***をコピー
複数通貨決済の設定(推奨)
Stripeアカウントのデフォルト通貨が、請求する価格通貨と異なる場合(一般的な例:SGDアカウントでUSD請求):- Settings → Bank accounts and currencies → Add a settlement currency
- 価格通貨を選択(例:USD)
- 対応する銀行口座を接続(例:Aspire USD仮想口座)
- 保存 — StripeはUSD請求をUSD支払いに直接ルーティングし、為替変換は行いません
2. Backend .env
本番環境の.envで以下の3つのキーを設定します:
.envを編集した後、バックエンドを再起動してキーが読み込まれるようにします:
3. Admin で有効化
- 管理者としてログイン
- Admin → System Settings → Billing
- Enable Stripe Billing をONに切り替え
- バックエンドが
STRIPE_SECRET_KEYとSTRIPE_WEBHOOK_SECRETの両方が存在することを検証します — どちらかが欠落している場合は400を返し、トグルはOFFのままになります - 初回有効化時のみ、バックエンドはべき等なセットアップを実行します:
- Free + Pro プランをシード(既に存在する場合はスキップ)
system_settings.default_plan_idを Free プランのIDに設定- プランを持たないユーザーの
users.plan_id = free.idをバックフィル default_token_quota→ Free プランのmonthly_token_quotaを同期して、既存の管理者制御グローバルクォータを引き継ぎ
- その後のトグルオフ/オンは純粋なフラグ反転で、データ側の影響はありません
4. Pro プランをライブ価格で更新する
アクティベーション後、シードされた Pro プランをライブ Stripe 価格にポイントするように更新します:- Admin → Billing → Plans → Pro → Edit
- ステップ 1 から取得した
price_1***をStripe Price IDに貼り付けます - 保存します
5. スモークテスト
- 通常ユーザーとして
/settings?tab=billingを開く - Switch to Pro をクリック
- Stripe Checkout が開く。少額の実カードで完了する(その後払い戻す)
- Webhook が発火する — Stripe Dashboard → Webhooks → 最近のイベントで 2xx レスポンスが表示されることを確認
subscriptionsテーブルにサブスクリプション行が表示される。users.plan_idがproに切り替わる- UI に Pro プランと「Manage subscription」ボタンが表示される
請求の無効化
Admin → System Settings → Billing で Enable Stripe Billing スイッチを OFF に切り替えます。 無効化すると:- すべての
/api/billing/*エンドポイントが 503 を返す - webhook エンドポイントが 503 を返す(Stripe は再試行し、Dashboard に失敗として表示されます — これは問題ありません。請求が永続的に無効な場合は、Stripe Dashboard で webhook を無効にすることもできます)
Plan & Billingユーザー向けタブが消える- Admin → Billing ナビゲーショングループが非表示になる
- クォータチェーンがプランティアをスキップし、
default_token_quotaに直接フォールバックする
subscriptions、billing_plans、users.plan_id 行は変更されません。再度有効化すると、マイグレーションなしで同じ状態から再開されます。
計算リファレンス — クォータ & トークン計算
これは、ユーザーが消費できる内容、カウンターがリセットされるタイミング、および解決チェーンがどのように構成されるかを決定するすべての数値ルールの信頼できるリファレンスです。価格設定の変更、クォータの調整、使用状況ダッシュボードの構築、またはv2/v3作業の計画を行う前に、これをお読みください。まだ出荷されていない将来のルールは、予約されたスロットに記載されているため、貢献者は新しいロジックがどこに組み込まれるかを知ることができます。用語集
| 変数 | ストレージ | セマンティクス | 範囲 |
|---|---|---|---|
users.token_quota | ユーザーごと(オーバーライド) | 3状態オーバーライド。以下のセマンティクスを参照 | NULL、0、または正の整数 |
users.tokens_used_this_period | ユーザーごと(カウンター) | 最後のリセット以降の累積トークン | 非負の整数 |
users.quota_reset_at | ユーザーごと(アンカー) | 有料ユーザーの Subscription.current_period_end をミラーリング | タイムスタンプ |
users.plan_id | ユーザーごと(FK) | アクティブなプラン | FK billing_plans.id |
billing_plans.monthly_token_quota | プランごと | このプランのユーザーのハードキャップ | 非負の整数 |
system_settings.default_token_quota | シングルトン | プランが適用されない場合の防御的フォールバック | 非負の整数 |
system_settings.default_plan_id | シングルトン | 新規/未割り当てユーザーの無料プランポインター | FK または NULL |
system_settings.billing_enabled | シングルトン | マスタースイッチ——チェーンのステップ2をゲート | ブール値 |
トークンとしてカウントされるもの
トークン消費はLLMコール層で記録され、すべての完了時にLiteLLMのusageオブジェクトから取得されます。
- カウント対象: すべてのモデルコールにおけるプロンプトトークン + 完了トークン
- カウント対象: マルチステップ/ツール使用エージェントフロー内のすべてのラウンドトリップ(各モデルコールは個別の請求)
- カウント対象: 埋め込みリクエスト(KB取り込み、検索スコアリング)
- カウント対象外: モデルに送信されないがステージングされた入力(ユーザーが破棄したアップロードファイルなど)
- カウント対象外: プロバイダーに到達する前に失敗するリクエスト(認証エラー、レート制限事前チェック)
- キャッシュされた入力: v1では全額でカウント(プロバイダーキャッシュ割引は表示されません)。v2ではキャッシュされたプロンプトトークンを別途クレジットする可能性があります。
Three-state override semantics
users.token_quota はユーザーごとの管理者オーバーライドです。1つのカラムに3つの意味を持ちます:
| Value | Meaning | Use case |
|---|---|---|
NULL | 未設定 — プランまたはデフォルトに従う | すべての通常ユーザーのデフォルト状態 |
0 | 無制限 | 管理者 / 内部アカウント;「VIP ギフト」 |
N > 0 | N でハードキャップ | 不正使用者をブロック(有料サブスクリプションはキャンセルしない);プリペイド型エンタープライズ割り当て |
クォータ解決チェーン — v1(現在)
認証されたリクエストの場合、上限は上から下へ計算されます——最初にマッチしたものが優先されます:users.plan_id をバックフィルするためです。これは防御層として存在し、設定が誤ったプランがユーザーを静かに無制限にすることがないようにします。
期間リセット
- 有料ユーザーの場合、
quota_reset_atはSubscription.current_period_endと同期します。invoice.payment_succeededウェブフック ハンドラーは、各更新成功時にtokens_used_this_period = 0を設定し、quota_reset_atを新しい期間終了日に進めます。 - 無料ユーザー(Stripe サブスクリプションなし)の場合、時間単位の cron がプラン割り当て日を基準とした暦月の境界で
tokens_used_this_periodを 0 にリセットします。 - 期間中のプラン変更はカウンターをリセットしません——更新時のみリセットされます。これにより、クォータ サイクリング エクスプロイト(「サブスクライブ → Pro クォータを使用 → キャンセル → 再度サブスクライブ」)を防ぎます。
ミッドストリーム強制
- チャット呼び出しエントリでのプリフライトチェック:最も安価なパス、ユーザーが開始できない要求をブロックします。
- ストリーミング中、実行中のトークンカウントはチャンクごとに再評価されます。上限を超えると、ネットワークエラーではなく構造化ターミネータフレームでストリームを閉じます。
- フロントエンドはターミネータを解釈し、
/settings?tab=billingへのディープリンク付きで<QuotaExceededDialog>を表示します。 - ストリーミング以外のレスポンスはHTTP
402を返し、本文は{ code: "QUOTA_EXCEEDED", reset_at, upgrade_url }です。
請求機能無効時のフォールバック
system_settings.billing_enabled = FALSE の場合:
- チェーンのステップ 2 がスキップされます — チェーンは
override → default → unlimitedに縮小されます。 /api/billing/*と/api/webhooks/stripeは503を返します。Plan & Billingユーザータブと Admin → Billing ナビゲーショングループは非表示になります。- すべての請求データ(サブスクリプション、プラン、
users.plan_id)は保持されます — 再度有効にすると、マイグレーションなしで同じ状態から再開されます。
予約済み: クォータチェーン v2 — Team シート
まだリリースされていません。v2 作業の既知のランディングスポットとしてここに記載されています。
Subscription.quantityはシート数を保持します(Stripe ネイティブ)。- ユーザーの有効なプランは、個人プランにフォールバックする前に Team メンバーシップを通じて解決されます:
- クォータはシートごとです(各 Team メンバーは完全な
monthly_token_quotaを取得します)。プール化されたバケットではありません。プール化されたバケットは先着順の枯渇を引き起こし、顧客にとって悪いものです。 - オーバーライドセマンティクスは変わりません — Team 管理者は
users.token_quota = Nを使用して個別メンバーをハードキャップできます。これはチームプランチェーンの上に位置します。
予約済み: クォータチェーン v3 — ネイティブ Org アロケーション (Stripe なし)
まだリリースされていません。Stripe を通じてユーザーごとに支払うことなく、内部的にクォータを割り当てるオンプレミス / エンタープライズデプロイメント向けに予約されています。
- 新しいテーブル
org_quota_allocations(user_id, monthly_token_quota, org_id)は親予算をメンバー全体に配分します。 - アロケーションは共有プール ではなく、ユーザーごと — すべてのメンバーが明確な個別 SLA を持ちます。
- 更新されたチェーン:
max()、sum()ではありません。有料 Pro ユーザーは、Org 管理者が低いアロケーションを設定した場合でも、支払った額より少なくなることはありません。Stripe で支払われたクォータは神聖です。
予約済み:従量課金クレジット残高(v3 別次元)
未出荷。上記のチェーンとは別の軸——クレジットは1回限りのトップアップであり、サブスクリプション階層ではありません。
- 新しいテーブル
user_credits(user_id, balance_cents, currency)— Stripe Checkoutmode='payment'経由で資金提供。 - 消費順序:サブスクリプション割当量優先、その後クレジット残高(サブスクリプションが枯渇した後のみクレジット減少が開始)。
- クレジット残高は払い戻し不可(プリペイドの業界標準)。
- UI は両方のバーを公開:
Subscription quota: 4.2M / 5M used+Credits: $7.40 remaining。
デフォルト値
出荷時のデフォルト — すべてインストール後に調整可能(記載されている場合を除く)。| 変数 | デフォルト | 調整方法 |
|---|---|---|
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(アクティベーション時にFreeと同期) | Admin → System Settings → Quotas |
system_settings.billing_enabled | FALSE | Admin → System Settings → Billing |
| Pro list price | $20.00 USD / month | Stripe Dashboard (price object) |
| Stripe webhook events subscribed | 6 | Stripe Dashboard → Webhooks |
| Stripe price cache TTL | 5 minutes | stripe_client.pyにハードコード |
| Subscription lifecycle cron | 毎時間 | web/main.pyのAPScheduler |
| Free-tier reset cron | 毎時間(暦月の境界) | web/main.pyのAPScheduler |
料金モデル
V1はフラットサブスクリプションです。Free + Pro、月次請求、USD のみ。 V1 の対象外 (意図的に、ロードマップに延期):- Team プラン (Stripe seats /
subscription.quantity) - 年間請求
- 複数通貨の表示
- クーポン / プロモコード
- 税務処理 (Stripe Tax 統合 — 別途コンプライアンスレビューが必要)
- 使用量ベースのメータリング / 超過料金
- 従量課金クレジット残高 (ワンタイムトップアップ)
トラブルシューティング
トグルが有効化されない — 400 エラー
トグルが有効化されない — 400 エラー
有効化エンドポイントには
STRIPE_SECRET_KEY と STRIPE_WEBHOOK_SECRET の両方が設定されている必要があります。.env に存在することを確認し、編集後にバックエンドが再起動されていることを確認してください。Webhook が 503 を返す
Webhook が 503 を返す
課金が無効化されているか(トグルが OFF)、またはリクエスト署名の検証に失敗しています(
STRIPE_WEBHOOK_SECRET が一致していない)。Stripe ダッシュボード → Webhooks → 最近のイベントで実際のエラー本文を確認してください。ユーザーがサブスクライブしたが、まだ Free プランが表示される
ユーザーがサブスクライブしたが、まだ Free プランが表示される
checkout.session.completed webhook がバックエンドに到達しませんでした。Stripe ダッシュボードのエンドポイント URL が <your-domain>/api/webhooks/stripe と完全に一致していることを確認してください(末尾のパスを含む)。Webhook の最近の配信でエラーを確認してください。Pro ユーザーがテストモードの価格 ID を見ている
Pro ユーザーがテストモードの価格 ID を見ている
シード マイグレーションはテストモードの価格 ID を書き込みます。本番課金を有効化した後、Admin → Billing → Plans → Pro → Edit で Pro プランを更新して、本番環境の
price_1*** を使用するか、直接 SQL UPDATE で更新してください。領収書が Stripe のデフォルト ブランディングで表示される
領収書が Stripe のデフォルト ブランディングで表示される
Stripe ダッシュボード → Settings → Branding でビジネス ブランディングを設定してください。ロゴ、ビジネス名(例:「FIM Labs Pte. Ltd.」)、住所を追加してください。Stripe はこれらを自動生成されたすべての領収書と請求書に適用します。
支払い時の為替損失
支払い時の為替損失
Stripe アカウントのデフォルト通貨が請求通貨と異なる場合、Stripe は支払いのたびに変換します(1.5~2% のスプレッド)。Settings → Bank accounts and currencies で一致する決済通貨を追加し、同じ通貨の銀行口座を接続すると、Stripe は変換なしで同じ通貨の支払いをルーティングします。