AnySites

// GETTING STARTED

Platform API for AI Coding Tools

A per-project API key and REST endpoints under /api/v1 — let an AI coding tool check deploy status, read logs, trigger deploys, and read/write env vars on its own.

The Dev Prompt is a one-time snapshot — useful to paste at the start of a session, but it goes stale the moment something changes. The Platform API is the always-live counterpart: a REST API scoped to a single project that an AI coding tool (or any script) can call directly, without a human regenerating and re-pasting anything.

Getting a key

Open a project's Dev Prompt page and generate a key in the API Key card — optionally give it a name (e.g. "Cursor", "CI") so you can tell keys apart later. The raw key is shown exactly once — copy it immediately, since AnySites only ever stores its hash, not the value itself. A project can have any number of keys at once, each independently revocable, so giving one tool its own key doesn't affect any other tool's access. Revoking a key removes its access immediately; the others keep working.

The key is scoped to that one project — it authenticates as "this project", not as your account. It cannot see or affect any other project, even other projects in your own account. Treat it like a project-specific password: don't commit it to the repo it grants access to.

Authentication

Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Every request needs this header. There's no separate login step and no session — the key is the credential. A missing or revoked key returns 401.

Base URL

https://api.anysites.app/api/v1

Endpoints

Method & pathWhat it does
GET /statusProject status, site type, tech stack, build/start commands, port, the currently active deploy, and custom domains.
GET /deploysThe last 20 deploys — status, commit, branch, who/what triggered it.
GET /deploys/:deployIdOne deploy in full, including the complete build log.
POST /deploysTrigger a build of the production branch's latest commit — same pipeline as clicking Manual Deploy. Returns 409 if a deploy is already in flight.
GET /logs/runtime?lines=200Recent stdout/stderr from the running container. Same data as the dashboard's Runtime Logs page, not a live stream.
GET /envEvery environment variable with its real value — no masking, since the key itself already grants this level of access.
PUT /env/:keyCreate or update one variable. Rejects keys that don't match [A-Z_][A-Z0-9_]*. System variables (like DATABASE_URL) can't be modified this way — 403.
DELETE /env/:keyDelete one variable. System variables can't be deleted this way — 403.
GET /databaseThe project's live DATABASE_URL, if a database is provisioned.
GET /resourcesThe running container's current disk (writable layer) and memory usage, plus the thresholds AnySites itself alerts and auto-remediates on.
Editing an environment variable through the API doesn't restart the running container, same as editing it in the dashboard — call POST /deploys afterward if you need the change live immediately.

Checking your own container's footprint

A container's writable layer (local caches, log files, anything the app writes to its own filesystem instead of the database or object storage) is disposable but not unlimited — AnySites monitors it platform-wide and, past a hard ceiling, automatically recreates the container to reclaim the space. That's a safety net for the shared node, not a substitute for the app managing its own cache. GET /resources returns the same numbers that monitoring uses, so an AI coding tool can check them directly instead of finding out the hard way.

FieldMeaning
diskUsageBytesCurrent size of the container's writable layer.
diskWarningBytes / diskCriticalBytes5GB / 15GB. Past warning, AnySites logs an alert. Past critical, it recreates the container (same image, same config, fresh writable layer) automatically.
memoryUsageBytes / memoryLimitBytesCurrent usage against the container's memory limit.
The most common cause of runaway disk usage is an unbounded local cache — e.g. Next.js's App Router fetch() Data Cache writing to .next/cache/fetch-cache with no revalidate policy, which can grow into the tens of gigabytes over a few days of traffic. If diskUsageBytes is climbing toward diskWarningBytes, that's usually where to look.

Database management (`/db` prefix)

These run against the same connection pool and introspection logic as the project's Table Editor and SQL Editor in the dashboard — same trust level as a direct psql connection, not sandboxed to SELECT.

Method & pathWhat it does
GET /db/schemaEvery table: columns (type, nullable, default, primary key, foreign key), indexes, size, and row estimate.
GET /db/tables/:table/rowsPaginated rows. Query params: schema (default public), limit (max 500), offset, orderBy, orderDir, filters (JSON object of column→value equality filters).
POST /db/tables/:table/rowsInsert one row. Body: { values: {...} }.
PATCH /db/tables/:table/rowsUpdate one row. Body: { pk: {...}, values: {...} }. 404 if the table has no primary key — there's nothing safe to match on.
DELETE /db/tables/:table/rowsDelete one row. Body: { pk: {...} }.
POST /db/query / POST /db/migrateIdentical endpoints — run arbitrary SQL, including multi-statement scripts and DDL (CREATE TABLE, etc.). Body: { sql: "..." }. Results capped at 500 rows, 15-second statement timeout, same as the SQL Editor. /db/migrate is just a clearer name for the same thing: running a full schema.sql or migration file against a freshly-provisioned, empty database.
POST /db/tablesCreate a table. Body: { schema?, name, columns: [{ name, dataType, nullable, default?, primaryKey? }] }.
DELETE /db/tables/:tableDrop a table.
POST /db/tables/:table/columnsAdd a column. Body: { column: { name, dataType, nullable, default? } }.
DELETE /db/tables/:table/columns/:columnDrop a column.
POST /db/tables/:table/indexesCreate an index. Body: { name, columns: [...], unique? }.
DELETE /db/tables/:table/indexes/:indexNameDrop an index.
CSV import/export, saved queries, and backup/restore are deliberately not part of this API — the first two are dashboard-UI workflows, and a full-database restore is destructive enough that it stays a manual dashboard action rather than something reachable from a single API call. Use the dashboard's Database page for those.
Possessing the API key is the authorization for /db/query and /db/migrate — running DDL (creating tables, running a schema.sql against a freshly-provisioned empty database, etc.) through them doesn't require a separate confirmation step any more than running the same SQL through the dashboard's SQL Editor would. If you're an AI coding tool with a project's key and need to bootstrap its schema, call /db/migrate directly.

Example

curl -H "Authorization: Bearer ak_..." https://api.anysites.app/api/v1/status
curl -H "Authorization: Bearer ak_..." https://api.anysites.app/api/v1/db/schema

Design notes

None of these routes take a project ID in the URL — the key itself identifies exactly one project, so there's no ID to get wrong or spoof. This is deliberate: it's structurally impossible to use one project's key to read or modify another project's data, regardless of what path you construct.

Related documentation