Selling from your app

Connect your own Stripe account, define products per app, take payments from your users, and gate your app on what each user bought.

Your app can sell its own products (subscriptions or one-time purchases) to its own users. It runs on your Stripe account: money moves between your customers and you, and Authoric is not in the payment path. The catalog and every purchase are rows in your app's own database (products, user_subscriptions, user_orders), so they are queryable like the rest of your data.

Checkout runs on your page

The backend handles products, payments, subscriptions, cancellation and entitlements, with Stripe's webhooks reconciled into your app's database. Your app confirms payment on its own page with Stripe.js, using the clientSecret these routes return.

Set up

Connect Stripe

In Integrations › Providers, choose Connect Stripe and paste your Stripe secret key. It is encrypted before it is stored. Test and live are separate connections, and Authoric creates the webhook endpoint on your Stripe account for you, so purchase status flows back without any setup.

Create products in the app

In your app, open Commerce › Products and create a product: a name, a price in USD, and billing Monthly, Yearly or One-time. A recurring product can add the other interval at a discount. Each app keeps its own product list.

Say what a purchase grants

Give the product entitlements: limits (a number, such as projects: 25) and features (on or off, such as exports). Your app reads them back per user, so "what did this user buy" becomes one call.

A price cannot be edited once it exists, because existing subscribers are billed by it. Change Price adds a new one; existing subscribers keep the price they bought.

Who can buy

Purchasing is granted to the user role by the seeded App Product Purchase policy, so everyone who signs up can buy. A person who joined an organization by invitation holds no role until you give them one: give them user (or put the purchase actions in a role of your own) if they should be able to buy. Purchases belong to the signed-in user, never to whoever is named in a request.

Take a payment

Start the purchase on your server or in the browser

POST /{appUid}/autocrud/products/actions/subscribe with a recurring Stripe price id, or .../products/actions/order with a one-time price id and an optional quantity. Both return a clientSecret.

Confirm it with Stripe.js

Mount Stripe's Payment Element with the clientSecret and confirm. The card details go to Stripe, never through your server or Authoric.

The webhook settles it

Stripe reports the outcome to Authoric, which updates the row in your app's database: a subscription becomes active, an order succeeded. Read the status back rather than trusting the browser's confirmation.

curl -X POST "$AUTHORIC_URL/$APP_UID/autocrud/products/actions/subscribe" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "priceId": "price_1Q8xYzAbCdEf" }'

Test while you build, live when you launch

Each app has a billing mode, set in the console under the app's Products. A new app starts in test: everyone who buys in it, your testers included, pays with Stripe's test cards. Switch it to live when you launch, and from then on every purchase in your app is real. The mode is the app's, not the request's: these routes take no stripeMode, and entitlements are read in the app's mode, so a test purchase never unlocks anything in a live app. You can still run a test checkout from the console after launch.

Manage subscriptions

All of these act on the signed-in user's own purchases.

RouteDoes
GET /{appUid}/autocrud/user_subscriptions/actions/subscriptionsLists the user's subscriptions: uid, product_uid, status, current_period_end, cancel_at_period_end, and the entitlements each grants
POST /{appUid}/autocrud/user_subscriptions/actions/{subscriptionUid}/cancelCancels at the end of the current period. The user keeps access until then
POST /{appUid}/autocrud/user_subscriptions/actions/{subscriptionUid}/resumeUndoes a pending cancellation

Send the subscription's uid in the body as well as the path ({ "subscriptionUid": "..." }).

Gate your app on what was bought

GET /{appUid}/autocrud/user_subscriptions/actions/entitlements merges the limits and features of every active subscription the user holds:

{
  "status": "active",
  "limits": { "projects": { "soft": 25, "hard": 25 } },
  "features": { "exports": true },
  "subscriptions": 1
}

A user with no active subscription gets "status": "none" and empty limits and features. Check entitlements on the server side of anything you charge for: in a handler or a custom action, not only in your UI.

Errors to branch on

CodeStatusMeaning
PRICE_NOT_RECURRING400subscribe was given a one-time price. Use order.
PRICE_IS_RECURRING400order was given a recurring price. Use subscribe.
PRICE_SCOPE_MISMATCH403The price belongs to a product of another app.
SUBSCRIPTION_NOT_FOUND404No such subscription for this user.
NOT_APP_USER403Only an app's own signed-in users buy through these routes.
(none)403The caller's roles do not include the purchase actions (products:subscribe, products:order).

What's next

On this page