Skip to Content
Bool API (HTTP)

Bool’s HTTP API

Everything the bool CLI and the MCP server do, they do over the same HTTP API you can call yourself — with curl, a script, or a CI job. Use it to list your projects, fetch a project’s connection config and generated types, publish a new version, and read your app’s data key.

  • Base URL: https://bool.com
  • Auth: Authorization: Bearer <personal access token>
  • Format: JSON in, JSON out (one endpoint returns TypeScript as plain text)

Two different keys show up in Bool, and they’re not interchangeable. A personal access token (bool_live_…) is you, and it talks to this API — the platform. A project data key (boolsk_…) belongs to one app, and it talks to that app’s data over REST — see Your app’s data API at the end of this page.

Get a token

Create a personal access token at Settings → API tokensNew token. The value is shown once — copy it then, because Bool only stores a hash of it and can’t show it again. Treat it like a password.

Two things to know about a token:

  • It carries your permissions. It can’t do anything to a project you couldn’t do yourself in the editor.
  • It’s bound to a single workspace, and only ever acts there. Requests that would touch another workspace’s project fail as if the project didn’t exist. Need to script against two workspaces? Mint one token per workspace.

Tokens can be given an expiry, and can be revoked at any time from the same settings page — a revoked token stops working immediately.

Every request sends it as a bearer token:

export BOOL_TOKEN=bool_live_... curl -H "Authorization: Bearer $BOOL_TOKEN" \ https://bool.com/api/projects

The CLI reads the same value from BOOL_TOKEN (or --token), so a shell that’s set up for bool is already set up for curl.

Endpoints

List your projects

GET /api/projects

Returns an array of the projects in the token’s workspace, newest-updated first. Each item is the full project record — its id (what every other endpoint takes), name, slug, runtimeVersion, visibility, and timestamps.

curl -H "Authorization: Bearer $BOOL_TOKEN" \ https://bool.com/api/projects

Get one project

GET /api/projects/{id}

The project record plus a files array — every file in the project, sorted by path. Any level of access to the project is enough.

Create a project

POST /api/projects

Body: { "name": "...", "description": "...", "template": "..." } — all optional. Responds 201 with the new project record.

curl -X POST https://bool.com/api/projects \ -H "Authorization: Bearer $BOOL_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"my-todos"}'

Creating a project this way places it in your active workspace (the one selected in the web app), not the token’s bound workspace. If which workspace it lands in matters, create it with bool create, the MCP drop_project tool, or the web app instead.

Get a project’s connection config

GET /api/projects/{id}/connection

Everything a bool-sdk client outside Bool needs to point at the project:

{ "projectId": "…", "name": "My Todos", "slug": "my-todos", "schema": "app_…", "appOrigin": "https://bool.so", "appUrl": "https://my-todos.bool.so", "gatewayUrl": "https://bool.so/served/my-todos/_bool/v1", "supabaseUrl": "…", "supabaseAnonKey": "…" }

These are all public values — no secret is in this response, so it’s safe to commit (bool link writes it to bool.config.json). Any level of project access can read it.

A project created before Bool’s gateway runtime existed can’t be used as a backend from outside, and returns 409 with {"error":"not_gateway_project"}. Either start a new project, or have Bool make an upgraded copy of the old one and point at that; see Before you start on the CLI page.

Get generated TypeScript types

GET /api/projects/{id}/entities/types

Returns the project’s entity types as a single .d.ts file — plain text, not JSON. This is what bool types fetches. Re-fetch it after your data model changes.

curl -H "Authorization: Bearer $BOOL_TOKEN" \ https://bool.com/api/projects/$ID/entities/types > bool/types.d.ts

Reveal or rotate the app’s data key

GET /api/projects/{id}/api-key # reveal (creates it on first read) POST /api/projects/{id}/api-key # rotate

Both return { "apiKey": "boolsk_…" }. This is the project’s admin data key: it reads and writes every row in the app, so it’s owner-only — a collaborator’s token gets a 404. Rotating kills the previous key immediately.

curl -H "Authorization: Bearer $BOOL_TOKEN" \ https://bool.com/api/projects/$ID/api-key

Keep it out of client-side code and out of git. bool link writes it to .env.bool and gitignores that file for you.

Publish a new version

POST /api/drops

Body: { "project_id": "<id>" } (required — this endpoint deploys a new version of an existing project). It takes publish rights on the target, and the new version keeps the project’s current workspace and visibility.

The response is an upload slot:

{ "drop_id": "…", "upload_url": "https://…", "upload_method": "PUT", "upload_headers": { "…": "…" }, "status_url": "https://…", "expires_at": "2026-07-24T12:00:00.000Z", "max_upload_size_bytes": 10485760 }

Publishing is three steps:

  1. POST /api/drops to get the slot above.
  2. Upload a ZIP of your app’s source (not a build) to upload_url using upload_method and upload_headers.
  3. Poll status_url until the status settles.
# 1. Ask for an upload slot curl -X POST https://bool.com/api/drops \ -H "Authorization: Bearer $BOOL_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"project_id\":\"$ID\"}" # 2. Upload the source archive curl -X PUT --upload-file app.zip "$UPLOAD_URL" # 3. Poll for the result curl "$STATUS_URL"

status_url is pre-signed and scoped to that one drop, so polling it needs no token. It returns:

{ "drop_id": "…", "status": "building", "project_id": "…", "deployment_id": null, "url": null, "error": null }

status moves through awaiting_uploaduploadedvalidatingqueuedbuildingpublishingready, and can end at failed, expired, or canceled. On ready, url is the live app. On failed, error explains why.

Poll every couple of seconds, not in a hot loop — the status endpoint rate-limits and answers 429 with a Retry-After header if you push it. Bool also caps how much you can publish in a window; over the cap, the POST /api/drops call itself returns 429.

If all you want is “deploy this folder,” bool deploy does these three steps for you, including zipping the right files.

Errors

Errors come back as { "error": "..." } with a conventional status code:

StatusWhat it means
401No token, or the token is invalid, expired, or revoked.
404The project doesn’t exist, isn’t in the token’s workspace, or you don’t have the access this endpoint needs. Owner-only endpoints return 404, not 403, so a token can’t be used to probe for projects.
409The project can’t do this — e.g. an older-runtime project asked for its connection config.
429Too many requests, or a publish quota is exhausted. Honor Retry-After when it’s present.
503A capability isn’t configured on this deployment (e.g. data keys are unavailable).

Because a missing permission looks the same as a missing project, treat 404 as “not available to this token” rather than “deleted.”

Your app’s data API

The endpoints above manage projects. Reading and writing the data inside a published app is a separate surface with its own key: your project’s boolsk_ data key, sent as an api_key header to the app’s own origin.

curl -H "api_key: boolsk_..." \ "https://my-todos.bool.so/_bool/v1/db/rest/v1/todos?select=*"

Open your project’s Dashboard → API for the exact URLs, the field list for every model, and copy-paste snippets — that tab is generated from your app’s actual data models, so it’s always current. In app code, prefer the SDK (bool.entities.todos.list()) over raw REST — the SDK reference covers the whole surface.

Last updated on