Skip to main content
POST
App Subscriptions
App subscriptions are the recurring (or one-time) charges a merchant pays for an installed app. They are distinct from the store-level platform subscription at /api/v1/billing/* — each one is scoped to an installation that links a single app to a single merchant. A subscription is always created against an existing installation. If the app is not installed yet, the API returns 404 — App is not installed. Auth: merchant JWT (Authorization: Bearer <merchant-jwt>). All endpoints below require a merchant session — they cannot be called with an OAuth app token.

Charge approval flow

  1. App developer publishes pricing for their app: POST /apps/billing/pricing/:appId with { monthly, yearly, currency }. This provisions the Stripe Product + Price objects.
  2. Merchant installs the app via the marketplace.
  3. App (or merchant UI) calls POST /apps/billing/checkout-session to obtain a Stripe Checkout URL. The merchant is redirected, completes payment, and is returned to successUrl.
  4. Stripe fires checkout.session.completedPOST /apps/billing/webhook verifies the signature and marks the installation as subscribed plus records a billing transaction.
  5. Subsequent renewals fire invoice.paid webhooks; one transaction row is created per cycle.
For usage-based pricing (per-API-call, per-email-sent, etc.) the developer also records usage events via POST /apps/billing/usage — see Usage Records.

Setup pricing

string
required
Application UUID. The app must be owned by the calling developer or admin.
number
required
Monthly recurring price in major currency units (e.g. 9.99 for $9.99).
number
required
Yearly recurring price in major currency units.
string
required
ISO-4217 currency code (e.g. USD, EUR, INR).
Returns { status, type, message, data: { stripeProductId, stripePriceMonthly, stripePriceYearly } }.

Subscribe an installation

POST /apps/billing/subscribe creates a Stripe Subscription wired to the merchant’s stored payment method. Use this when the merchant has already saved a card on the platform; for first-time card collection, use /checkout-session (below).
string
required
Application UUID. Must correspond to an existing installation for the calling store; otherwise 404.
string
required
Either monthly or yearly. The Stripe Price for that interval must have been provisioned via POST /pricing/:appId.
string
Stripe Subscription id.
string
UUID of the installation now linked to this subscription.
string
Stripe status: active, incomplete, incomplete_expired, past_due, canceled, trialing, unpaid.
string
ISO timestamp of next renewal.

Hosted checkout session (charge approval URL)

POST /apps/billing/checkout-session returns a Stripe Checkout URL. This is the canonical “charge approval URL” — redirect the merchant to it, they pay, Stripe redirects them back to successUrl.
string
required
UUID of the installed app.
string
required
One of monthly, yearly, one_time. one_time is used for non-recurring app charges.
string
URL Stripe redirects to on payment success. Defaults to the app’s configured success URL.
string
URL Stripe redirects to if the merchant abandons checkout. Defaults to the app’s configured cancel URL.
string
Stripe-hosted checkout URL. Open in a new tab or redirect.
string
cs_… Stripe Checkout Session id.
string
UUID of the linked installation.

Cancel a subscription

POST /apps/billing/cancel cancels the Stripe Subscription tied to an installation. The installation row remains; only the recurring charge is stopped. Cancellation takes effect at the end of the current billing period — the merchant retains access until then.
string
required
UUID of the installation. Get it from GET /apps/installations or from the subscribe / checkout-session response.
string
Stripe subscription status after cancellation — typically canceled (if immediate) or active with cancelAtPeriodEnd: true.
boolean
true when the merchant keeps access until currentPeriodEnd.
string
ISO end date.

Active subscriptions for a merchant

There is currently no dedicated “list app subscriptions for this merchant” endpoint. Use one of:
  • GET /apps/installations (merchant) → each row carries billing: { subscriptionId, status, currentPeriodEnd, planInterval }.
  • GET /apps/billing/transactions (merchant) → groups paid invoices per installation. See Transactions.
A dedicated GET /apps/billing/subscriptions endpoint that returns just the active subscription rows for the merchant is planned but not yet exposed publicly.

Webhook

POST /apps/billing/webhook (public, no auth) is the Stripe webhook endpoint. The handler verifies the Stripe-Signature header against STRIPE_APP_BILLING_WEBHOOK_SECRET and processes: Apps subscribe to these outbound webhook topics in their manifest — they do NOT receive the raw Stripe webhook.

Error codes