Reseller

Enable reseller mode, define products, and provision client workspaces.

Intermediate
6 min read

Reseller

Reseller mode turns a workspace into a control plane for creating and managing client workspaces. It is the foundation of Gravity Rail's B2B2C model: define products with features, limits, and pricing; provision client workspaces against those products; and keep each client's data isolated in its own PostgreSQL schema.

Who Should Read This

  • Org owners enabling reseller mode for their organization
  • Reseller administrators creating client workspaces and defining products
  • Operations leads provisioning or lifecycle-managing client workspaces

For the architectural deep-dive (data model, API routes, provisioning internals), see the Reseller feature doc.

Prerequisites

Before you begin, you'll need:

  • Organization Owner or Admin role in Gravity Rail
  • A workspace in your organization that will act as the reseller workspace (the one that creates and manages clients)
  • manage_workspace permission on that reseller workspace

Enabling Reseller Mode

Reseller mode is controlled by the is_reseller flag on a workspace. It is set by Gravity Rail during onboarding — contact your account representative to enable it on the workspace you want to use as the reseller.

Once enabled:

  • The workspace can create and manage client workspaces via /reseller/workspaces
  • The workspace can define products via /reseller/products
  • Client workspaces created from it cannot themselves be resellers (no recursive nesting)

To confirm reseller mode is active:

bash

The result should be true.

Defining a Product

A product is a subscription offering with features, limits, and pricing plans. Clients subscribe to products; products determine what their workspaces can do.

Product Types

TypePurposeExample
workspaceFull workspace subscription, optionally cloned from a template"Professional Plan"
memberPer-member subscription within an existing workspace"Premium Member"
orgOrganization-wide subscription across all workspaces"Enterprise SSO"

Creating a Product via API

http

After creation, attach features, limits, inclusions, plans, and overages to the product. See the Reseller feature doc for the full request shape.

Creating a Product via CLI

bash

Product Visibility

  • isPublic: true — visible to non-admins on the public product catalog
  • isFeatured: true — surfaced in a featured section
  • isPopular: true / isRecommended: true — additional merchandising flags
  • selfService: true — users can subscribe without talking to sales

Provisioning a Client Workspace

Client workspaces go through two steps: create (metadata only) and provision (actually create the database schema and run migrations).

Step 1: Create the Client Workspace

http

The new workspace is created with:

  • reseller_id = your reseller workspace ID
  • organization_id = your reseller's organization
  • status = PENDING
  • No database schema yet

slug is optional — if you omit it, Gravity Rail generates one from the name.

Step 2: Provision Infrastructure

http

This:

  1. Creates a PostgreSQL schema named ws_{workspace_uuid}
  2. Runs Alembic migrations to create all workspace tables
  3. Creates default WorkspaceSettings
  4. Transitions status from PENDINGPROVISIONINGAVAILABLE

If provisioning fails, status will be set to ERROR. Check logs, resolve the underlying issue, and retry.

Step 3: Assign a Product (Optional)

Assigning a product to the client workspace enforces the product's features and limits. This step is typically handled automatically by the Stripe subscription webhook, but you can do it manually via the subscription API.

Client Workspace Lifecycle

StatusMeaning
PENDINGCreated, not yet provisioned
PROVISIONINGSchema creation and migrations in progress
AVAILABLEReady for use
ERRORProvisioning failed — safe to retry
DELETEDSoft-deleted; schema and data retained

To list your client workspaces:

bash

To soft-delete:

http

Soft delete sets status to DELETED but leaves the schema in place. Contact Gravity Rail support to hard-delete a client workspace and purge its data.

Security and Data Isolation

  • Workspace isolation — each client workspace lives in its own PostgreSQL schema. Queries only ever see one client's data at a time. See Security Model: Multi-Tenancy for the architectural details.
  • Reseller isolation — a reseller only sees the client workspaces it created (reseller_id matches). One reseller cannot read another reseller's clients.
  • Product visibility — non-admin users see only isPublic: true products. Admins see everything.
  • Provisioning authorization — requires manage_workspace permission plus is_reseller=true on the calling workspace.

Common Tasks

Cloning from a Template Workspace

Set template_workspace_uuid on a workspace product to clone a fully-configured template (tasks, agents, data types, forms) into every new client workspace that subscribes to that product.

Self-Service Signup

Set selfService: true and isPublic: true on a product, and ensure the client workspaces it provisions have allow_signup: true. Users will be able to discover the product on your public catalog and subscribe without sales involvement.

Monitoring Client Usage

Usage analytics for client workspaces are available via the Analytics API. See Analytics & Usage Reports for how to query usage data programmatically.

Troubleshooting

"You must be a reseller to perform this action" (HTTP 403) The calling workspace does not have is_reseller=true. Contact your account representative to enable reseller mode on the right workspace.

Provisioning stuck in PROVISIONING Rare, but indicates the migration step did not complete. Check API logs for the failure, resolve it, then retry the provision call — the endpoint is idempotent for PENDING and ERROR states.

Slug already taken Workspace slugs are globally unique. Pick a different slug or omit it and let Gravity Rail auto-generate one.

Client workspace can't access a feature Check that the product assigned to the workspace includes that feature in its ProductFeature list, and that any relevant resource limits (ProductLimit) haven't been exceeded.