Concepts
The Lessly platform model
Learn the model the rest of this documentation assumes: organization, product, member, role, permission, integration, API key and session, driven through four equivalent interfaces.
Lessly is a platform for teams building their own products. You build your product; Lessly holds the surrounding structure — the parts every product needs but nobody wants to build again:
- accounts and sign-in;
- an organization to bill and govern;
- per-product isolation;
- roles and permissions;
- connections to external services;
- deploys.
The same operations are available from a web app, a command line, an MCP server, and a REST API. Whatever you can do in the interface, you can script, and an AI agent can do it too, under the same permission checks.
The eight terms below are the ones the rest of this documentation assumes. Each is defined once here; the section pages carry the depth.
Organization
The customer entity. An organization owns the subscription and the invoice, holds the members, and contains the products.
- Membership. A user account can be a member of several organizations.
- Address. The organization has no slug and never appears in a URL — it is resolved from the session. Organization pages sit at
/organizationin the Product App. - Limit. An organization role by itself grants nothing inside a product. Access to a product is always a concrete grant on that product.
For depth: manage an organization.
Product
One deployable thing inside an organization — a SaaS app, a game, a store. A product has its own database, cache, and deploys.
- Name. Non-empty, at most 100 characters, case-insensitively unique among your own products.
- Slug. Derived from the name in kebab-case (
My Product→my-product) and recalculated when the product is renamed. Slugs are unique across the whole platform: a taken slug gets a short random suffix (my-product-a3f1b2). Some slugs are reserved for platform routes —api,admin,settings,login,signup,billing,docs,account,organizationamong them — and a name that produces one is rejected with a conflict error. The slug is the{product}segment in every product URL. - Region. Every product is created in the
euregion. The region cannot be chosen or changed today.
Products are isolated. There is no implicit path from one product to another, even within the same organization.
For depth: create and rename a product.
Member
A person in an organization. Membership is held at the organization level and carries one of three roles: owner, admin, or member. A membership is invited until it is accepted, then active, and it can carry an expiry date after which it lapses.
Membership in the organization is not by itself access to a product. Access to an individual product is always a concrete grant on that product, and it comes from one of two places:
- Organization role. Owners and admins get a grant on every product in the organization, created when the product is created.
- Explicit share. An organization member gets a product only when someone shares it with them. Without a share, they cannot see it. The default is deny.
For depth: invite a member and share a product.
Role
What a member is allowed to do on a product. Each product grant carries exactly one role, and roles are not stacked — to combine two sets of rights, define a role that carries both.
Four roles exist in every product:
| Role | What it allows |
|---|---|
| Owner | Everything. |
| Admin | Everything except billing operations and deleting the product. |
| Member | Read and everyday write operations; cannot manage roles or assign them. |
| Viewer | Read-only; cannot manage roles or assign them. |
Member and Viewer are defined by the kind of operation, not by a list of features, so they behave consistently as new capabilities appear. An organization can also define its own named roles once and assign them repeatedly; assigning one applies its rights on the target product.
Who may assign what:
- Owner. Any role except ownership itself, which no operation reassigns.
- Admin. Admin, member, or viewer.
- Nobody. No member can demote themselves.
For depth: assign and compose roles.
Permission
The unit a role is built from. Every guarded operation has a stable key of the form {area}_{entity}_{action} — for example, organization_product_create. One vocabulary covers every surface, so the same key describes the operation whether it is reached from the Product App, the CLI, the MCP server, or the REST API.
A role carries two lists of patterns, allow and deny, matched segment by segment over the underscore-separated key:
- The operation must match something in
allow, and must not match anything indeny. - No match in
allowmeans denied — default-deny, withdenyoverridingallow. - A browsable catalog of the grantable permission keys is available, so roles can be composed without memorizing key names.
For depth: read the permission keys and the allow/deny rules.
Integration
An external service connected to the platform. connector is the name used in URLs and API routes. Available today: GitHub, ClickUp, Google Drive, Cloudflare, and Google Ads.
- Owner. The organization owns the connection and attaches it to products many-to-many, so a single connection can serve several products. A product sees only what is attached to it, and an integration with no attachments is dormant.
- Limit. Uniqueness is per organization: the same external account cannot be connected twice in one organization for the same provider.
- Scope. Each attachment records its origin — the product connected the service itself, or an organization admin granted it. Where the provider supports it, the attachment is narrowed to a segment, such as one Google Ads customer or one Drive folder. GitHub and ClickUp grants cover the whole external organization.
- Asking. A product that is not attached can file an access request; any member of the product may ask, and an organization owner or admin approves or denies it.
- Detaching. Organization owners and admins manage attachments; a product member can detach their own product.
For depth: connect an external service and request access to one.
API key
A long-lived credential for programmatic access, scoped to a single product. Keys start with lsk_dev_.
- Created, listed, and revoked on the product’s developer page in the Product App.
- The key value is shown once, at creation, and is not stored anywhere you can read it again. Losing it means creating a new one.
- Each key has a name, records who created it and when it was last used successfully, and can be revoked at any time.
- The key is pinned to the product it was created for. A request that presents it against a different product is rejected.
Use an API key where no human is present to sign in — automated jobs, scripts, and MCP clients configured with a static bearer header.
For depth: create and revoke an API key.
Session
One sign-in on one device. A session records the device, its name, and the IP the sign-in came from, and it is what the Product App and the CLI rely on to keep you signed in.
Sessions expire two ways at once, and are capped in number:
- Inactivity. A session lapses 30 days after its last activity. Using it pushes that deadline out again, so an actively used session stays valid.
- Absolute age. A session ends 90 days after it was created regardless of activity. There is no way to extend past this; sign in again.
- Count. A user can hold at most 10 active sessions. Creating an eleventh revokes the oldest.
- Revocation. Signing out revokes the session immediately. Revoked sessions are kept as a record rather than deleted.
- Boundary. Sessions are separate from API keys and from tokens issued to MCP clients: revoking a session does not revoke those, and they do not extend a session.
For depth: review and revoke your sessions.
The four surfaces
The platform is driven through four interfaces. They are equivalent in what they can reach — each is a different rendering of the same set of operations, and the same permission checks run behind all of them.
| Surface | Address | Use it when | Credential |
|---|---|---|---|
| Product App | app.lessly.com | A person is working by hand. Product pages sit under /{product}/; organization and account pages at /organization and /account. | Browser session |
lessly CLI | npm package @lessly/cli | You are scripting, or working from a terminal. lessly auth login for a person, lessly auth login --token for a script with no human present. | Session or product-scoped token |
| MCP server | mcp.lessly.com | An AI agent acts for you. The agent sees exactly the operations the signed-in identity may perform on the active product. | OAuth, or a static API key |
| REST API | api.lessly.com | You are calling from your own service. Routes are versioned; breaking changes arrive under a new version prefix. | Bearer token |
Next steps
- Create a product and read its slug rules: what a rename does to your URLs.
- Share a product with a member: who gets a grant, and how.
- Compose a role from permission keys: the catalog and the allow/deny evaluation.
- Issue an API key: create, list and revoke a product-scoped credential.
- Connect an external service: what an organization owns and what a product sees.