Skip to content

Billing your clients on your own Stripe

Connect your own Stripe account, publish your own client plans, and let a paid invoice apply limits and allocate credits from your pool automatically.

Reseller and agency accounts only

Beyond allocating pooled credits by hand, you can bill your clients on your own Stripe account. Clients pay you directly — Checkout and the Customer Portal both run on your Stripe, never ours — you author your own priced plans, and Evoriqa still allocates AI credits from your pool the instant an invoice is paid.

Sending a client a checkout link plans them and allocates their credits automatically on every invoice. The manual Allocate button in Pooled credits and caps stays for clients you bill some other way — invoice, wire, cash.

Before you start

Connecting Stripe and creating a client plan need an active reseller plan — the same gate as white-label branding. Viewing the config, testing the connection, editing or retiring an existing plan, and reading the webhook log do not.

Your own reseller plan is still billed by Evoriqa. This is how you bill your clients, not how you pay us.

Connect your Stripe account

Everything here lives under Reseller → BYO Stripe, in the "Your Stripe" card.

1. Set up the webhook endpoint first

In your own Stripe Dashboard, under Developers → Webhooks, add an endpoint pointing at the URL the card shows:

Enable exactly these events — anything else is silently ignored, and selecting extra ones only fills your webhook log:

2. Connect

Copy that endpoint's signing secret (whsec_…), choose Connect Stripe, and paste it alongside your account's secret key (sk_…) or a restricted key (rk_…). A secret key works as is. A restricted key is the safer choice, since it can only do what you grant it, and it needs these permissions in Developers → API keys → Edit key:

Accounts: Read sits under Connect even if you don't use Connect. Without it, connecting fails and Evoriqa shows Stripe's own message, which names the missing permission and links to the key's edit page. Edit the key, save, and connect again: the same key picks up the new permission.

Only Accounts: Read is checked when you connect. If another permission is missing, the key connects but the first action that needs it (creating a plan, a checkout, the billing portal, a refund) fails with Stripe's message naming what to add.

Confirm with your current TOTP code, or your account password if two-factor is off. This is the same critical step-up class as deleting your account: a hijacked session must not be able to redirect your payment flow to someone else's Stripe key.

On save, Evoriqa makes one authenticated call to prove the key works and capture your Stripe account id, and rejects a live/test mode mismatch against this deployment — a test-mode deployment refuses a live key (sk_live_… or rk_live_…) and a live deployment refuses a test key (sk_test_… or rk_test_…), so a sandbox can never hold live keys.

Both the secret key and the webhook secret are encrypted at rest (AES-256-GCM), the same primitive as your mail credentials.

3. Test connection

Test connection re-verifies the stored key at any time, and heals a stuck "Error" status back to "Active" the moment the key starts working again. A bad or revoked key, or a Stripe outage, shows Stripe's own error message and heals on the next successful test.

Only a genuine decrypt failure on the stored ciphertext locks the status at "credentials could not be read" — that one needs a reconnect.

Author client plans

Under Reseller → BYO Stripe → Client plans.

Add plan takes a name, a monthly price, an optional annual price, the monthly AI credits it carries, and the same three limit overrides as Per-client limits — chatbots, team seats, and knowledge sources. A subscriber gets those applied to their workspace the moment their invoice is paid. Leave a limit blank to inherit the client's base workspace plan (each limit is blank or ≥ 1; a 0-limit plan is not settable).

Creating a plan provisions a Stripe Product and recurring Price(s) on your own account.

Editing a value — name, credits, limits — updates in place. Changing a price mints new Stripe prices, because Stripe prices are immutable, and archives the old ones; the superseded ids are kept, so an already-subscribed client's in-flight invoice still resolves to the right plan.

Retiring a plan hides it from new checkout links and archives its Stripe prices. Existing subscribers are untouched and keep renewing at their current price.

There is no economic floor on a BYO plan's price. Unlike our own reseller tiers, you set both sides of this relationship.

From the Client plans card, pick a client, a plan, and a billing interval, then Copy checkout link. That mints a Checkout Session on your Stripe account which you paste into an email or a chat — the client does not need to be signed in.

The session bills the client workspace owner's email address and returns to your white-labeled billing page on success or cancel, never a platform URL.

Warning:

Client checkout carries none of our tax parameters. Your own Stripe tax setup is what applies, if you have one configured.

Minting the link is refused when the plan's knowledge-source cap would overdraw your org's pooled source allocation for that client — lower another client's source limit or upgrade your reseller tier first. A webhook never refuses (Stripe has already charged); it warn-logs the overdraw and applies the plan anyway.

Let clients subscribe themselves

A client whose provider has BYO Stripe active sees a plan grid on their own billing page instead of the usual "managed by your provider" notice, and can handle their own subscription:

  • Subscribe creates one reusable Stripe customer per client, lazily on first checkout. A client who already has an active or past-due subscription is refused a second checkout and pointed at "Manage subscription" instead — that is what the portal is for.
  • Manage subscription opens your Stripe Customer Portal for that client's subscription. Checkout and the portal both open in a new tab.

Both are for the client workspace's owner (an admin sees the grid read-only, with no buttons), and both are refused for anyone who isn't actually a client of a Stripe-connected provider. A client who signed up on your domain is sent to this grid after verifying, and prompted on their dashboard until they subscribe. The client-side view is documented in Plans from your provider.

What a paid invoice does

On invoice.paid — a subscription being created or renewed — Evoriqa resolves the invoice's price to your client plan, applies that plan's three limit overrides and billed amount to the client workspace, and allocates that plan's monthly credits from your pool to the client — one month for any cadence, after forfeiting the client's unspent pool credit from the month before (the client's own top-up packs stay, and so does any provider top-up pack credit you've hand-allocated to them; a stale, out-of-order invoice allocates but never forfeits). An annual client invoice stamps its billing period on the subscription, and the drip job pulls months 2–12 from your pool on each monthly anniversary, forfeiting each prior month; a pool shortfall pins the month for the same refill that a renewal uses. A manual invoice grants nothing.

A mid-cycle plan change doesn't wait for the next renewal. When a client switches plans themselves, the new plan's limits apply immediately and they are topped up to the new plan's period allowance minus whatever this cycle already granted — the renewal credits plus any earlier top-ups. A downgrade's delta clamps to zero: already-granted credits are never taken back, only future grants shrink.

A short pool doesn't lose the allocation — it resumes. If your pool can't cover the full amount at invoice time, the client gets whatever is available now and the shortfall is pinned on their subscription for the current cycle. The moment your pool is topped up — a new reseller-plan invoice, a mid-cycle tier upgrade, or buying a top-up pack into it — every client still short is credited automatically. There is nothing to re-trigger by hand.

Credit drawn from a top-up pack to cover a client's plan allowance this way stays top-up credit on that client: it doesn't expire at their renewal (only the plan part does), they spend it after their plan credit, and it returns to your pool as top-up credit if you reclaim it or delete the client.

All of it is idempotent per invoice: a redelivered Stripe event is always a safe no-op.

Refunds, disputes and cancellation

A refund or dispute on a client's charge claws back their unspent allocated credits to your pool — never more than they still hold, so a partly consumed grant can't drive the ledger negative. You get a bell notification when it happens. A later won dispute, or reinstated funds, restores exactly what was clawed back.

The same applies when a refund itself fails or is canceled — the customer's bank returns the money to you, so it never reached your client and their credits are restored. A charge that is still fully refunded by other successful refunds keeps its clawback.

Cancelling clears the client's three limit overrides — they fall back to their base workspace plan's caps — and, in the same clear, nulls the per-client API-access override (a heal, since API access is otherwise a platform-admin decision, not one of the plan's limits). Their credits stay. Those were paid for.

Disconnecting

Disconnect takes the same critical step-up as connecting. It removes your stored credentials, clears stale rows, stops webhook verification, and stops allocating credits for new invoices.

Warning:

Disconnecting does not cancel anything, so it is refused while any client subscription is still live (active or past-due) on your Stripe account, or while a client checkout started in the last 24 hours is still pending. The refusal names how many. Cancel or migrate live subscriptions in Stripe first; a client who keeps opening checkouts can hold the disconnect off, so retire your client plans and try again once the last checkout is 24 hours old. If a client's checkout is mid-way through talking to Stripe, the disconnect answers "A client checkout is finishing — try again in a minute." Client payment pages expire after 23 hours, inside that window.

Reconnecting a different Stripe account is refused while any client still has a live (active or past-due) subscription tied to the old one — even after a disconnect in between, since disconnect doesn't cancel those subscriptions — and while a client checkout started in the last 24 hours is still pending, because its payment page lives on the old account. A client whose checkout is in flight while you reconnect or rotate your Stripe key is asked to try the checkout again. To switch accounts for good: reconnect the original account, cancel or migrate those clients from the Stripe Customer Portal (or remove those client workspaces), then connect the new one.

Deleting a client workspace best-effort cancels that client's live subscription on your Stripe account first, so nothing keeps charging after a client is gone. A second subscription on one of your client plans is cancelled too; anything else you bill the same customer for (hosting, a retainer) keeps billing. Account deletion and the purge job do the same.

Webhook activity

Reseller → BYO Stripe → Webhook activity lists every event your Stripe account has delivered, filterable by type and date range: event type, event id, a duplicate-delivery flag, and the time it arrived. Open a row for the full JSON payload and its processed state.

Scoping is double-enforced against your organisation, so you only ever see your own account's events — never platform events, not even your own organisation's reseller-subscription ones.

Where to go next

Last updated