メインコンテンツへスキップ

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.

FIM One は、管理者が制御する機能フラグの背後に完全な Stripe 請求パイプラインを搭載しています。支払い機能が不要なプライベート デプロイメントはこれをオフのままにし、UI は表示されません。SaaS オペレーターは 1 つのトグルを切り替えるだけで、ホストされた Checkout、カスタマー ポータル、webhook 駆動のサブスクリプション ライフサイクル、およびクォータ強制が すぐに利用できます。
請求はデフォルトで無効です。新規インストールと既存のセルフホスト デプロイメントの両方は、system_settings.billing_enabled = FALSE で開始されます。管理者が明示的に有効にするまで、請求 UI は表示されません。

提供内容

  • Free + Pro ティア(月次トークンクォータ付き、デフォルト:Free 1M / Pro 5M、アクティベーション後にカスタマイズ可能)
  • Stripe ホスト型チェックアウト — ユーザーはアップグレード時にカード情報があなたのコードに触れることなく完了
  • カスタマーポータル — ユーザーが支払い方法の更新、請求書のダウンロード、キャンセルをすべて Stripe UI で実行
  • Webhook 駆動ライフサイクル — サブスクリプションは自動的にプロビジョニングおよび更新され、キャンセルされたサブスクリプションは期間終了時に Free に降格
  • クォータ強制実行 — トークン使用量を期間ごとに追跡、ストリーム中のカットオフと構造化されたアップグレードプロンプト
  • 管理ページ — プラン CRUD とサブスクリプション監視用

前提条件

  1. Stripe アカウント(ライブモード有効化済み)。シンガポール法人の場合は KYC(事業 UEN、取締役 ID、銀行口座)の完了が必須です。承認には通常 1~3 日かかります。
  2. Stripe ライブ API キー(制限付きタイプ推奨。標準の sk_live_*** より取り消しやすく、権限がスコープされています)。
  3. Webhook エンドポイント<your-domain>/api/webhooks/stripe で公開アクセス可能)。
  4. 銀行口座(支払い用)。USD 以外がデフォルトの Stripe アカウントの場合、マルチ通貨決済(例:USD 口座への USD 支払い)を推奨します。これにより、トランザクションあたり 1.5~2% の為替損失を回避できます。

セットアップ

1. Stripe ダッシュボード

Pro製品を作成する

  1. Catalog → Products → + Add product
  2. Name: Pro、description: 5M tokens / month, priority support
  3. Pricing: Recurring、monthly、$20.00 USD(ご自身の価格戦略に合わせて調整してください)
  4. Save → 結果の price_*** IDをコピーします(アクティベーション後、ローカルの billing_plans テーブルをこの値で更新します)

制限付きAPIキーを作成する

  1. Developers → API keys → + Create restricted key
  2. Name: fim-one production
  3. Permissions (minimum):
    • Customers: Write
    • Subscriptions: Write
    • Checkout Sessions: Write
    • Customer portal: Write
    • Prices: Read
    • Products: Read
  4. Save → copy rk_live_***

Webhookエンドポイントを登録する

  1. Developers → Webhooks → + Add endpoint
  2. URL: https://<your-domain>/api/webhooks/stripe
  3. 受け取るイベント:
    • checkout.session.completed
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.payment_succeeded
    • invoice.payment_failed
  4. 保存後、「Reveal signing secret」をクリック → whsec_*** をコピー

複数通貨決済の設定(推奨)

Stripeアカウントのデフォルト通貨が、請求する価格通貨と異なる場合(一般的な例:SGDアカウントでUSD請求):
  1. Settings → Bank accounts and currencies → Add a settlement currency
  2. 価格通貨を選択(例:USD)
  3. 対応する銀行口座を接続(例:Aspire USD仮想口座)
  4. 保存 — StripeはUSD請求をUSD支払いに直接ルーティングし、為替変換は行いません

2. Backend .env

本番環境の.envで以下の3つのキーを設定します:
STRIPE_SECRET_KEY=rk_live_***
STRIPE_WEBHOOK_SECRET=whsec_***
STRIPE_BILLING_RETURN_URL=https://<your-domain>/settings?tab=billing
詳細は環境変数を参照してください。 .envを編集した後、バックエンドを再起動してキーが読み込まれるようにします:
./deploy.sh   # or: docker compose restart fim-one

3. Admin で有効化

  1. 管理者としてログイン
  2. Admin → System Settings → Billing
  3. Enable Stripe Billing をONに切り替え
  4. バックエンドが STRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRET の両方が存在することを検証します — どちらかが欠落している場合は400を返し、トグルはOFFのままになります
  5. 初回有効化時のみ、バックエンドはべき等なセットアップを実行します:
    • Free + Pro プランをシード(既に存在する場合はスキップ)
    • system_settings.default_plan_id を Free プランのIDに設定
    • プランを持たないユーザーの users.plan_id = free.id をバックフィル
    • default_token_quota → Free プランの monthly_token_quota を同期して、既存の管理者制御グローバルクォータを引き継ぎ
  6. その後のトグルオフ/オンは純粋なフラグ反転で、データ側の影響はありません

4. Pro プランをライブ価格で更新する

アクティベーション後、シードされた Pro プランをライブ Stripe 価格にポイントするように更新します:
  • Admin → Billing → Plans → Pro → Edit
  • ステップ 1 から取得した price_1***Stripe Price ID に貼り付けます
  • 保存します
または SQL 経由で(直接 DB アクセスを希望する場合):
UPDATE billing_plans
SET stripe_price_id = 'price_1***'
WHERE slug = 'pro';

5. スモークテスト

  1. 通常ユーザーとして /settings?tab=billing を開く
  2. Switch to Pro をクリック
  3. Stripe Checkout が開く。少額の実カードで完了する(その後払い戻す)
  4. Webhook が発火する — Stripe Dashboard → Webhooks → 最近のイベントで 2xx レスポンスが表示されることを確認
  5. subscriptions テーブルにサブスクリプション行が表示される。users.plan_idpro に切り替わる
  6. 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 に直接フォールバックする
データは保持されます:既存の subscriptionsbilling_plansusers.plan_id 行は変更されません。再度有効化すると、マイグレーションなしで同じ状態から再開されます。

計算リファレンス — クォータ & トークン計算

これは、ユーザーが消費できる内容、カウンターがリセットされるタイミング、および解決チェーンがどのように構成されるかを決定するすべての数値ルールの信頼できるリファレンスです。価格設定の変更、クォータの調整、使用状況ダッシュボードの構築、またはv2/v3作業の計画を行う前に、これをお読みください。まだ出荷されていない将来のルールは、予約されたスロットに記載されているため、貢献者は新しいロジックがどこに組み込まれるかを知ることができます。

用語集

変数ストレージセマンティクス範囲
users.token_quotaユーザーごと(オーバーライド)3状態オーバーライド。以下のセマンティクスを参照NULL0、または正の整数
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つの意味を持ちます:
ValueMeaningUse case
NULL未設定 — プランまたはデフォルトに従うすべての通常ユーザーのデフォルト状態
0無制限管理者 / 内部アカウント;「VIP ギフト」
N > 0N でハードキャップ不正使用者をブロック(有料サブスクリプションはキャンセルしない);プリペイド型エンタープライズ割り当て
オーバーライドは常にプランとデフォルトより優先されます。管理者が Stripe に触れることなく、個別ユーザーをプラン階層の上下に固定できるよう存在します。

クォータ解決チェーン — v1(現在)

認証されたリクエストの場合、上限は上から下へ計算されます——最初にマッチしたものが優先されます
1. users.token_quota        ── NULL? skip. 0? unlimited. N>0? cap at N.
2. users.plan.monthly_token_quota   ── only when billing_enabled = TRUE
3. system_settings.default_token_quota  ── defensive fallback
4. unlimited                ── last resort if everything above is NULL
ステップ3は、課金が有効な場合はめったに到達しません。これは、アクティベーションがすべてのユーザーの users.plan_id をバックフィルするためです。これは防御層として存在し、設定が誤ったプランがユーザーを静かに無制限にすることがないようにします。

期間リセット

  • 有料ユーザーの場合、quota_reset_atSubscription.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/stripe503 を返します。
  • Plan & Billing ユーザータブと Admin → Billing ナビゲーショングループは非表示になります。
  • すべての請求データ(サブスクリプション、プラン、users.plan_id)は保持されます — 再度有効にすると、マイグレーションなしで同じ状態から再開されます。

予約済み: クォータチェーン v2 — Team シート

まだリリースされていません。v2 作業の既知のランディングスポットとしてここに記載されています。
Team プランがリリースされる場合:
  • Subscription.quantity はシート数を保持します(Stripe ネイティブ)。
  • ユーザーの有効なプランは、個人プランにフォールバックする前に Team メンバーシップを通じて解決されます:
    effective_plan = team.plan if team_member(user) else user.plan
    
  • クォータはシートごとです(各 Team メンバーは完全な monthly_token_quota を取得します)。プール化されたバケットではありません。プール化されたバケットは先着順の枯渇を引き起こし、顧客にとって悪いものです。
  • オーバーライドセマンティクスは変わりません — Team 管理者は users.token_quota = N を使用して個別メンバーをハードキャップできます。これはチームプランチェーンの上に位置します。

予約済み: クォータチェーン v3 — ネイティブ Org アロケーション (Stripe なし)

まだリリースされていません。Stripe を通じてユーザーごとに支払うことなく、内部的にクォータを割り当てるオンプレミス / エンタープライズデプロイメント向けに予約されています。
  • 新しいテーブル org_quota_allocations(user_id, monthly_token_quota, org_id) は親予算をメンバー全体に配分します。
  • アロケーションは共有プール ではなく、ユーザーごと — すべてのメンバーが明確な個別 SLA を持ちます。
  • 更新されたチェーン:
    override → max(plan_quota, org_allocation) → default → unlimited
    
  • max()sum() ではありません。有料 Pro ユーザーは、Org 管理者が低いアロケーションを設定した場合でも、支払った額より少なくなることはありません。Stripe で支払われたクォータは神聖です。

予約済み:従量課金クレジット残高(v3 別次元)

未出荷。上記のチェーンとは別の軸——クレジットは1回限りのトップアップであり、サブスクリプション階層ではありません。
  • 新しいテーブル user_credits(user_id, balance_cents, currency) — Stripe Checkout mode='payment' 経由で資金提供。
  • 消費順序:サブスクリプション割当量優先、その後クレジット残高(サブスクリプションが枯渇した後のみクレジット減少が開始)。
  • クレジット残高は払い戻し不可(プリペイドの業界標準)。
  • UI は両方のバーを公開:Subscription quota: 4.2M / 5M used + Credits: $7.40 remaining

デフォルト値

出荷時のデフォルト — すべてインストール後に調整可能(記載されている場合を除く)。
変数デフォルト調整方法
billing_plans.monthly_token_quota (Free)1,000,000Admin → Billing → Plans → Free → Edit
billing_plans.monthly_token_quota (Pro)5,000,000Admin → Billing → Plans → Pro → Edit
system_settings.default_token_quota1,000,000(アクティベーション時にFreeと同期)Admin → System Settings → Quotas
system_settings.billing_enabledFALSEAdmin → System Settings → Billing
Pro list price$20.00 USD / monthStripe Dashboard (price object)
Stripe webhook events subscribed6Stripe Dashboard → Webhooks
Stripe price cache TTL5 minutesstripe_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 統合 — 別途コンプライアンスレビューが必要)
  • 使用量ベースのメータリング / 超過料金
  • 従量課金クレジット残高 (ワンタイムトップアップ)
次に予定されている内容については、ロードマップを参照してください。

トラブルシューティング

有効化エンドポイントには STRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRET の両方が設定されている必要があります。.env に存在することを確認し、編集後にバックエンドが再起動されていることを確認してください。
課金が無効化されているか(トグルが OFF)、またはリクエスト署名の検証に失敗しています(STRIPE_WEBHOOK_SECRET が一致していない)。Stripe ダッシュボード → Webhooks → 最近のイベントで実際のエラー本文を確認してください。
checkout.session.completed webhook がバックエンドに到達しませんでした。Stripe ダッシュボードのエンドポイント URL が <your-domain>/api/webhooks/stripe と完全に一致していることを確認してください(末尾のパスを含む)。Webhook の最近の配信でエラーを確認してください。
シード マイグレーションはテストモードの価格 ID を書き込みます。本番課金を有効化した後、Admin → Billing → Plans → Pro → Edit で Pro プランを更新して、本番環境の price_1*** を使用するか、直接 SQL UPDATE で更新してください。
Stripe ダッシュボード → Settings → Branding でビジネス ブランディングを設定してください。ロゴ、ビジネス名(例:「FIM Labs Pte. Ltd.」)、住所を追加してください。Stripe はこれらを自動生成されたすべての領収書と請求書に適用します。
Stripe アカウントのデフォルト通貨が請求通貨と異なる場合、Stripe は支払いのたびに変換します(1.5~2% のスプレッド)。Settings → Bank accounts and currencies で一致する決済通貨を追加し、同じ通貨の銀行口座を接続すると、Stripe は変換なしで同じ通貨の支払いをルーティングします。