> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instacloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-tenant & integrations

> Provision apps for your users, out of the box: a master token for your backend, then a project or an app per customer, all over the REST API.

InstaCloud supports multi-tenancy out of the box: to make each of your customers an **app** or a **project** with exactly the right permissions, use the endpoints below. The [API](/reference/api/overview) is directly available on any account; when you put a real fleet on it, [contact us](#enterprise-plans) for an Enterprise plan with custom restrictions.

## 1. Provision the master token

Your backend keeps one **master token**: an organization-scoped API token, minted once (`insta tokens create master --org <orgId>`). It acts as your backend's master key: it is the credential that creates projects and [mints narrower tokens](/reference/api/overview#minting-a-token), never wider than itself, and it never leaves your backend.

From there, give each customer the isolation boundary that matches how much they touch. In doubt, take a project per customer.

## 2. A project per customer

Every customer, whether that is a user of your builder or a tenant of your SaaS, gets a separate project, for token isolation. This is the shape to pick when customers freely create apps and use resources, or when each customer's app carries its own database: mint a **project-level token** per customer, and everything that runs for them runs under it, inside their own project.

```bash theme={null}
API=https://api.instacloud.com

# 1. A project for the new customer. Master token only.
PROJECT=$(curl -s -X POST $API/orgs/$ORG/projects \
  -H "Authorization: Bearer $MASTER" -H "Content-Type: application/json" \
  -d '{"name":"acme"}' | jq -r .project.id)

# 2. A token bound to that project alone. The plaintext is returned once;
#    store it with the customer record.
TOKEN=$(curl -s -X POST $API/tokens \
  -H "Authorization: Bearer $MASTER" -H "Content-Type: application/json" \
  -d "{\"name\":\"acme\",\"orgId\":\"$ORG\",\"projectId\":\"$PROJECT\"}" | jq -r .token)

# 3. Everything for this customer now runs under $TOKEN.
curl -s -X POST $API/projects/$PROJECT/services -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{"type":"postgres","name":"db"}'
curl -s -X POST $API/projects/$PROJECT/services -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{"type":"compute","name":"app","port":3000}'

# 4. Wire the database in, then deploy.
curl -s -X PUT $API/projects/$PROJECT/secret-bindings/DATABASE_URL \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"target":"compute/app","source":"postgres/db"}'
curl -s -X POST $API/projects/$PROJECT/deploy -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"image":"ghcr.io/you/tenant-app:1.0.0","group":"app","port":3000}'
```

The responses are plain JSON. Creating the project answers with the project row and its default branch; minting the token answers once with the plaintext:

```json title="POST /orgs/{orgId}/projects (201)" theme={null}
{"project":{"id":"36b7fe0a-87a1-4db4-8fc5-9b2188962afe","org_id":"86e77ca0-...","name":"acme","status":"active","agent_policy":{"mode":"full_access"},"created_at":"2026-09-29T03:28:24.245Z"},"defaultBranch":{"id":"0ba7ab98-...","name":"main"},"resources":[]}
```

```json title="POST /tokens (201)" theme={null}
{"token":"insta_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","record":{"id":"nbvAiBn5...","name":"acme","scope":"project","orgId":"86e77ca0-...","projectId":"36b7fe0a-...","access":"full","expiresAt":null,"createdAt":"2026-09-29T03:28:24.873Z"}}
```

The project token is the isolation boundary, so hand it to the customer's runtime without worry:

* It reaches its own project only. Any endpoint outside the binding answers `403 token_scope`, and it cannot mint tokens at all.
* A second token with `"access":"read_only"` serves customer-facing dashboards: it is accepted on `GET` and `HEAD` only.
* Each customer gets their own branches for previews and agent runs ([branch per task](/agents/branch-per-task)).
* `GET /projects/{projectId}/usage` is that customer's bill; `/usage/daily` gives the day-by-day series.
* Offboarding is two calls with the master token: `DELETE /projects/{projectId}` and `DELETE /tokens/{tokenId}`.

Idle customers stay cheap: a project's [Postgres suspends by default](/postgres/overview) and bills only for storage, and its compute can [scale to zero](/compute/overview) the same way.

## 3. An app per customer

If all a customer interacts with is a single unit of resources, one app, say one generated app per user without a database of its own, you can skip the per-customer project: keep one shared project and make every customer a **compute service** of their own.

```bash theme={null}
# Per customer: one app in the shared project, wired to the shared database, deployed.
curl -s -X POST $API/projects/$PROJECT/services -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{"type":"compute","name":"acme","port":3000}'
curl -s -X PUT $API/projects/$PROJECT/secret-bindings/DATABASE_URL \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"target":"compute/acme","source":"postgres/db"}'
curl -s -X POST $API/projects/$PROJECT/deploy -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"image":"ghcr.io/you/tenant-app:1.0.0","group":"acme","port":3000}'
```

* Each app deploys, scales, restarts and stops on its own, without touching the rest of the fleet.
* Logs and metrics still read per app: `GET /projects/{projectId}/logs?group=<app>`, and the same `group` filter on `/metrics`.
* A database per customer inside the shared Postgres keeps separation clean: `POST /projects/{projectId}/database/databases`.
* Usage is reported for the whole project, so per-customer billing needs your own accounting on top, and a growing fleet hits the plan's per-branch service caps first. When a customer outgrows the shared project, promote them to a project of their own.

Either way, the organization's audit stream (`GET /orgs/{orgId}/events/stream`) gives you one timeline of everything every customer's infrastructure did.

## Enterprise plans

Standard plans cap how many services of each type a branch can hold, sized for one team rather than a fleet of tenants, so an app per customer hits the compute cap first and a project per customer eventually meets its own ceilings. For production multi-tenant use, contact us to be upgraded to an **Enterprise plan with custom restrictions**: limits sized to your tenant count, and guardrails where you want them, per project. Tell us what you are building and roughly how many tenants you expect:

* Email [founders@insforge.dev](mailto:founders@insforge.dev), or
* use the [contact form](https://www.instacloud.com/contact).

We answer within one business day.

## The API design

The full API design is published, split by which token scope can call each endpoint:

* [API overview](/reference/api/overview): authentication, token scopes, errors, and the end-to-end provisioning flow.
* [Account](/reference/api/account), [organization](/reference/api/org) and [project](/reference/api/project) endpoint pages, generated from the platform's own OpenAPI document.
* `GET https://api.instacloud.com/openapi.json`: the machine-readable spec, if you would rather generate a client.
