Billing & Monetization
What this is
Section titled “What this is”Most platforms let you pay them. Axowl billing points the other way: your organization charges its own end users, through the same identity core that authenticates them.
Three structural properties set it apart:
- Per-app-group collection. Each app group (brand) runs its own plans and charges its own users under its own name. One organization, many collecting brands.
- Consolidated statements. Every brand rolls up into one organization-level statement — the whole company in one book.
- Sealed invoices. A period statement is sealed the moment it closes. Every line traces back to the ledger entry it billed, and anyone can verify the seal independently — see Invoices and Seals & integrity.
Money settles to your own Stripe account. Axowl takes a rate — it never holds your funds. This path (Application payment integration) is open to organizations in the 44 countries where Stripe opens seller accounts.
Connecting your own gateway (KG Inicis or Toss Payments through PortOne, or Razorpay) is open to organizations in any country — bring the merchant account you already have. Meeting the gateway’s own merchant requirements (for example a local business registration) is between you and the gateway. Application payment integration (payments go to your own Stripe seller account) is for organizations in the 44 countries where Stripe opens seller accounts. Korean organizations see only their own gateway. Payment goes straight from the buyer to your gateway account, Axowl still runs products, subscriptions, vouchers and entitlements, and there is no take rate on this path — you pay only your gateway’s own fees. The marketplace commission below still applies to marketplace sales and is billed to you monthly in arrears, since no money passes through Axowl to withhold it from.
Your organization needs a country. Every payment decision above starts from the organization’s country (Organization Settings › General). A new organization must be created with one, and if an older organization has none, every payment door — payout account, the collection switch, connecting your own gateway — answers 409 REGION_REQUIRED and the dashboard asks you to set the country first, instead of guessing.
One organization is one legal entity. The country is the country your selling company is registered in, so it decides which payment options open. If you also sell through a company registered in another country — for example a Korean company that sells in the US through its US subsidiary — create a separate organization for that company. Where a payment option doesn’t open, the dashboard says so and links to creating a new organization.
The schedule
Section titled “The schedule”One rate on billed volume. No per-invoice fee, no monthly minimum. Stripe processing passes through at cost.
| Plan | Take rate | App groups that collect | Volume cap | Consolidated + verify API |
|---|---|---|---|---|
| Free | 0.7% | 1 | $5,000 / month | — |
| Pro | 0.7% | 1 | No cap | — |
| Pro+ | 0.6% | Unlimited | No cap | — |
| Business | 0.5% | Unlimited | No cap | ✓ |
| Enterprise | from 0.4% | Unlimited | No cap | ✓ |
The same numbers appear on the live pricing page.
How the schedule behaves:
- Free is metered by volume, not by features. The full engine — plans, seats, usage, sealed invoices — works on Free. Past the cap, new charges pause until you upgrade; existing subscriptions keep collecting.
- Sealing is not gated. Every invoice on every plan is sealed — that is how the product works. Business gates the organization roll-up, the public verify API, and audit export.
- Downgrades never cut a live subscription. Dropping below a plan blocks new collection that the lower plan wouldn’t allow; charges already running are grace-period protected.
The collection switch
Section titled “The collection switch”Each app group has a collection switch: Dashboard → Applications → your app group → Payments → “Billing collection”. Turning it on is plan-gated — how many app groups may collect at once comes from the schedule above (Free/Pro: 1, Pro+ and up: unlimited). Past the limit the server answers 403 { "error": "UPGRADE_REQUIRED", "feature": "billing.collect" }. An organization outside the 44 Stripe seller countries gets 409 NOT_OFFERED, and an app group whose local market country is outside them gets 409 MARKET_NOT_OFFERED (connect your own gateway, or don’t collect payments). Turning it off is always allowed, and a downgrade never flips the switch on a group that is already collecting — only new enables are blocked.
Every flip is a sealed audit event: appgroup.monetization.enabled / appgroup.monetization.disabled.
Turning collection on or off is billing, so it follows the owner carve-out: the organization owner, or a member explicitly granted the billing-manage permission (org.org.billing_manage), may flip it. Editing the app group itself is not enough — an admin without that grant gets 403 PERMISSION_DENIED.
Reading what you collected
Section titled “Reading what you collected”Collection lands in your organization’s cash account on the settlement ledger, one line per sale. Because those lines are keyed by the brand that sold, the org-level total needs its own call:
GET /api/org/{slug}/billing/earnings{ "configured": true, "cashBalance": 1985.40, "brands": [ { "brand": "acme-cloud", "cashBalance": 1985.40, "lines": 42 } ]}This is the opposite direction from /billing/credit, which is what your organization pays Axowl. Cash and credit are separate books by design — this endpoint only ever reports settled money. Owner-only (view.billing). When the settlement ledger cannot be reached, the answer is cashBalance: 0, an empty brands list and "unreachable": true — never an estimate.
For sales by period, by app and by product, use the revenue call (owner or admin). It reads the same settlement ledger, across every brand of the organization:
GET /api/org/{slug}/marketplace/revenue{ "gatewayOk": true, "koreanPackage": false, "payments": 4, "thisMonth": { "grossUsd": 285.02, "netUsd": 268.77 }, "thisYear": { "grossUsd": 285.02, "netUsd": 268.77 }, "total": { "grossUsd": 285.02, "netUsd": 268.77 }, "byDay": [ { "period": "2026-09-30", "grossUsd": 285.02, "netUsd": 268.77 } ], "byMonth": [ { "period": "2026-09", "grossUsd": 285.02, "netUsd": 268.77 } ], "byYear": [ { "period": "2026", "grossUsd": 285.02, "netUsd": 268.77 } ], "byApp": [ { "key": "appgroup_…", "name": "Shiftboard", "thisMonth": 285.02, "thisYear": 285.02, "total": 285.02, "netTotal": 268.77, "payments": 4 } ], "byProduct": [ { "appKey": "appgroup_…", "appName": "Shiftboard", "productName": "Setup pack", "thisMonth": 200.00, "thisYear": 200.00, "total": 200.00, "netTotal": 188.60, "payments": 1 } ]}grossUsd is what the buyer paid. netUsd is that amount after the take rate and the marketplace commission; the card processing fee is deducted by your own Stripe account and is not in these numbers. Dates are the payment dates, in UTC. byDay covers the last 30 days and byMonth the last 12 months; byYear starts at the first payment. A marketplace payment is grouped under the app group it was made for; a sale outside the marketplace, such as a retail voucher, is grouped under its brand (key = brand: + the brand slug). productName is the product as it was at payment time, so a plan change leaves earlier payments under the old name.
When payments cannot be read, or the answer is incomplete, the call returns gatewayOk: false with zeros. It never fills in an estimate.
The fields above are the US-dollar sales. The response also carries currencies — one entry per currency sold (currency, payments, and the same thisMonth … byProduct set, in that currency’s own amounts, never converted or added across currencies) — which is where sales through your own gateway in KRW or INR appear. displayCurrencies lists the currencies the console offers for a combined total, fx holds the exchange rates it converts with, and hasListedApps says whether any app group is published on the marketplace. koreanPackage only tells the console whether to offer a currency switch. On the live platform, payments made through a test gateway connection are left out.
The policy API
Section titled “The policy API”Payment engines read the org’s billing policy before charging on its behalf — Axowl publishes the policy; the engine executes it.
GET /api/public/v1/monetizationX-Api-Key: ah_live_…{ "takeRatePercent": 0.7, "currency": "USD", "perInvoiceFixedFeeUsd": 0, "stripeSellerEligible": false, "stripeDirectRailOpen": true, "ownGatewayEligible": true, "ownGatewayProviders": ["portone", "razorpay"], "ownGatewayTakeRatePercent": 0, "sellerPolicyRequiredFor": ["stripe_payout", "own_gateway"], "sellerPolicy": { "version": "v1.0-2026-10-21", "accepted": false, "signedAt": null, "url": "/legal/seller-policy" }, "monthlyVolumeCapUsd": 5000, "collectingAppGroups": { "limit": 1, "enabled": 1 }, "consolidatedEnabled": false, "appGroups": [ { "key": "appgroup_…", "name": "…", "monetizationEnabled": true } ]}monthlyVolumeCapUsd is null on paid plans; collectingAppGroups.limit of -1 means unlimited. Unknown or missing plans resolve fail-closed to the Free rules. stripeSellerEligible says whether this organization may open a Stripe seller account today; a payment engine opening Stripe Connect for the organization reads it fail-closed, the same way it reads sellerPolicy.accepted. stripeDirectRailOpen is the platform-wide switch behind it. ownGatewayEligible and ownGatewayProviders say whether this organization may connect its own gateway and which ones (every supported gateway — portone, razorpay — for any organization with a country set; an empty list when the country is missing); ownGatewayTakeRatePercent is always 0. sellerPolicyRequiredFor lists the doors that stay closed until the owner has signed the seller policy — both the Stripe payout account and the own-gateway connection — so an engine opening either door reads sellerPolicy.accepted first and refuses when it is false.
appGroups[].key is the App Group public key (appgroup_…) — the one identifier to join on. It is what the customer copies from Applications > Settings, what POST /brands/{slug}/bind-app-group stores, and what GET /catalog/by-app-group/{key} is keyed by. Do not keep a second spelling of this binding alongside it.
A platform payment engine that holds a brand→org binding rather than the org’s own key asks by org id instead. This call is limited to platform keys — any other key gets 403 — and returns the same policy, with appGroups entries carrying key and monetizationEnabled but no name:
POST /api/public/v1/orgs/monetizationX-Api-Key: ah_live_…Content-Type: application/json
{ "orgId": "…" }Verifying a sealed invoice
Section titled “Verifying a sealed invoice”Anyone holding an invoice id can verify the sealed statement — no API key, no Axowl account:
GET /api/public/v1/invoices/{id}/verifyThe endpoint recomputes the statement hash from the stored lines and compares it to the value sealed at issue time. It returns the verdict and both hashes — never amounts (it is an anonymous surface). Statements still open for the current period report "status": "open" and seal when the period closes. Available when the issuing org is on the Business plan or higher; below that the endpoint answers 403 UPGRADE_REQUIRED.
How the rate is collected
Section titled “How the rate is collected”Settlement runs on Stripe Connect. When a consumer pays for a catalog product, the payment is charged on the seller’s own Stripe account (a direct charge), and the take rate is withheld at the source as a Stripe Connect application fee — never billed separately, and never debited from your Axowl credit ledger (cash and credit are separate books by design). The engine reads this page’s policy API at charge time; if the policy cannot be read, the charge is refused rather than guessed. Past the Free volume cap, new charges are refused with upgrade_required — running subscriptions are unaffected.
Marketplace commission
Section titled “Marketplace commission”When another organization buys your app on marketplace.axowl.com, Axowl adds a marketplace commission of 5%. It is separate from the take rate above and is added on top of it. It applies to the amount actually paid after vouchers and discounts, on every payment. For a monthly plan, that means every month. The pricing page shows the same rate.
Like the take rate, it is withheld at the source as part of the Stripe Connect application fee — or, when the seller connected its own gateway, accrued per payment and billed monthly in arrears. In the ledger it is a separate line from the take rate, so the two can always be told apart. Marketplace Subscription plans are real Stripe subscriptions that charge monthly. A voucher discounts the first invoice only. A refund reverses the seller’s lines of that payment in proportion to the amount refunded; the take rate and the commission already charged are not returned. How buying and installing work is in Applications → Selling on the marketplace.
Payment rules in plain words
Section titled “Payment rules in plain words”Each rule says what happens and why.
What Axowl charges, and on which path. Money reaches a seller in one of two ways, and they are priced differently. Axowl does not take your customers’ money and forward it.
| Path | Who moves the money | Axowl’s fee | Where |
|---|---|---|---|
| Your own gateway — PortOne in Korea (with a KG Inicis or Toss Payments contract), Razorpay in India | The buyer pays straight into your gateway account | No take rate. Razorpay needs the Razorpay connection add-on ($3/month per organization); PortOne connections have no add-on fee. You also pay your gateway’s own fees (PortOne or Razorpay). The 5% marketplace commission still applies to marketplace sales and is billed to you monthly | Organizations in any country |
| Application payment integration — your own Stripe seller account | Stripe pays you directly; on each payment Stripe splits the plan’s rate off for Axowl | The plan’s rate on the amount paid — 0.7% on Free and Pro, lower on higher plans (see the schedule); no per-invoice fee, no monthly minimum | Organizations in the 44 countries where Stripe opens seller accounts |
On no path does Axowl hold your customers’ money. “Free” above means the Axowl fee: your payment gateway still charges its own processing fee, as it would without Axowl.
Sellers who already have a Stripe account keep it. Nothing changes for sellers who connected before: their payouts, subscriptions and refunds keep working exactly as before, at the same rate. If that ever changes, you will be told in advance and the change will appear here first.
Signing the seller policy comes before any payout door — including your own gateway. Before an organization can connect a Stripe payout account or its own gateway, the organization owner reads the seller policy (sanctions, anti-money-laundering, counter-terrorist-financing) and signs it with a passkey seal. The dashboard asks for the signature right where you connect; the API answers 409 SELLER_POLICY_REQUIRED until it is signed. Why both doors: a gateway connection is a place where money arrives, and the law we follow does not care which processor moves it. One signature covers the organization; a new policy version asks for a new signature.
Test keys do not take sales on the live platform. On api.axowl.com, a gateway can be connected with a test key (a Razorpay rzp_test_… Key ID, or PortOne with the test checkbox) and its test payment can be run, but the connection is not confirmed for sales: the confirm step answers TEST_CHANNEL_CANNOT_CONFIRM (as confirmError). The exception is an app group in Development, which takes test payments only. A “payment” made with a test card is not money, yet it would still grant entitlements and count as sales. Use test.axowl.com to try the whole flow with test keys; a production app group on the live platform sells with live keys only.
Disconnecting a gateway ends the subscriptions it created first. When you disconnect Razorpay, Axowl first asks Razorpay to end every live subscription that was created through that connection — at the end of the current paid period, so nobody is cut off mid-period and nobody is charged again. Only when every subscription has been handed over does the connection close. If Razorpay cannot be reached or refuses, the connection stays and the API answers 409 SUBSCRIPTIONS_NOT_CANCELED with how many subscriptions are still live; cancel them in your Razorpay dashboard, then disconnect. Why: once the keys are gone, Axowl can no longer stop those charges, and your customers’ cards would keep being charged for an app they no longer have. PortOne card registrations are different — Axowl charges them each period itself, so revoking the connection simply stops the charging.
Organizations in Korea buy add-ons in won. A Korean organization that reaches the US-dollar (Axowl Credit) add-on route gets 409 krw_org_use_krw and the dashboard explains it in one sentence: the product is sold in won; open it from the Korean-language screen. Exceptions: an organization that locked its billing to USD, and add-ons that exist only on the credit route (Project Management AI). The reason is the card-company review for the won rail — Korean customers must see and pay the won price.
App groups in development
Section titled “App groups in development”An app group in the Development stage takes test payments only: test gateway keys can be connected even on the live platform, and starting a purchase without one answers 409 LIVE_PAYMENTS_REQUIRE_PRODUCTION. Promote the app group to production to take live payments — promotion requires a live gateway key when the group collects payments. See Applications → Development and production.
Connecting Stripe
Section titled “Connecting Stripe”Organizations registered in one of the 44 countries where Stripe opens seller accounts collect through their own Stripe account. On App Group ▸ Payments the owner creates the Stripe account right on the page; Stripe’s own setup opens there, and the account can take payments once Stripe has verified it. The fee is the plan’s rate on each payment, taken by Stripe for Axowl, and the money goes to your Stripe account, never through Axowl. The seller policy is signed first (409 SELLER_POLICY_REQUIRED until then). API: POST /api/org/{slug}/app-groups/{groupId}/payout-session.
Connection add-on. A new Razorpay connection — or reusing one on another app group — needs the Razorpay connection add-on ($3/month per organization, available on every plan including Free). Without it the connect call answers 402 ADDON_REQUIRED with addon: "addon.razorpay_gateway" before Axowl contacts Razorpay; the dashboard offers to turn it on in place. Connections made before the add-on existed keep working. While an app group is connected to Razorpay, turning the add-on off answers 409 ADDON_IN_USE — disconnect Razorpay first. In the gateway list, organizations in the 44 Stripe countries also see Stripe at the top: it is Application payment integration (your own Stripe account, take rate per your plan), not a key-based connection.
Your own gateway works from any country. Any organization can connect PortOne or Razorpay, whatever country it is registered in — for example a US company that already has a PortOne merchant account in Korea. Each gateway charges in its own currency (PortOne in KRW, Razorpay in INR), so an app group with a local market connects only that country’s gateway: a Korea app takes PortOne, an India app takes Razorpay, and a local app for any other country cannot connect either (409 MARKET_NOT_OFFERED). Organizations in the 44 Stripe countries can also collect through Stripe as above, unless the app group’s local market country is outside those 44 countries: then creating the group with collection on, turning collection on, the payout account and switching to Application payment integration answer 409 MARKET_NOT_OFFERED.
The seller is the merchant
Section titled “The seller is the merchant”Every card payment that belongs to a seller is charged on the seller’s own Stripe account: a marketplace app, a catalog product (one-time or monthly), a voucher purchase, and a consumer topping up a brand’s credit.
| Who | |
|---|---|
| Merchant for the payment (the name on the buyer’s card statement) | The seller |
| Refunds | Paid from the seller’s Stripe balance. The seller issues them in its own Stripe dashboard |
| Card disputes (chargebacks) and the dispute fee | Taken from the seller’s Stripe balance. The seller answers the dispute in its own Stripe dashboard |
| Card processing fee | Charged by Stripe on the seller’s account, at Stripe’s rate for the seller’s country. Axowl does not collect it |
| What reaches Axowl | The take rate, plus the 5% marketplace commission on marketplace sales |
| A balance the seller cannot repay | Stripe’s loss. It is not taken from Axowl |
What this means when you sell:
- Set up card payments once. The payout account step in Applications → Payments creates a Stripe account that can take card payments. An older payout account that could only receive transfers is replaced by the same step. Until Stripe has verified the new account, checkout answers
409 brand_not_payablewith areasonofnot_started,upgrade_requiredornot_verified. - When a buyer disputes a payment on a monthly plan, the subscription on that card is ended so the card is not charged again, and you are told by email.
- Taxes on what you sell are yours to handle, as the merchant.
Axowl’s own charges — plans, add-ons and credit top-ups — are not part of this: for those, Axowl is the merchant.
Related
Section titled “Related”- Invoices — the sealed period statement itself.
- Seals & integrity — what a seal proves and how to verify one.
- Public API — the policy and verify endpoints.