Imperal Docs
Billing & Earnings

Billing & Earnings — overview

How Imperal Cloud bills users and how developers earn revenue from their extensions

This section is for extension developers publishing on the Imperal Marketplace. It covers how users pay, how your extension earns, and how you get paid out.

Not building extensions? This section is for marketplace publishers. If you're a regular Imperal Cloud user looking at your own bill, log into the Panel → Billing tab.

The three things users pay for

Imperal users pay along three independent surfaces:

┌──────────────────────────────────────────────────────────────┐
│ Tier 1: Platform subscription                                │
│   Flat monthly/annual fee for Panel access.                  │
│   Charged via Stripe recurring (auto-renew).                 │
├──────────────────────────────────────────────────────────────┤
│ Tier 2: Token wallet (pay-as-you-go)                         │
│   Replenishable token balance — top up via Stripe one-shot.  │
│   Tokens get consumed on every action call.                  │
├──────────────────────────────────────────────────────────────┤
│ Tier 3: Extension rental (planned — not yet enforced)        │
│   Optional monthly token subscription per paid extension.    │
└──────────────────────────────────────────────────────────────┘

As a developer, you earn from Tier 2 — every time a user invokes one of your extension's @chat.function handlers, tokens flow from their wallet, and a percentage accrues to your developer balance. Your developer tier controls the split, app cap, payout access, analytics window, and rate limit:

TierSplit (dev / platform)Max appsPayoutAnalytics windowRate limitAnnual price
explorer (default)70 / 301❌ accrue only7 days100 req/minFree
indie80 / 20330 days500 req/min9,000 tokens / year
studio85 / 151090 days2,000 req/min29,000 tokens / year
partner (admin-promoted)95 / 5unlimited365 days5,000 req/min79,000 tokens / year

Default for new developers is explorer. Tier subscriptions auto-renew once a year; lapse drops you back to explorer (existing earnings stay in your balance). See Developer Tiers for break-even math, upgrade flow, and tier-lock semantics on existing apps.

What your extension can charge for

Every @chat.function in your extension has an action_type (read / write / destructive). When a user invokes it:

  1. Web-kernel resolves the token cost from your pricing config (Redis key imperal:billing:pricing:{app_id}).
  2. Cost = base_price (from your pricing) + platform_fee (covers Imperal's LLM cost; zero for BYOLLM users — see BYOLLM Pricing).
  3. Tokens deducted atomically from user wallet via Lua script.
  4. Audit event written to imperal:billing:events stream.
  5. Billing consumer writes double-entry rows to token_ledger and your developer_earnings row.

You see the result in Dev Portal → My App → Earnings.

What you DON'T charge for

These flows bypass your earnings — they're either platform-side or web-kernel-internal:

  • Skeleton refreshes (@ext.skeleton decorator) — free, web-kernel runs them in background; never billed.
  • Panel renders (@ext.panel handlers) — free, also background-driven.
  • Branch B conversational turns — when user chats without invoking a tool, web-kernel charges __system__/hub_chat/write (not your extension). For BYOLLM users this is zero.
  • Cancelled / refunded actions — saga compensation refunds the user; your earnings row is reversed.

Quick reference

WhatWhere to read
Set prices for your extensionPricing Models
Tier system + revenue splits (70 → 95%)Developer Tiers
How earnings are tracked + viewedRevenue & Earnings
BYOLLM impact on your revenueBYOLLM Pricing ← important
Request a payoutPayouts
Pricing UI walkthroughDev Portal Publishing guide

Lifecycle of pricing edits

App status:  draft  →  pending_review  →  active
             ─────     ───────────────     ──────
Pricing:     editable  locked (review)    locked (must `Pause` to edit)

To change prices on an active app: Pause in Dev Portal → edit → Resubmit for Review → admin re-approves. Prices propagate to Redis on approval.

Real-time observability

In Dev Portal → Earnings:

  • Total Earned — sum of all developer_share across developer_earnings (Redis cache: imperal:developer:earnings:{your_id})
  • Pending Payout — earned minus what's already paid/approved
  • Paid Out — sum of developer_payouts WHERE status IN ('approved','paid')

Updates within seconds of each user call (consumer-driven).


Federal billing invariants (live since 2026-05-12)

Five federal contracts pin the correctness of the billing critical path. They are enforced by tests in imperal-web-kernel/tests/test_i_* and by static-source assertions in imperal_kernel/_invariant_assertions.py. CI fails any commit that drops them.

InvariantWhat it pinsWhy it matters to you
I-BILLING-ENFORCE-UNIFIEDEvery billable code path goes through a single deduct_for_action() chokepoint; legacy direct-wallet writes are forbidden. BILLING_ENFORCE=true in the platform-worker + session-worker .env is now the production posture.Your @chat.function always charges the user via the same dispatch logic — you cannot accidentally skip billing in a refactor, and pricing changes propagate uniformly across single-action, chain-reserve, and Branch B paths.
I-WALLET-PERSISTENTAll four Redis Lua wallet scripts (CHECK_AND_DEDUCT, RESERVE, SETTLE, CREDIT) call PERSIST KEYS[1] atomically. Wallet keys are TTL-free by construction.Your earnings row is never lost to a stray TTL on the source wallet key. A wallet that "disappears" is a federal incident, not a stale-cache UX bug.
I-WALLET-SWEEP-ACTIVEA Temporal WalletPersistSweepWorkflow runs hourly in the imperal-billing namespace and re-runs PERSIST on any wallet keys that somehow regained a TTL (external Redis maintenance scripts, etc.).Defence-in-depth — even if a third-party tool tries to apply a blanket EXPIRE, the sweep restores correctness within the hour. No cron — Temporal only (federal rule).
I-BYOLLM-PLATFORM-FEE-ZEROWhen ctx.user.is_byollm == True, platform_fee → 0 at every deduct site (single-action, chain reserve, Branch B conversational). Resolved at deduct time via async lookup of user_llm_config store, with 60s Redis cache imperal:byollm_user:{user_id}.Your base_price is unchanged; only the platform component drops. See BYOLLM Pricing for the full impact on earnings.
I-NARRATOR-NO-FABRICATED-TOKEN-CLAIMSThe web-kernel narrator MUST NOT emit cost claims to the user unless the claim is sourced from the actual deduct event. A regex+whitelist detector at the delivery chokepoint strips fabricated phrases like "this cost you 12 tokens" when no deduct row backs them.What the user sees in chat matches what they were actually charged. Your extension's pricing config is the only source of truth — the narrator cannot make up a different number.

Spec: superpowers/specs/2026-05-12-v5-92-enf-billing-2-rollout.md. See BYOLLM Pricing for the developer-facing impact of the first four invariants.

On this page