Imperal Docs
Billing & Earnings

Pricing Models

Configure how your extension charges tokens — free, per-action, or subscription

When you publish an extension, you pick one of three pricing models. You can change the model + values while the app is draft or suspended; once active, you must Pause first to edit.

free — no charge per call

Dev Portal → Pricing tab → Set Model: Free
pricing_model = "free"
pricing_config = {}    # nothing else needed

Resolver short-circuits to (0, 0, 0). Your developer_earnings rows still get written with developer_share=0 for analytics, but no tokens flow.

Use when:

  • Building audience / portfolio extensions
  • Helper utilities that complement a paid extension you also publish
  • Anything where the value-prop is "make Imperal more useful for free"

per_action — charge per function call

Dev Portal → Pricing tab → Set Model: Per Action
pricing_model = "per_action"
pricing_config = {
    "tool_prices": {
        "summarize_inbox": 5,       # tokens per call
        "draft_reply": 3,
        "send_email": 10,
        "list_messages": 1,
    }
}
revenue_split_dev = 70   # explorer tier default; 80/85/95 at indie/studio/partner

For each @chat.function, you set an integer token cost. Pricing maps to the base_price component; web-kernel adds platform_fee on top (model-tier-derived; zero for BYOLLM users).

Effective user-side cost per call:

Non-BYOLLM user:  cost = tool_price + platform_fee  (e.g. 5 + 2 = 7 tokens)
BYOLLM user:      cost = tool_price                  (e.g. 5 tokens)

Your earnings per call (at explorer tier 70%):

Non-BYOLLM:  earned = floor(7 × 0.70) = 4 tokens
BYOLLM:      earned = floor(5 × 0.70) = 3 tokens

Upgrade to indie/studio/partner for higher % — see Developer Tiers for break-even math. BYOLLM impact in detail: BYOLLM Pricing.

Setting tool prices via the UI

  1. Open Dev Portal → My App → Pricing tab.
  2. Click Edit Pricing.
  3. Switch model to Per Action.
  4. For each discovered function, enter a token price (or 0 for free-per-function inside an otherwise-paid extension).
  5. Save → status flips to draft (or stays suspended) → admin re-approval needed before live.

Functions are discovered from disk — the Dev Portal lists every @chat.function it finds in your deployed extension. Add a new function → push to git → deploy → it appears in the price table on next refresh.

Tip: pricing by action type

A common pattern — price destructive more than write more than read. Defaults Imperal uses for first-party apps:

action_typedefault price
read1 token
write3 tokens
destructive10 tokens

You're free to pick your own numbers. Just remember users see the total including platform_fee — high prices push users away.

subscription — flat monthly fee per user

Dev Portal → Pricing tab → Set Model: Subscription
pricing_model = "subscription"
pricing_config = {
    "monthly_price": 5000   # tokens per month per user
}
revenue_split_dev = 80

Not yet enforced (gap G-4 — Extension Rental). The schema accepts subscription mode, but the web-kernel's ExtensionRentalWorkflow is not yet wired. Stick to per_action or free for now if you want predictable revenue.

When enforced, this will:

  • Charge user's wallet monthly_price on subscription start AND every 30 days
  • Suspend access (revoke user_extensions.status) if wallet can't cover
  • Resume on user top-up

Pricing internals — what gets stored where

When you save pricing in Dev Portal, two things happen synchronously:

  1. MySQL: UPDATE developer_apps SET pricing_model=?, pricing_config=? WHERE app_id=?
  2. Redis sync (sync_pricing_to_redis):
    • imperal:developer:app:{app_id} (HASH) ← developer_id, pricing_model, revenue_split_dev, status
    • imperal:billing:pricing:{app_id} (HASH) ← translated to web-kernel's resolver schema:
      • free{mode: "free"}
      • per_action{mode: "per_function", functions: JSON(tool_prices)}
      • subscription{mode: "subscription", monthly_price: int}

Web-kernel reads only the Redis key — your DB row is the source of truth for the Dev Portal UI + admin review.

Edit lifecycle

draft / suspended  →  edit prices freely  →  Submit for Review


                                              pending_review

                                              (admin review)

                                ┌─────────────────────┴────────────────┐
                                ▼                                      ▼
                            approved                              rejected
                                │                                      │
                                ▼                                      ▼
                            status='active'                  status='draft' + reason
                            Redis sync triggers              you fix + resubmit
                            prices go LIVE

Active = immutable. To change anything, Dev Portal → Pause → edit → Resubmit. This protects users from surprise price hikes.

Per-function pricing — when category isn't enough

If your extension has wildly different costs per tool (e.g. lookup is trivial but full_report calls a paid API on your backend), use per_action with per-function prices instead of relying on the action_type categories.

pricing_config = {
    "tool_prices": {
        "lookup": 1,
        "summarize": 5,
        "full_report": 50,    # this one's expensive, charge accordingly
    }
}

Tools you don't list fall back to web-kernel's category defaults (price_read=1, price_write=3, price_destructive=10). To make a tool free, list it explicitly with 0.

On this page