Skip to content
AbloAblo Docs
Esc
navigateopen⌘Jpreview
On this page

Projects

One organization, many apps — each with its own schema, data planes, and keys.

A project is the isolation unit inside your organization — the shape you know from Neon or Supabase. Each app you build gets its own project, and each project gets its own root and child branches, schemas, data planes, and API keys. Two teams in one org can ship two apps that never see each other’s models, keys, or rows.

organization
├── project: default          ← every org has one; pre-project apps live here
│   ├── production root
│   ├── development/preview branches
│   └── branch-bound schema, data plane, and credentials
└── project: my-app           ← npx ablo init creates this for a new app
    ├── production root
    ├── development/preview branches
    └── branch-bound schema, data plane, and credentials

The default project

Every organization has a default project. If you never create another one, everything works exactly as if projects didn’t exist — your keys, schema pushes, and registered databases all belong to it. Keys minted before projects existed are default-project keys automatically.

Keys belong to exactly one project

A key’s project is fixed at mint and can never be changed or overridden — the same discipline as its immutable branch binding. Everything a runtime key mints inherits its project: the short-lived session credentials (ek_), agent keys (rk_), everything. There is no way to “switch projects” with an existing key; you use a key minted for the project you mean.

Schema pushes, database registrations, reads, and writes all act on the key’s project:

  • npx ablo push activates the schema for the pushing key’s project — it can never demote another project’s schema.
  • Registering a database (DATABASE_URL) attaches it to the key’s project and immutable branch.
  • A write or read against a model that belongs to another project in your org fails with a typed project_scope_denied — never a silent empty result, and never the misleading “unknown model, run ablo push”.

Branches belong to a project

Production is the protected root branch; development and preview branches are children. Each branch has its own rows, active schema artifact, claims, log, credentials, and optional registered database. A child copies the parent’s active schema when created and owns its history afterward, so a feature-branch push cannot change a sibling or production.

ablo dev derives a child from Git and mints an expiring sk_ credential bound to its immutable branch id. Production runtimes use sk_ bound to the root. There is no shared sandbox schema and no runtime environment switch.

CLI

npx ablo init creates a project for your app automatically (slug derived from your package.json name; --project <slug> to choose, --no-project to stay on the org default). Manage projects any time:

npx ablo projects list             # all projects (default first)
npx ablo projects create my-app    # create one (--name "Display Name")
npx ablo projects use my-app       # set the ACTIVE project locally
npx ablo projects use default      # back to the org default
npx ablo status                    # shows the active project

The active project is a local targeting preference in your CLI config: new management and branch credentials you mint pick it up. It never changes what an existing key can reach — project and branch scope are decided server-side at mint. Use npx ablo whoami to confirm the exact target of the active credential.

API

Projects are a control-plane resource authenticated with a management (mk_) key:

curl https://api.abloatai.com/api/v1/projects \
  -H "Authorization: Bearer $ABLO_API_KEY"            # list

curl https://api.abloatai.com/api/v1/projects \
  -H "Authorization: Bearer $ABLO_API_KEY" \
  -H "content-type: application/json" \
  -d '{"slug": "my-app", "name": "My App"}'           # create

A create with a taken slug fails with project_slug_taken (409). Reads of another org’s project ids 404 — never confirm existence across orgs.

Errors

Code Status Meaning
project_scope_denied 403 The model/resource belongs to another project in your org: use a key minted for that project.
project_slug_taken 409 A project with this slug already exists in the organization.

Was this page helpful?