Paid Public Flows
Quick Answer
To sell a flow today:
- Open the creator workspace billing page and complete seller payout onboarding.
- Open the flow's Publish page.
- Save the public listing, pricing or price catalog, and optional trial settings.
- Publish the current draft as the live buyer version.
- Verify buyer checkout from another workspace.
Example:
- Seller onboarding:
/<workspace-id>/billing - Flow publishing:
/<workspace-id>/flows/<slug>/publish - Public app page:
https://breyta.ai/apps/<flow-slug> - Buyer verification: sign in as a different workspace and open
/<buyer-workspace-id>/discover
Breyta handles buyer checkout, Stripe webhooks, entitlement state, and payout routing.
The creator does not create Stripe Checkout Sessions, products, or prices manually.
The creator does need a seller account for their workspace so payouts can be routed correctly.
Paid publishing and seller payout setup are currently behind the
BREYTA_FLOW_REUSE_APPROVER_USER_IDS rollout gate. If the Publish page or
seller-payout controls are missing, confirm that the current user id is included
in that allow-list.
What Breyta Handles Vs What The Creator Handles
| Area | Breyta handles | Creator handles |
|---|---|---|
| Buyer payments | Stripe Checkout Sessions, webhook delivery, checkout completion, entitlement state | Nothing directly in Stripe Checkout |
| Seller payouts | Connected-account routing, payout transfer metadata, Connect account persistence on the workspace | Completing Stripe onboarding and giving Stripe required payout details |
| Flow publishing | Runtime install/check/run/release machinery | Authoring the flow, setting metadata, releasing the live version |
Seller Onboarding (Once Per Workspace)
Breyta uses Stripe Connect seller accounts for creator payouts.
The current integration creates an Express connected account for the creator workspace and routes buyer payments to that account.
Creator onboarding path:
- Open
/<workspace-id>/billing. - In the seller payouts card, start or resume Stripe onboarding.
- Complete the Stripe-hosted onboarding flow.
- Return to Breyta. The billing page refreshes seller payout state through
?billing_refresh=seller.
The workspace is ready to sell when the Connect state is effectively active.
In sandbox validation, the ready state corresponded to:
charges_enabled=truepayouts_enabled=truecard_payments=activetransfers=active
If seller onboarding is incomplete, buyer checkout is blocked with:
Creator payouts are not configured for this flow
Operators can still use the admin Stripe Connect endpoints for diagnostics and
sandbox runbooks, but they are no longer the normal creator path.
Publish From The Flow
Use the dedicated Publish page for the flow:
/<workspace-id>/flows/<slug>/publish
The Publish page owns the creator-facing paid-flow controls:
- public listing visibility for Discover/install surfaces
- free, one-time, subscription, usage, or subscription usage pricing
- optional price catalogs for multiple plans
- subscription interval
- before-install paid checkout
- prepaid run-pack quantity for usage pricing
- included runs for subscription usage pricing
- optional subscription trial days
- whether a trial requires a payment method
- draft-to-live publishing
- seller payout readiness
- installs and checkout activity
For a paid flow:
- Make sure the flow has a saved draft.
- Open the Publish page.
- Choose
One-time purchase,Subscription,Usage per run, orSubscription usage. - Enter amount and currency.
- For subscriptions, choose the billing interval and optional trial settings.
- For usage pricing, enter the run-pack quantity. For subscription usage, enter included runs per billing period.
- Enable public listing.
- Save settings.
- Publish changes.
Public paid flows can include manual interfaces, schedules, and webhook
interfaces. End users manage automatic entrypoint enablement per installation.
The checkout path charges one-time purchases, subscriptions, prepaid usage
packs, and subscription-usage plans through Stripe Checkout. Usage packs and
subscription usage then rely on Breyta's run ledger for allowance tracking.
Trial-run packages can bypass Stripe first and start with a Breyta trial
entitlement when the selected pricing shape supports that path.
Advanced source/CLI workflows can still represent paywall.when explicitly.
Breyta's default public-flow platform fee is 5% plus 30 cents USD. One-time
USD checkout applies both components. Subscription checkout applies the
percentage component through Stripe Checkout; fixed subscription fee settlement
is tracked separately.
The publish action creates the live version buyers install. If the draft differs
from the live version, the page shows that the draft needs publishing.
Author Monetization In Source (Advanced)
The Publish page is the normal creator path. Source-first authoring remains
useful for code-reviewed flow definitions, fixtures, and CLI-heavy operations.
The flow file can carry marketplace monetization metadata directly, and
breyta flows push persists it. For new paid apps, author the catalog under
:marketplace {:app {... :monetization {:plans [...]}}}. Legacy flow-level
:marketplace {:monetization ...} is still supported for existing listings,
but new paid apps should use app-owned identity so Discover, checkout, billing,
and install ownership all use the same app id and plan ids.
Pricing Models
Choose the pricing type based on what the buyer is purchasing:
| Pricing type | Buyer pays | Buyer receives | Typical use case | Required fields |
|---|---|---|---|---|
:free | Nothing | Free install and run access | Open tools, lead-gen flows, free templates | pricing.type |
:one-time | One upfront payment | Paid access without recurring billing | Fixed-fee utility, template, or app | amount, currency |
:subscription | Recurring monthly or yearly charge | Access while the subscription stays active | SaaS-style app access | amount, currency, interval |
:usage | One-time payment for a prepaid pack | A fixed number of successful runs with no time expiry | "$100 for 500 runs" | amount, currency, unit, included-quantity |
:subscription-usage | Recurring monthly or yearly charge | A fixed number of successful runs every billing period | "$49/mo includes 22 runs" | amount, currency, interval, unit, included-quantity |
Operational rules:
:usageis prepaid packaging, not pay-as-you-go metering.:usagepacks do not expire by time; they are consumed only by successful completed runs.:subscription-usageresets allowance on subscription renewal.:subscription-usagedoes not currently bill paid overages. When included runs are exhausted, the buyer is blocked until renewal or a future product change.- Failed, cancelled, terminated, and timed-out runs do not consume paid allowance.
Trial Options
Supported trial shapes depend on the pricing type:
| Pricing type | Supported trial |
|---|---|
:one-time | trial.runs |
:subscription | trial.days, optional trial.payment-method-required |
:usage | trial.runs |
:subscription-usage | trial.runs, or pricing.free-quantity as the fallback no-card trial-run allowance when explicit trial.runs is absent |
Important trial details:
trial.daysis the subscription-style time-based trial.trial.runsis the run-counted trial.pricing.free-quantityon:subscription-usageis a PLG-style fallback trial entry point, not a second paid allowance bucket.- If both
trial.runsandpricing.free-quantityare present on:subscription-usage, explicittrial.runswins.
Supported values:
pricing.type::free,:one-time,:subscription,:usage,:subscription-usagepricing.amount: positive price in major currency units. Decimals are allowed when the currency supports them, for example"0.99"USD.pricing.currency: lowercase ISO currency code such as"usd"pricing.interval::monthor:yearfor subscriptions and subscription usagepricing.unit::runfor usage and subscription usagepricing.free-quantity: zero or more free trial runs for:usage, or fallback no-card trial runs for:subscription-usagewhentrial.runsis not setpricing.included-quantity: positive paid run quantity for:usage, or positive included runs per billing period for:subscription-usagepaywall.when::before-installor:before-runfor paid flowstrial.days: positive integer, optionaltrial.payment-method-required:trueorfalse, optionalplans: app-owned catalog entries under
:marketplace {:app {:monetization {:plans [...]}}}. Every plan must
normalize to a unique stableplan-id, every entry must be valid, and at
most one plan can be markeddefaultorrecommended. If no default is set,
the first plan is treated as the default.- Seat-based pricing is not implemented. Do not describe a plan as "N seats" or
"N installs" unless the product has added explicit seat entitlements. Use
run quantities only for usage-priced plans.
New app-owned source example:
{:slug :customer-insights
:name "Customer Insights"
:tags ["analytics" "customer-insights"]
:discover {:public true}
:marketplace
{:visible true
:app
{:app-id "customer-insights-suite"
:app-name "Customer Insights"
:app-primary-flow-slug "customer-insights"
:app-flow-slugs ["customer-insights"]
:monetization
{:plans
[{:plan-id "starter"
:name "Starter"
:default true
:pricing {:type "subscription"
:amount 29
:currency "usd"
:interval "month"}
:trial {:days 7
:payment-method-required false}}
{:plan-id "pro-pack"
:name "Pro Pack"
:pricing {:type "usage"
:amount 49
:currency "usd"
:unit "run"
:included-quantity 250}}
{:plan-id "metered"
:name "Metered"
:pricing {:type "subscription-usage"
:amount 99
:currency "usd"
:interval "month"
:unit "run"
:included-quantity 1000}}]}}}}
Use a single plan in the catalog for a one-price app. Existing legacy
flow-level examples with :marketplace {:monetization {:pricing ...}} remain
valid for preserving old listings.
Multi-Plan Catalogs
Use a plan catalog when a buyer should choose among multiple pricing options
for the same app, for example:
- monthly vs annual subscription
- starter vs pro tiers
- subscription plus prepaid run-pack options
- a recommended default plan with alternatives
Rules:
- each plan must normalize to a unique stable
plan-id - at most one plan can be marked
defaultorrecommended - existing buyer entitlements store the selected
plan-id, so deleting or renaming active plan ids is risky and should be treated like a migration
Example:
{:slug :paid-flow-catalog
:tags ["catalog"]
:discover {:public true}
:marketplace {:visible true
:app {:app-id "paid-flow-catalog"
:app-name "Paid Flow Catalog"
:app-primary-flow-slug "paid-flow-catalog"
:app-flow-slugs ["paid-flow-catalog"]
:monetization
{:plans [{:plan-id "starter"
:name "Starter"
:default true
:pricing {:type "subscription"
:amount 29
:currency "usd"
:interval "month"}}
{:plan-id "pro-pack"
:name "Pro Pack"
:pricing {:type "usage"
:amount 100
:currency "usd"
:unit "run"
:included-quantity 500}}
{:plan-id "metered"
:name "Metered"
:pricing {:type "subscription-usage"
:amount 49
:currency "usd"
:interval "month"
:unit "run"
:included-quantity 22
:free-quantity 5}}]}}}
...}
If you operate directly against /api/commands, the underlying monetization command is flows.marketplace.monetization.update.
For source-authored paid apps, prefer the app-owned catalog shape above. For
day-to-day creator work, prefer the Publish page so public listing,
monetization, and draft publishing stay in one place.
Publish Checklist
App path:
- Confirm seller payouts are ready on
/<workspace-id>/billing. - Open
/<workspace-id>/flows/<slug>/publish. - Save the public listing and paid-flow settings.
- Publish changes so the current draft becomes the live buyer version.
- Verify from another workspace.
Source/CLI path:
- Author the flow with descriptive metadata tags for the use case, audience,
integration, and modality. Do not treatend-useras an installability
requirement; existing legacy flows may still carry it as ordinary metadata. - For a new paid app, add
:marketplace {:app {... :monetization {:plans [...]}}}for paid behavior.
Keep:marketplace {:monetization ...}only when preserving an existing
legacy listing. - Choose one marketplace visibility path:
- source-first: add
:marketplace {:visible true}in the flow file before push - explicit after push: run
breyta flows marketplace update <slug> --visible=true
- source-first: add
- Choose one discover visibility path:
- source-first: add
:discover {:public true}in the flow file before push - explicit after push: run
breyta flows discover update <slug> --public=true
- source-first: add
- Push the flow:
breyta flows push --file ./tmp/flows/<slug>.clj
- Run the explicit visibility commands if you chose the explicit path.
- Release a live version:
breyta flows release <slug> --release-note-file ./release-note.md
- Verify the buyer surface from another workspace.
Verify The Published Result
From the Publish page, check that:
- seller payouts are ready for paid flows
- availability is public
- pricing and trial settings match the intended buyer offer
- paid checkout is before install
- the live version is up to date
From the CLI, use:
breyta flows show <slug> --pretty
breyta flows discover list
breyta flows discover search <query>
breyta flows readiness <slug> --target live --public --marketplace
Check for:
tagsare descriptive metadata; installability comes from public visibility,
marketplace visibility, and a released live version, not from anend-usertag.marketplace.visibleistruemarketplace.app.monetization.planscontains the intended pricing, paywall,
and optional trial fields for new paid apps. Existing legacy listings may
still reportmarketplace.monetization.discover.publicistrue- the flow has an active released version
- the public app page at
https://breyta.ai/apps/<flow-slug>opens the
intended buyer-facing app surface
Then verify the actual buyer experience from another workspace in the web app:
- the flow appears in
/:workspace-id/discover - the CTA matches one-time vs subscription vs trial behavior
- checkout completes
- the resulting installation state matches the paywall policy
Current Product State
The current publishing flow is real and creator self-serve.
Today:
- seller onboarding starts from the workspace billing page
- paid-flow publishing starts from the flow Publish page
- the Publish page writes listing, pricing, trial, and live publish state
- CLI/source metadata still works for scripted or code-reviewed publishing
- paid publishing is gated by
BREYTA_FLOW_REUSE_APPROVER_USER_IDSduring rollout
Treat the app path as canonical for normal creator use, and the CLI/source path
as an advanced/operator path.