whoami/api/v1/whoamiConfirm this key is valid. 401 means it does not resolve.
{ "uid": "abc123" }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.
$ curl https://abstrak.zenithurl.com/api/v1/whoami \
-H "Authorization: Bearer ak_live_a3f2…"{ "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.
Read what already exists before you create anything. State is the one call you should learn first.
whoami/api/v1/whoamiConfirm this key is valid. 401 means it does not resolve.
{ "uid": "abc123" }state/api/v1/stateFull 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.
{
"defaultProjectId": "my-project",
"projects": [{
"id": "...", "label": "...",
"hasDatabase": true,
"collections": [...],
"subProjects": [...],
"config": { apiKey, projectId, ... }
}],
"gates": [{ publicKey, mode, label, projectId, subPath, providers }]
}projects/api/v1/projectsLighter list — just ids and labels. Prefer /state unless you only need names.
{ "projects": [{ "id", "label", "isDefault" }] }project/api/v1/projectOne project in detail. Pass subPath to drill into a from_<name>/all sub-project.
{ "projectId": "...", "subPath"?: "from_<name>/all" }{ "config", "collections", "subProjects", "hasDatabase" }dump/api/v1/dumpEvery document that has data, in one list. Read-only. Handles the artifacts/{appId}/… layout that most AI-generated apps use.
{ "projectId": "..." }{ "docs": [{ "path", "data" }] }Everything an admin can do. Each call is one action; chain them for a flow.
create-database/api/v1/create-databaseMake the (default) Firestore database inside an existing project.
⚠ location cannot be changed later.
{ "projectId": "...", "location": "nam5" }{ "ok": true, "message": "..." }create-subproject/api/v1/create-subprojectPartition inside a project — same shape as merge produces, but no new Firebase project used.
{ "projectId": "...", "name": "my-sub" }{ "ok": true, "id": "from_my-sub" }merge/api/v1/mergeCopy 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.
{ "from": "<id> | [ids]", "to": "<id>", "deleteSources"?: false }{ "total", "deleted", "issues", "message" }reorganize/api/v1/reorganizeMove 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.
{ "projectId": "..." }{ "ok", "moved", "folder", "repointed" }rules/api/v1/rulesRead 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.
{ "projectId": "..." } // read
{ "projectId": "...", "source": "<full rules>" } // deploy{ "source": "..." } // read
{ "ok", "message" } // deployMint and manage the pk_live_ keys developers paste into their frontend.
create-gate/api/v1/create-gateMint 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.
{ "mode": "quick"|"accounts", "name"?, "providers"?,
"googleClientId"?, "projectId"?, "subPath"? }{ "id": "pk_live_..." }update-gate/api/v1/update-gateRe-point an existing gate at a different project / sub-project.
{ "publicKey": "pk_live_...", "projectId"?, "subPath"? }{ "ok": true }delete-gate/api/v1/delete-gateRemove a gate. The pk_live_ it minted stops working immediately.
{ "publicKey": "pk_live_..." }{ "ok": true }set-default/api/v1/set-defaultChange which project new gates store data in by default.
{ "projectId": "..." }{ "ok", "projects" }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.
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 });