Ecosystems and products
A product is something you build and offer to other people: a website, a native app or a service. In the hub, each product you make gets a place of its own, with its own users, its own sign-in, its own applications, settings, storage, integrations and billing. That place is called an ecosystem. Your workspace has one too, and it is the boundary that keeps your data apart from everyone else's. A product's ecosystem sits under your workspace's.
This all happens under Ecosystems.
Topics
- What an ecosystem is: the boundary around a set of data, with who owns it and where it sits in the tree.
- The Products feature: the list of your products, and the topics each one has.
- Users: the people who use your product and how they sign in, plus the waitlist before launch.
- Applications: where a product registers the clients that will call the hub.
- Feature flags: switches inside a product.
- Server bags: values a product keeps on the server for its applications.
- Sync: how an application keeps an offline copy of its data.
- Integrations: connecting a product to outside services.
- Billing: what you offer, and how Stripe takes the money.
- Gamification and games: badges, levels, and the backend for a game.
- Moving things between ecosystems: the ways something moves from one ecosystem to another.
- Other topics: the product topics covered elsewhere.
What you do with a product on the site, a program can do over the API: list and set up ecosystems and their features, register applications and mint their tokens, sign a product's users in, run a waitlist, read flags and server bags, sync, connect services, bill, and move things between ecosystems.
Ecosystems and products share the ecosystem routes. A product's features are provisioned by the same feature routes a workspace uses.
Applications mint, list and revoke an application's own tokens under the application's routes in ecosystem. Those tokens have no person behind them and reach only the product's ecosystem.
Sign-in for a product's users is the oauth and customer routes. The server behind it is Ory Hydra, serving one customer realm per ecosystem. An application registers a public client, using PKCE with the authorization code and refresh token grants and the scope openid offline_access email. The flow is discovery, start, the callback, and complete. A completed sign-in returns a customer token confined to reading who the user is, the product's feature flags, its server bag, and sync. The "who am I" call answers with the user, the ecosystem and the customer realm. A customer can also sign in by email, verified phone or slug at the customer login route. The settings Authentication writes are the client auth routes in ecosystem.
Email signup is the audience routes. Lists and templates are plain resources, with the workspace given as a query. Everything else is hand-written: a list's members are read and removed, a list has stats, campaigns are listed, created, changed and removed, each has its deliveries, and a campaign can be test-sent, sent, used to invite, and have its key rotated. A campaign that has left draft refuses edits with a conflict. The embedded form posts to the public signup-list routes, and a public route unsubscribes by token.
Feature flags are read by an application at the ecosystem feature-flags route in ecosystem. The hub's own flags are served publicly under system.
The server bag is read with a customer token at the ecosystem server-bag route in ecosystem.
Sync is one pull call and one push call under sync. Which tables sync is enrolled per ecosystem by platform staff through the admin sync routes.
Integrations are the integrations routes: list connections, list providers, get a provider's authorization or install address, make a link token, register an instance, adopt installations, test credentials, connect, disconnect, sync, run an action, change settings, and read or write a provider's configuration per ecosystem. The sign-in callback is on the hub, and the addresses a provider may send a user back to are derived from the registry of sites. Every outbound request goes through an agent that filters server-side request forgery.
Billing is the billing routes: the billing context, accounts, prices and events, plus a redrive of events. A claim and a resend of a claim are routes too. Stripe's webhook is a public route per ecosystem. The hub stores the event first and applies events in the order they were created. A paywall answers with the same payment-required status the usage gate uses.
Gamification and games are the gamification and game routes: a realm's configuration, catalog, badges, levels and event types, and a replay. A game's typed and generic tables are under the game routes, and publishing a game artifact is one-way.
Moving things is an ownership transfer, an ecosystem move, a customer transfer with its preview, and the memberships routes, which add and remove a customer's membership in an ecosystem.
Over MCP, a connected service's actions appear to an agent as integration tools, one per provider and action.
The full list of routes, with each one's parameters, body and responses, is the REST reference on the help site. The tools an agent gets are listed in the MCP reference.
The ecosystem is the one boundary. Every row of data says which ecosystem it belongs to, and the database itself filters on that. That one rule is what lets a product, a persona and a workspace be the same kind of thing.
The hub is the first ecosystem. Developers are customers of the hub exactly as end users are customers of a product. One login store, one customer model, no special case.
Where a thing sits and who owns it are different questions. A product's place in the address tree and its owner are kept apart, so a product lives under its owner's own ecosystem without being owned by it.
The realm is worked out, never declared. A client's realm comes from the ecosystem it was registered with, so no client can claim a tenancy that suits it.
One sign-in engine, two realms. Customer accounts live in the hub's database because the sign-in server has no pages of its own and the hub draws every login page.
Stripe owns the money. The hub stores each webhook event before acting on it and applies events in order. It never holds a balance. That keeps the hub out of payment liability, and an event that arrives out of order cannot corrupt anything.
Only absence keeps a table out of sync. Enrollment can turn on anything the sync catalog lists, so a table that is off by default is not a gate. The chat tables are listed once, and both the plain data routes and sync read that one list.
A game's backend, not its engine. A column is typed when the hub reads and acts on it, and generic when the hub only stores it, so a second game of a different kind fits without a change to the schema.