Management API
Everything the CLI and portal UI do goes through the portal's own HTTP API — there is no private back channel. Anything you can click, you can script.
This page is for your own tooling. If the caller is an AI client, use the MCP endpoint instead: it's these same operations exposed as MCP tools — with argument schemas, a project-scoped token you can rotate, and the docs served alongside them — rather than endpoints a model has to guess its way around.
This is the control plane, and it's a different axis from the project API your app talks to. /rest/v1 and friends read and write the data inside a project; the management API creates and configures the projects themselves. Keep the two straight and the security model falls out naturally: app code holds an anon key and can never provision infrastructure, while a management token can provision anything and therefore never belongs in an app.
Reach for it whenever a human clicking the portal is the bottleneck — when project setup has to be reproducible, or when the thing that needs to act isn't a person.
- Provision a project per customer
- A B2B product that gives every tenant an isolated database: create the project, apply migrations, and read back the keys, all from your signup flow, instead of clicking through the portal for each new account.
- Ephemeral environments in CI
- Spin up a throwaway project for a pull request, run the test suite against real Postgres and real RLS policies rather than mocks, and delete it when the branch merges.
- Infrastructure as code
- Keep flags, secrets, scheduled functions, and DNS records in a script under version control, so a rebuilt project is identical to the one it replaced.
- Internal admin tooling
- Build your own support console — look up a user, ban an account, re-run a schedule — without giving support staff portal logins.
Authenticating
Exchange your admin email and password for a bearer token at /api/auth/cli-token — the same token the CLI stores in ~/.shovelbase/config.json. Treat it like a root credential: it can read every key and delete every project in the organization.
TOKEN=$(curl -s -X POST https://shovelbase.com/api/auth/cli-token \ -H 'Content-Type: application/json' \ -d '{"email": "admin@…", "password": "…"}' | jq -r .token) curl -s https://shovelbase.com/api/projects -H "Authorization: Bearer $TOKEN"A worked example — provision a project, wait for it, apply a schema, and print the keys an app would need:
set -euo pipefailAPI=https://shovelbase.com/apiAUTH="Authorization: Bearer $TOKEN" # 1. Create the project — the response is the project row, incl. its keys.REF=$(curl -s -X POST "$API/projects" \ -H "$AUTH" -H 'Content-Type: application/json' \ -d '{"name": "tenant-acme"}' | jq -r .slug) # 2. Wait for the service containers to come up (the endpoint returns an# array, one entry per service, each with a "healthy" boolean).until curl -sf "$API/projects/$REF/services" -H "$AUTH" \ | jq -e 'length > 0 and all(.healthy)' >/dev/nulldo sleep 3; done # 3. Apply the schema. "version" is the ordering key migrations are recorded# under — the CLI uses a timestamp, so anything sortable works.curl -s -X POST "$API/projects/$REF/migrations" \ -H "$AUTH" -H 'Content-Type: application/json' \ -d '{"version": "20260720120000", "name": "init", "sql": "create table public.todos (id bigint generated always as identity primary key);"}' # 4. Hand the app its credentials. There is no "url" field — a project is# always served at https://<slug>.shovelbase.com.ANON=$(curl -s "$API/projects/$REF" -H "$AUTH" | jq -r .anon_key)echo "SHOVELBASE_URL=https://$REF.shovelbase.com"echo "SHOVELBASE_ANON_KEY=$ANON"Projects & schema
| Endpoint | Methods | Purpose |
|---|---|---|
/api/projects | GET, POST | List / create projects |
/api/projects/<ref> | GET, DELETE | Project detail (incl. keys) / delete |
/api/projects/<ref>/migrations | GET, POST | Applied migrations / apply one |
/api/projects/<ref>/sql | POST | Run arbitrary SQL as the project owner |
/api/projects/<ref>/tables | GET | Schema catalog — tables, columns, definitions |
/api/projects/<ref>/tables/export | GET | Download a table as CSV |
/api/projects/<ref>/tables/import | POST | Import CSV rows (multipart) |
/api/projects/<ref>/backups | GET, POST | List backups + current job / back up now |
/api/projects/<ref>/backups/restore | POST | Restore from a given backup |
Functions, schedules & secrets
| Endpoint | Methods | Purpose |
|---|---|---|
/api/projects/<ref>/functions | GET, POST | List / deploy edge functions |
/api/projects/<ref>/functions/<name> | GET, PUT, DELETE | Read source / redeploy (merges files, preserves verify_jwt + MCP flags) / delete |
/api/projects/<ref>/schedules | GET, POST, PATCH, DELETE | Cron schedules for functions — list / create / update / delete |
/api/projects/<ref>/schedules/run | POST | Run a schedule immediately |
/api/projects/<ref>/secrets | GET, POST, DELETE | Function secrets (applied live) |
Auth
| Endpoint | Methods | Purpose |
|---|---|---|
/api/projects/<ref>/auth/users | GET, PATCH, DELETE | List users / ban-unban / delete — note there is no POST; users are invited, not created |
/api/projects/<ref>/auth/users/send | POST | Send an auth email: { type: "invite" | "recovery" | "confirmation", email } — "invite" creates the user |
/api/projects/<ref>/auth/config | GET, PUT | Site URL + additional redirect URLs |
/api/projects/<ref>/auth/providers | POST, DELETE | Enable / disable Google and Apple sign-in |
/api/projects/<ref>/auth/providers/apple-secret | POST | Sign an Apple client secret from the stored .p8 — returns it, saves nothing |
/api/projects/<ref>/auth/emails | GET, PUT | Email template subjects and HTML bodies |
/api/projects/<ref>/auth/confirm-config | GET, PUT | Require-confirmation toggle |
/api/projects/<ref>/auth/reset-page | GET, PUT | Hosted reset page HTML (and confirm-page for the confirmation equivalent) |
Storage, queues & flags
| Endpoint | Methods | Purpose |
|---|---|---|
/api/projects/<ref>/storage | GET, POST, DELETE | Browse / upload / delete objects |
/api/projects/<ref>/storage/buckets | GET, POST, PATCH, DELETE | List / create / toggle public-private / delete buckets |
/api/projects/<ref>/storage/sign | GET | Mint a signed URL for a private object |
/api/projects/<ref>/queues | GET, POST, DELETE | List (with message counts) / create / delete SQS queues |
/api/projects/<ref>/queues/<name>/messages | POST | Enqueue a message |
/api/projects/<ref>/queues/triggers | GET, POST, PATCH, DELETE | Queue triggers — list / create / update (functions, enabled) / delete |
/api/projects/<ref>/queues/webhooks | GET, POST, DELETE | Queue webhooks (public inbound URL → queue) — list / create / delete |
/api/projects/<ref>/flags | GET, POST, PATCH, DELETE | List / create / toggle / set rollout percentage / delete feature flags |
Web & domains
| Endpoint | Methods | Purpose |
|---|---|---|
/api/projects/<ref>/sites | GET | List published static sites |
/api/projects/<ref>/sites/<site> | GET, POST, DELETE | Site manifest (paths + ETags) / upload a file / prune paths or delete the site |
/api/projects/<ref>/sites/<site>/invalidate | POST | Invalidate attached CloudFront distributions after a publish |
/api/projects/<ref>/domains | GET, POST, DELETE | List / connect / disconnect a domain |
/api/projects/<ref>/domains/<domain>/records | GET, POST, DELETE | List / add / delete DNS records |
/api/projects/<ref>/distributions | GET, POST, DELETE | Attach / detach a custom domain to a site or the project API |
Monitoring
| Endpoint | Methods | Purpose |
|---|---|---|
/api/projects/<ref>/services | GET, POST | Service health / restart containers |
/api/projects/<ref>/services/logs?service=… | GET | Service logs (rest, auth, storage, functions, queues, sites, postgres) |
/api/projects/<ref>/observability[?section=…] | GET | Resources overview, or per-product detail (database, auth, storage, functions, queues, sites) |
/api/projects/<ref>/signals?range=… | GET | Signals overview aggregates |
/api/projects/<ref>/signals/events | GET | Raw event feed, newest first, paginated |
/api/projects/<ref>/signals/users | GET | User profiles derived from events |
/api/projects/<ref>/signals/query | POST | Run a chart config and get its data (no need to save the chart first) |
/api/projects/<ref>/signals/meta | GET | Event names / property keys / top property values in a range |
/api/projects/<ref>/signals/charts | GET, POST | Saved charts (PATCH, DELETE on /charts/<id>) |
Sources & organization
Sources mirror the project endpoints for the surfaces they have — database, functions, schedules, secrets, logs — under /api/sources/<slug> instead of /api/projects/<ref>.
| Endpoint | Methods | Purpose |
|---|---|---|
/api/sources | GET, POST | List / create sources (blank — name only) |
/api/sources/<slug> | GET, DELETE | Source detail / delete |
/api/sources/<slug>/functions | GET, POST | List / deploy source functions (GET, PUT, DELETE on /functions/<name>) |
/api/sources/<slug>/schedules | GET, POST, PATCH, DELETE | Source schedules (POST /schedules/run to fire one now) |
/api/sources/<slug>/secrets | GET, POST, DELETE | Source function secrets |
/api/sources/<slug>/sql | POST | Run SQL against the source database |
/api/sources/<slug>/tables | GET | Source schema catalog (+ /export, /import) |
/api/sources/<slug>/services | GET, POST | Source service health / restart (+ /services/logs) |
/api/org | GET, PATCH | Organization detail / rename |
/api/org/members | GET, POST, DELETE | Admin accounts — list / invite / remove |
Responses are JSON; failures carry a non-2xx status and an { "error": "…" } body. See the CLI reference for the commands that wrap the most common of these calls.