// agent api reference

Fourteen endpoints.
One header. No SDK.

Every call takes Authorization: Bearer ak_live_…, returns JSON, and operates on the Firebase projects of the Google account that minted the key. There is no per-project key scoping — a key covers everything you own.

basehttps://abstrak.zenithurl.com
authAuthorization: Bearer ak_live_…
spec/llms.txt— paste into any AI
errors{ "error": "..." }401 bad key · 400 bad body · 500 server
how to get a key
  1. Open the dashboard and sign in with Google.
  2. Click Connect Google account and approve the two Firebase permissions.
  3. Open the Keys tab and click Generate key. Copy it — the full value is shown once.
  4. Paste it as the Bearer header above. Hit /api/v1/whoami to confirm.
zsh — your first call
$ curl https://abstrak.zenithurl.com/api/v1/whoami \
    -H "Authorization: Bearer ak_live_a3f2…"
200 ok
{ "uid": "<your account id>" }

Hand this guide to any AI by linking to /llms.txt, or paste its contents into the chat. Agents are the primary audience here.

// inspect

Inspect

Read what already exists before you create anything. State is the one call you should learn first.

GETwhoami
/api/v1/whoami

Confirm this key is valid. 401 means it does not resolve.

response
{ "uid": "abc123" }
GETstate
/api/v1/state

Full snapshot — call this first and before each create. Lists every project with its database, collections, sub-projects, and web config, plus every gate and the default project.

response
{
  "defaultProjectId": "my-project",
  "projects": [{
    "id": "...", "label": "...",
    "hasDatabase": true,
    "collections": [...],
    "subProjects": [...],
    "config": { apiKey, projectId, ... }
  }],
  "gates": [{ publicKey, mode, label, projectId, subPath, providers }]
}
GETprojects
/api/v1/projects

Lighter list — just ids and labels. Prefer /state unless you only need names.

response
{ "projects": [{ "id", "label", "isDefault" }] }
POSTproject
/api/v1/project

One project in detail. Pass subPath to drill into a from_<name>/all sub-project.

body
{ "projectId": "...", "subPath"?: "from_<name>/all" }
response
{ "config", "collections", "subProjects", "hasDatabase" }
POSTdump
/api/v1/dump

Every document that has data, in one list. Read-only. Handles the artifacts/{appId}/… layout that most AI-generated apps use.

body
{ "projectId": "..." }
response
{ "docs": [{ "path", "data" }] }
// create & move

Create & move

Everything an admin can do. Each call is one action; chain them for a flow.

POSTcreate-database
/api/v1/create-database

Make the (default) Firestore database inside an existing project.

⚠ location cannot be changed later.

body
{ "projectId": "...", "location": "nam5" }
response
{ "ok": true, "message": "..." }
POSTcreate-subproject
/api/v1/create-subproject

Partition inside a project — same shape as merge produces, but no new Firebase project used.

body
{ "projectId": "...", "name": "my-sub" }
response
{ "ok": true, "id": "from_my-sub" }
POSTmerge
/api/v1/merge

Copy every document from one or more source projects into a target, namespaced under from_<source>/. Sources are left untouched unless deleteSources is true.

⚠ Merge does NOT redirect apps that pointed at a deleted source. Those references break.

body
{ "from": "<id> | [ids]", "to": "<id>", "deleteSources"?: false }
response
{ "total", "deleted", "issues", "message" }
POSTreorganize
/api/v1/reorganize

Move a project's root data into its own from_<projectId>/all/ sub-project. Copies first, then deletes the root; re-points gates targeting the root. Apps reading the old paths directly must be updated.

⚠ Destructive. Only run when explicitly asked.

body
{ "projectId": "..." }
response
{ "ok", "moved", "folder", "repointed" }
POSTrules
/api/v1/rules

Read or deploy Firestore security rules. One ruleset per project — shared by every sub-project. ALWAYS GET first, merge your additions into the existing source, then POST the whole thing. Never POST only your own block.

body
{ "projectId": "..." } // read
{ "projectId": "...", "source": "<full rules>" } // deploy
response
{ "source": "..." } // read
{ "ok", "message" } // deploy
// gates

Gates

Mint and manage the pk_live_ keys developers paste into their frontend.

POSTcreate-gate
/api/v1/create-gate

Mint a public gate key. projectId + subPath target where this gate's users and data land. Both optional — default is the account's default project root.

body
{ "mode": "quick"|"accounts", "name"?, "providers"?,
  "googleClientId"?, "projectId"?, "subPath"? }
response
{ "id": "pk_live_..." }
POSTupdate-gate
/api/v1/update-gate

Re-point an existing gate at a different project / sub-project.

body
{ "publicKey": "pk_live_...", "projectId"?, "subPath"? }
response
{ "ok": true }
POSTdelete-gate
/api/v1/delete-gate

Remove a gate. The pk_live_ it minted stops working immediately.

body
{ "publicKey": "pk_live_..." }
response
{ "ok": true }
POSTset-default
/api/v1/set-default

Change which project new gates store data in by default.

body
{ "projectId": "..." }
response
{ "ok", "projects" }
// for humans

SDK — paste once, done.

If you want your own users to sign in on your own site, mint a pk_live_ gate in the dashboard and drop the npm package in your frontend. The hosted popup handles Google — no Google Console setup, no Firebase Auth boilerplate.

$ npm install abstrak
app.tsx
import { abstrak } from "abstrak";

const gate = abstrak("pk_live_…");
const user = await gate.signIn();
await gate.tag({ role: "student" });
if (await gate.is({ role: "admin" })) showPanel();
await gate.require({ role: "admin" });
await user.data.set({ purchases: 3 });