Drive GnamiAI from anywhere.
One Bearer key, JSON over HTTPS, every endpoint that powers the
dashboard. Build a Discord bot, a smart-mirror, a cron job that
summarizes your inbox — same surface as the web app. No SDK
required; fetch is enough.
1. Authentication
Every authenticated endpoint accepts a Bearer key in the
Authorization header:
Authorization: Bearer gnami_xxxxxxxxxxxxxxxxxxxxxx
Create one in the dashboard at Settings → API keys. The full key is shown once at creation. We store only its scrypt hash; we cannot recover the secret. Lose it, revoke it and create a new one.
A key carries the same authority as a browser session for the owning workspace, with a few exceptions noted in section 10.
2. Errors & rate limits
Every error is a JSON body with error (machine
code) and message (human). HTTP status follows the
usual semantics:
400— bad request body401— missing or invalid Bearer key402— provider not configured (no inference key on the workspace) or quota exhausted403— endpoint requires a browser session, not an API key404— resource not found429— rate limit.Retry-Afterheader carries the wait in seconds.502— upstream provider failed503— service-level dependency missing (e.g. unconfigured Polar env vars)
Rate limit on /api/agent/turn: 20
turns per minute per workspace, regardless of which key drove
them. Exceeding returns 429 + Retry-After: 60.
Other endpoints are not per-call rate-limited today; budget cap
applies to inference cost via your provider plan in Settings.
3. POST /api/agent/turn — drive the agent
The main event. Sends a turn through your configured provider,
loads your skills + memory, optionally executes any
gnami-action blocks the model emits, and returns
the user-visible reply.
Body
{
"input": "string, required, ≤ 8 000 chars",
"history": [{ "role": "user"|"assistant", "content": "..." }, ...],
"subagentId": "uuid | null",
"attachments": [{ "name": "doc.pdf", "mimeType": "application/pdf", "data": "<base64>" }],
"audio_input": "<base64 audio bytes> (optional, triggers Whisper STT)"
}
Response (200)
{
"output": "string — the assistant reply",
"provider": "openai|anthropic|openrouter|ollama",
"model": "gpt-4o-mini",
"latencyMs": 1240,
"agentName": "default | <subagent name>",
"actions": [{ "type": "create_skill", "ok": true, "summary": "..." }],
"context": { "memoriesUsed": 0, "skillsUsed": 2, "historyMessages": 4, ... }
}
curl
curl https://gnamiai.live/api/agent/turn \
-H "Authorization: Bearer $GNAMI_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"Summarize what I did this week."}'
Node
const res = await fetch("https://gnamiai.live/api/agent/turn", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.GNAMI_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ input: "Summarize what I did this week." })
});
const { output } = await res.json();
console.log(output);
4. /api/skills — workspace skills
Plain-text Markdown blocks injected into the system prompt at
turn time when enabled = true.
GET /api/skills— list owned skills (full content + entitlements from marketplace)POST /api/skills— body{ name, content, enabled?, command_slug? }PATCH /api/skills/:id— partial updateDELETE /api/skills/:id— remove
Quotas: see Settings → Account, depends on your plan.
5. /api/subagents — managed specializations
Named personas with their own system prompt + optional model
override. Pin one in chat with /agent <name>
or pass subagentId to /api/agent/turn.
GET /api/subagents— listPOST /api/subagents—{ name, description, systemPrompt, model? }PATCH /api/subagents/:id— partial updateDELETE /api/subagents/:id— remove
6. /api/crons — scheduled runs
Recurring agent turns. Triggered by Vercel Cron at the cadence
defined in interval_minutes. The agent picks up
every cron whose next_run_at ≤ now().
GET /api/crons— list with last status / outputPOST /api/crons—{ name, prompt, interval_minutes, subagent_id? }PATCH /api/crons/:id— toggle enabled, change prompt, etc.DELETE /api/crons/:id— removePOST /api/crons/:id/run— fire one-off, ignoring schedule
7. /api/approvals — pending HITL gates
Destructive actions that the agent emitted but cannot execute
without your sign-off. Build a custom approval UI by polling
?status=pending.
GET /api/approvals?status=pending|approved|rejected|expiredPOST /api/approvals/:id/resolve—{ decision: "approve"|"reject" }
8. /api/memory/tree — episodes & long-term memory
Conversation episodes (auto-generated 2-3 sentence summaries, 50 most recent) plus the Mem0 connection status if configured.
GET /api/memory/tree
→ {
"episodes": [{ "id", "ts", "summary", "tokens" }, ...],
"mem0": { "connected": true|false, "scope": "..." }
}
9. Public marketplace endpoints (no auth)
Anyone can hit these — useful for indexers, integrations, or a marketplace mirror. No Bearer header needed.
GET /api/marketplace/stats— aggregate creator/listing/install countsGET /api/marketplace/listings/all— every published listingGET /api/marketplace/listings/by-slug/:slug— listing detail + recent reviews + ratingsGET /api/marketplace/listings/:listingId/reviews— full review list (max 50)GET /api/marketplace/creator/by-slug/:slug— creator profile + their listings
10. Endpoints API keys CANNOT reach
These return 401 for Bearer auth even with a valid
key — they require a real browser session. The intent is to
prevent a leaked key from being able to take down the workspace
or escalate itself.
DELETE /api/account— workspace deletionPOST /api/account/import— overwrite workspace from a JSON dumpPOST /api/auth/google/link+/unlink— identity provider bindingGET|POST|DELETE /api/settings/api-keys+/api-keys/:id— managing keys themselves
11. End-to-end recipes
Four runnable Node scripts. View or download each one directly
— they're plain .mjs files served by this site:
marketplace-snapshot.mjs— fetches public stats + lists every published skill (no auth)agent-turn.mjs— single Bearer-authenticated turnlist-skills.mjs— list and pretty-print your workspace skillsdiscord-bot.mjs— production-ready Discord bot: auto-reconnect with RESUME, per-channel history, queued turns (respects rate limits), structured JSON logs, graceful shutdown. Zero npm deps.
Each is < 100 lines and runnable with node script.mjs + a GNAMI_KEY env var. Quick fetch:
curl -O https://gnamiai.live/examples/agent-turn.mjs
export GNAMI_KEY=gnami_xxxxxxxxxxxxxxxxxxxxxx
node agent-turn.mjs "ping"
Or read the README for the full setup.
Build the integration
Spin up a key in Settings, copy one of the example scripts, change three lines. Production-ready in < 10 minutes.