Rebilling
Rebilling is how you, the agency, charge your subaccounts. Insighto.ai gives you two billing methods plus full control over what plans your subaccounts can pick.
All rebilling state lives on a single field — agency.billing_plan — a JSON config field on the Agency row. The keys you'll see throughout this page (billing_method, stripe_api_key, subaccount_wallet, deduct_agency_wallet, etc.) all live in there.
The setup flow
Open Manage Agency → Rebilling Plan. The page is laid out as numbered steps.
Step 1 — Billing method
Pick one:
- Stripe (
billing_method = "stripe") — Insighto creates Stripe Customers and Subscriptions on your Stripe account for each subaccount. You set the prices, you collect the revenue, we plug into the lifecycle webhooks to update plan tiers automatically. - Custom (
billing_method = "custom") — You invoice subaccounts outside the platform. Insighto still enforces plan tiers and feature gating, but doesn't charge anyone — you handle the payment relationship entirely yourself.
Custom is irreversible on the UI. The Method dropdown disables itself once Custom is saved. Pick deliberately.
Step 2 — Stripe credentials (only if Stripe)
Paste your Stripe restricted API key in the Stripe API key field and click Save key. Then click Set webhook — the backend calls stripe.WebhookEndpoint.create on your account, pointing it at https://{API_DOMAIN}/api/v1/agency/webhook/stripe/{agency_id} with these events:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.deletedcustomer.subscription.pausedcustomer.subscription.resumedcustomer.subscription.trial_will_endcustomer.subscription.updatedinvoice.paidinvoice.payment_failed
The badge turns green when check_stripe_webhook confirms the endpoint exists on your Stripe account. If it stays red:
- Confirm the key has write permission for
webhook_endpoints,customers,subscriptions, andprices. - Re-run Set webhook — it's idempotent (it
modifys if astripe_webhook_idalready exists, falls through tocreateotherwise). - Check Stripe's webhook log on their dashboard for any rejected events.
Step 3 — Subaccount billing
Two related toggles.
Enable Wallet for subaccounts
When on, each subaccount gets their own prepaid Wallet (a wallet record created on first use with default_wallet_balance from your subaccount_wallet config). Top-ups go through your Stripe; usage deducts from their wallet at the rates your multipliers define.
The first time you enable this checkbox, the backend writes subaccount_wallet: true and deduct_agency_wallet: true together — those are the initial values, then Configure wallet and Multipliers let you fill in the real subaccount_wallet object.
- Configure wallet sets
default_wallet_balance(default $5) andwallet_currency(defaultusd). - Multipliers sets four numeric multipliers —
llm_cost,voice_cost,transcriber_cost, andplatform_cost— defaulting to 1.0 each. These are applied to the platform's base rates (1¢ transcriber, 1¢ LLM, 2¢ voice, 2¢ platform per minute of voice).
This toggle is disabled if the billing method isn't Stripe.
Auto-deduct from my agency wallet
(deduct_agency_wallet) — Your subaccounts use your platform-managed keys, and all their LLM / TTS / STT spend deducts from your Agency Wallet. You bill them externally for that consumption. This is the "I absorb costs, I invoice you" model.
The two toggles are not mutually exclusive in code — they're stored as independent booleans on agency.billing_plan. In practice you'll typically set one or the other depending on whether you want subaccount-level prepaid wallets or whether you want to cover all usage centrally.
The agency.billing_plan JSONB shape
A fully populated Stripe agency with subaccount wallets looks roughly like:
{
"billing_method": "stripe",
"stripe_api_key": "rk_live_...",
"stripe_webhook_id": "we_1Q...",
"deduct_agency_wallet": false,
"subaccount_wallet": {
"default_wallet_balance": 5,
"wallet_currency": "usd",
"multipliers": {
"llm_cost": 1.5,
"voice_cost": 1.5,
"transcriber_cost": 1.0,
"platform_cost": 1.0
}
}
}
Both shapes of subaccount_wallet exist in production
Be aware that older rows have subaccount_wallet: true (a bare boolean) rather than the object shape above. The backend treats those as "enabled but not configured" — is_agency_subaccount_wallet_enabled returns False for them because it explicitly requires subaccount_wallet to be a dict containing default_wallet_balance:
Migrate boolean rows to the object form by opening Configure wallet and saving — it overwrites the boolean with the dict shape.
How a subaccount conversation gets billed
The subaccount gets billed at the marked-up rate; the agency owner's wallet (the admin_uuid from key resolver) is debited the base rate when deduct_agency_wallet is true. The difference between marked-up and base is the agency's margin.
Plans catalog
Below the setup steps is the plans catalog — the plans your subaccounts can pick from at signup or upgrade. Tabs map to billing_plan_group:
- Default — bundled defaults from the platform. Read-only.
- Plans — your custom monthly subscription plans (
group = "regular"). - Boosters — one-time top-ups / add-on bundles.
- Wallet — wallet-based pay-as-you-go plans. Only one plan in this group can exist per agency.
The Add plan button is enabled only if subaccount_wallet is set. The creation modal walks you through name, lookup key (used in Stripe and your BillingPlan.plan_lookup_key), monthly price, per-credit allowances (queries_count, voice_seconds, bots_count, words_count), and per-plan feature toggles (byok, workflows, calendar_pools, custom_voice, form, custom_tool, sip_enabled, human_agents, campaign_count, channels.twilio, channels.whatsapp, and a few others).
The plan marked Default is what new subaccounts land on. It must be free ($0). Use Set default plan on a plan row to mark it.
Multipliers — the math
Voice cost example, agency with voice_cost = 1.5 and a basic LLM:
Platform base voice line items (¢/min)
transcriber 1 + llm 1 + voice 2 + platform 2 = 6¢/min (your cost)
With multipliers (subaccount-wallet shape, transcriber=1, llm=1, voice=1.5, platform=1)
1 + 1 + 3 + 2 = 7¢/min (what subaccount's wallet is debited)
Your margin = 1¢/min
The platform base values (base_transcriber_cost = 0.01, base_llm_cost = 0.01, base_voice_cost = 0.02, platform_cost = 0.02) are constants. The LLM model multiplier (e.g., 10× for gpt-4o) gets layered on top of base_llm_cost before the agency llm_cost multiplier is applied.
Lifecycle automation (Stripe path)
The agency webhook handler updates plan state in response to Stripe events:
- New subaccount signup → Stripe Customer created, attached to the default free plan.
- Subaccount upgrades → Stripe Checkout creates the Subscription; on success the plan tier flips.
- Subaccount downgrades → scheduled at end of current cycle.
- Failed renewal → Stripe dunning kicks in; if all retries fail, the subscription cancels and the plan tier reverts to the default free plan.
- Wallet top-up → one-time charge via
add_invoice_itemsagainst the active subscription; balance updates oninvoice.paid.
You can override any of this manually from Manage Agency → Sub account → [subaccount] → Change plan or by calling /api/v1/agency/billing/subaccount/change_billing_plan and /refresh_billing_cycle directly.
Custom billing method
If you picked Custom in Step 1:
- All the same plan catalog mechanics work — you still pick plans, set allowances, and assign them to subaccounts.
- No Stripe Customers or Subscriptions are created.
- You're responsible for tracking what each subaccount owes you and collecting payment.
- Insighto still enforces the plan tier — if you mark a subaccount as on the "Pro" plan but they haven't paid, they'll get Pro features until you manually downgrade them in the UI.
Useful for one-off enterprise deals where Stripe doesn't fit your customer's procurement process.