Automate with the HTTP API
Anything that can send HTTP can build on Appbricx: your own scripts, internal tools, a deploy pipeline, or an agent framework without MCP. You can create projects, check and apply contracts, test the app as each user, take screenshots, read data, deploy, and operate the running app (SQL, rows, schema, snapshots, rollbacks, workflow runs, logs, secrets). JSON in, JSON out.
When you would use it
- You are wiring Appbricx into your own tooling, for example an agency dashboard that spins up a project per client.
- Your language or platform has no MCP client and you would rather not shell out to the CLI.
It does the same things as the MCP server and the CLI, with the same answers. If you just want to try it, the curl examples below are the quickest start.
Base URL and auth
https://appbricx.com/api/dev/v1
Authorization: Bearer apx_pat_...- Use an access token. Tokens work on
/dev/v1and/mcponly; they are never accepted by the rest of the Appbricx API (billing, admin, workspace settings). - The web app's signed-in session also works here, with every scope across all of the user's workspaces.
- Send
content-type: application/jsonon requests with a body.
Endpoints
"read" endpoints work with any valid token. Writing endpoints also need a non-viewer role in the project's workspace.
| Method | Path | Scope | What it does |
|---|---|---|---|
| GET | /me | read | User, auth kind, scopes, workspaces |
| GET | /docs | read | The contract guide (text/markdown) |
| POST | /tokens | session only | Mint a token. A token can't mint another token (403 SESSION_REQUIRED) |
| GET | /tokens | read | Your active tokens (prefix, scopes, expiry, last used) |
| DELETE | /tokens/:id | read | Revoke one of your tokens |
| GET | /projects | read | Projects in reach, newest first (max 200) |
| POST | /projects | apply | Create a project: { name, description?, workspaceId? } |
| GET | /projects/:id | read | Build state and preview path |
| GET | /projects/:id/contract | read | { contract, built } |
| POST | /projects/:id/check | read | { contract } → { report }; no changes |
| POST | /projects/:id/apply | apply | { contract, force? } → build dev |
| POST | /projects/:id/patch | apply | { edits, dryRun?, force? } → typed edit ops |
| POST | /projects/:id/verify | read | { report }: static, data, browser |
| POST | /projects/:id/screenshot | read | { route?, as?, width?, height?, fullPage? } → PNG (base64 in JSON, or raw with ?format=png) |
| POST | /projects/:id/data/query | read | { table, where?, orderBy?, desc?, limit? } → dev rows (read-only, max 200) |
| GET | /projects/:id/logs | read | ?limit=&workflow= → workflow runs and notifications |
| POST | /projects/:id/deploy | deploy | { environment?, allowDestructive?, skipVerify?, subdomain? } → publish to https://<subdomain>.apps.appbricx.com, verify-gated |
| GET / POST | /projects/:id/sign-in | read / apply | { provider, enabled, client?, clientId?, clientSecret? } → social sign-in. { "provider": "google", "enabled": true }uses Appbricx's Google client, no setup |
| POST | /components/check | read | { name, source, sample? } → run one component through every gate |
Operate the running app
env is dev (the preview, the default) or prod (the published app). Every prod write takes a database snapshot first and returns its snapshotId; if the snapshot fails, nothing is written. Every write is recorded in the project's admin audit trail.
| Method | Path | Scope | What it does |
|---|---|---|---|
| GET | /projects/:id/schema | read | ?env=→ tables (columns, keys, indexes, constraints, triggers, policies), views, functions, enums; each table's origin: contract, platform, internal or hand-made |
| POST | /projects/:id/sql | read / apply / deploy | { sql, env? } → rows (max 1000), rowCount, statements, durationMs, snapshotId on prod writes. Read-only SQL needs read; writes need apply (dev) or deploy (prod) |
| POST | /projects/:id/rows | apply / deploy | { table, env?, op, rows?, id?, ids?, patch?, as? } → one result per row, through the app's rules, RLS and change events. as: "admin" (default) or { role, user_id? } |
| GET / POST | /projects/:id/snapshots | read / apply | ?env= → snapshots; POST { env? } takes one (default prod) |
| POST | /projects/:id/snapshots/:snapshotId/restore | deploy | Replace the database with the snapshot (the current state is snapshotted first: undoSnapshotId) |
| GET | /projects/:id/deploys | read | ?environment=&limit= → deploy history |
| POST | /projects/:id/deploys/:deploymentId/rollback | deploy | Switch what's live back to an earlier deployment (files only) |
| POST | /projects/:id/workflows/:workflowId/run | apply / deploy | { input?, env?, as? } → runId, plus status and result when it finishes within 30s (202 otherwise) |
| GET | /projects/:id/runs/:runId | read | One run with its log |
| GET | /projects/:id/dead-letters | read | ?limit= → jobs that used up their retries |
| POST | /projects/:id/dead-letters/replay | apply / deploy | { ids? } (default all) → queue them again. Deploy when a job ran on prod |
| GET | /projects/:id/tail | read | ?kind=events|requests|errors&env=&since=15m&limit= → change events and topic messages, or the request log (every error, about 10% of the rest, 7 days, paths only) |
| GET | /projects/:id/secrets | read | Secret names, env and updated-at; never values |
| PUT / DELETE | /projects/:id/secrets/:name | apply | PUT { value, env? } sets it (env dev | prod | all, default all); DELETE ?env= removes it. Workspace owners and admins only |
Hand-made schema (indexes, views, functions, triggers, extra tables and columns created with sql) is kept by contract apply and publish; schema marks it.
HTTP bodies use camelCase (dryRun, fullPage, skipVerify); the MCP tools use snake_case for the same fields. data/query also accepts entity in place of table.
Examples
export API=https://appbricx.com/api/dev/v1
export AUTH="Authorization: Bearer $APPBRICX_TOKEN"
export P=3f2c9a10-... # project idCheck
curl -sS -X POST "$API/projects/$P/check" -H "$AUTH" \
-H "content-type: application/json" \
-d "{\"contract\": $(cat appbricx.json)}"
# → { "report": { "ok": true, "errors": [], "fixes": [...], "warnings": [], "summary": {...} } }Apply
curl -sS -X POST "$API/projects/$P/apply" -H "$AUTH" \
-H "content-type: application/json" \
-d "{\"contract\": $(cat appbricx.json)}"
# → { "report": {...}, "summary": "... demo sign-ins per role ...", "warnings": [], "changed": true }Verify
curl -sS -X POST "$API/projects/$P/verify" -H "$AUTH"
# → { "report": { "status": "pass", "ms": 25000, "stages": [
# { "stage": "static", "status": "pass", "checks": [...] },
# { "stage": "data", "status": "pass", "checks": [...] },
# { "stage": "browser", "status": "pass", "checks": [...] } ] } }Each check has id, status, evidence and, when it fails, a fix. skipped is never a pass.
Screenshot
# The PNG itself
curl -sS -X POST "$API/projects/$P/screenshot?format=png" -H "$AUTH" \
-H "content-type: application/json" \
-d '{"route": "/jobs", "as": "technician"}' -o jobs.png
# JSON: png (base64), url, signedInAs, viewport, errors, overflowX, text
curl -sS -X POST "$API/projects/$P/screenshot" -H "$AUTH" \
-H "content-type: application/json" \
-d '{"as": "guest"}'as is a persona id, a demo login email or "guest". The default viewport is 390×844.
Run SQL on prod
curl -sS -X POST "$API/projects/$P/sql" -H "$AUTH" \
-H "content-type: application/json" \
-d '{"env": "prod", "sql": "CREATE INDEX job_due ON job (due)"}'
# → { "rows": [], "rowCount": 0, "statements": [{ "sql": "CREATE INDEX ...", "command": "CREATE" }],
# "env": "prod", "readOnly": false, "durationMs": 41, "snapshotId": "prod-20261012T...-agent-sql" }Errors
Errors are JSON with a message and, usually, a code:
{ "error": "This token lacks the \"deploy\" scope", "code": "FORBIDDEN_SCOPE" }| Status | Code | Meaning |
|---|---|---|
| 400 | (none) / BAD_REQUEST / BAD_QUERY | Validation failed (details lists fields) or a query names an unknown table or column |
| 401 | UNAUTHENTICATED | Missing, invalid, expired or revoked token, or the user left the token's workspace |
| 403 | FORBIDDEN_SCOPE | The token lacks the scope |
| 403 | SESSION_REQUIRED / INVALID_SCOPE | Token minting rules (see Access tokens) |
| 404 | (none) | Project not found, or outside the token's reach (never "forbidden") |
| 409 | PROJECT_BUSY | Another build is running; retry |
| 409 | HAND_EDITED_FILES | Compiled files were edited by hand; files lists them. Re-run with force: true to back them up and regenerate |
| 409 | NOT_BUILT | Nothing to screenshot yet; apply first |
| 422 | CONTRACT_INVALID | The contract can't be built; read report.errors |
| 422 | VERIFY_FAILED | Deploy refused because verify is red; report is included |
| 422 | SCREENSHOT_FAILED | The screenshot couldn't be taken (message says why) |
| 400 | STMT_FORBIDDEN | The SQL names a catalog or role statement the SQL editor refuses; use schema for catalog questions |
| 403 | TABLE_FORBIDDEN | rows: the role may not do that to the table, or the table is internal |
| 409 | NO_PERSONA | No app user holds the as role in that env |
| 503 | SNAPSHOT_FAILED | The snapshot before a prod write failed; nothing was written |
| 500 | BUILD_FAILED | The build failed at stage |