Back to overview
api reference

Documentation for the app.nz AI agent cloud.

One control-plane API and one OpenAI-compatible model gateway, both authenticated with the same key. Launch coding agents on your repos, route chat across providers, and publish sites, all over HTTP. Every endpoint here maps to a live route in the Go server.

Authentication

Every API call authenticates with a bearer key created from your account. Pass it as an Authorization header. Browser sessions (cookie auth) work too, but keys are the right choice for servers, agents, and the CLI. Secrets are shown once at create/rotate time, so store them immediately.

basehttps://app.nz
GET/api/keysList keys (metadata only, no secrets)API key
POST/api/keysCreate a key; response includes the one-time secretAPI key
POST/api/keys/rotateRotate by id, by name, or all at onceAPI key
DELETE/api/keys?id=key_123Revoke a keyAPI key
GET/api/meCurrent account for the supplied key or sessionAPI key
Create a key and call the API
# Create a key (secret returned once)
curl -sX POST https://app.nz/api/keys \
  -H "Authorization: Bearer $APP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"deploy bot"}'

# Use it on every other request
curl -s https://app.nz/api/me \
  -H "Authorization: Bearer app_live_..."

Models gateway

An OpenAI-compatible API in front of 15+ providers. Point any OpenAI or Anthropic client at the base URL and keep your code. Use app/auto to let the router pick a model from the prompt, or bias it with a variant, or pin a specific provider model. The same key meters usage across every call.

basehttps://app.nz/v1
POST/v1/chat/completionsChat completions (streaming + tools)API key
POST/v1/messagesAnthropic-compatible messages (supports thinking)API key
GET/v1/modelsList routable models and aliasesAPI key
POST/v1/embeddingsText embeddingsAPI key
POST/v1/images/generationsImage generationAPI key
POST/v1/audio/speechText-to-speechAPI key
POST/v1/audio/transcriptionsAudio transcriptionAPI key
POST/v1/searchWeb and papers searchAPI key
Model routes (the model field)
app/autorouteDefault. Reads the prompt and picks the backend.
app/auto-coderouteBias toward strong coding models.
app/auto-fastrouteLowest latency for interactive use.
app/auto-cheaprouteBias toward lowest cost per token.
app/auto-reasoningrouteRoute reasoning depth automatically.
app/auto-visionrouteBias toward image-input models.
app/auto-imagerouteBias toward image-generation models.
provider/modelpinPin a specific upstream model, e.g. anthropic/claude or openai/gpt.
Chat completion with auto routing
curl -s https://app.nz/v1/chat/completions \
  -H "Authorization: Bearer app_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "app/auto",
    "messages": [{"role": "user", "content": "Explain CRDTs in one paragraph."}],
    "reasoning_effort": "auto",
    "stream": false
  }'

Agents API

Run cloud coding agents against a repo and a prompt, then poll status, stream step events, inspect changed files, and cancel or retry. GET /api/agents/config returns the option lists (engines, models, reasoning efforts, machine types, providers, skills) and needs no auth so a UI can render the form before sign-in.

basehttps://app.nz
GET/api/agents/configOption lists for the agent formpublic
POST/api/agents/tasksLaunch an agent taskAPI key
GET/api/agents/tasksList your agent tasksAPI key
GET/api/agents/tasks/{id}Get a task with its current statusAPI key
GET/api/agents/tasks/{id}/eventsStep-by-step events and statusAPI key
POST/api/agents/tasks/{id}/cancelCancel a running taskAPI key
POST/api/agents/tasks/{id}/retryRetry a finished or failed taskAPI key
GET/api/agents/tasks/{id}/filesList files the agent changedAPI key
PUT/api/agents/tasks/{id}/files/{fileId}Edit a changed file before reviewAPI key
POST /api/agents/tasks body
prompt*stringWhat the agent should do (max 20k chars).
repostringTarget repo as owner/name.
branchstringWorking branch to create or use.
baseBranchstringBranch to base the work on.
modelstringModel route, e.g. app/auto-code.
enginestringAgent engine (see /config).
reasoningEffortstringnone | low | medium | high | auto.
machineTypestringWorker size, e.g. cpx32.
providerstringRepo/git provider (see /config).
skillsstring[]Enabled skills, e.g. ["github","visualbench"].
autoMergePrbooleanAuto-merge the PR when checks pass.
autoNextStepsbooleanLet the agent queue follow-up steps.
spendCapUsdnumberHard spend ceiling for the task.
timeoutSecondsnumberWall-clock timeout.
projectIdstringProject to bill and scope to; defaults to your default project.
titlestringDisplay title; derived from the prompt if omitted.
Launch an agent
curl -sX POST https://app.nz/api/agents/tasks \
  -H "Authorization: Bearer app_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "add usage analytics to the dashboard",
    "repo": "acme/ai-dashboard",
    "model": "app/auto-code",
    "reasoningEffort": "high",
    "machineType": "cpx32",
    "skills": ["github", "visualbench"],
    "spendCapUsd": 2.00,
    "autoMergePr": false
  }'

Character chat API

Start chats with any character by url_name or id, pin a model for that chat, and stream replies over the same server-sent-events shape as the OpenAI-compatible gateway. User-created characters can include long-form text or Markdown documents; app.nz strips image links, chunks the text, stores it in the character vector-search boundary, and retrieves relevant excerpts for each turn.

basehttps://app.nz
GET/api/search-ais?q=luna&limit=20Find characters by name, title, tags, or descriptionpublic
GET/api/get-ai-by-name?name=lunaLoad one character by url_name or display namepublic
POST/api/charactersCreate a user-owned character and ingest text/Markdown docsAPI key
PATCH/api/characters/{url_name}Update your character and optionally replace indexed docsAPI key
POST/api/assistant/chatsCreate a chat for a character with a chosen modelAPI key
POST/api/assistant/chats/{id}/messagesSend a turn and stream the character replyAPI key
GET/api/assistant/chats/{id}Reload a chat and its active branchAPI key
Character and chat bodies
name*stringPOST /api/characters display name.
system_promptstringOptional persona prompt; generated from name/description/greeting if omitted.
documentsarrayOptional long-form docs: [{ "name": "lore.md", "content": "# Markdown..." }]. Alias: knowledge_docs.
character_url_name*stringPOST /api/assistant/chats target character slug.
modelstringModel or route for this chat, e.g. app/auto or app/auto-fast.
reasoning_effortstringauto | off | low | medium | high.
content*stringMessage text for POST /messages.
Create a documented character and talk to it with a model
# Create a character with long-form Markdown knowledge.
curl -sX POST https://app.nz/api/characters \
  -H "Authorization: Bearer app_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "GPU Brain Operator",
    "description": "Helps operate the gpu-brain search stack.",
    "voice": "Kore",
    "documents": [{
      "name": "runbook.md",
      "content": "# Runbook\nUse gobed for low-latency KNN over text chunks. Never ingest image links."
    }]
  }'

# Start a chat with a given model.
CHAT=$(curl -sX POST https://app.nz/api/assistant/chats \
  -H "Authorization: Bearer app_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "character_url_name": "gpu-brain-operator",
    "model": "app/auto-fast",
    "reasoning_effort": "auto"
  }' | jq -r .chat.id)

# Send a message. The response is text/event-stream; relevant doc excerpts are
# retrieved server-side before the model call.
curl -N -sX POST https://app.nz/api/assistant/chats/$CHAT/messages \
  -H "Authorization: Bearer app_live_..." \
  -H "Content-Type: application/json" \
  -d '{"content":"What should I check if KNN search looks stale?"}'

Sites API

Host a static site straight from the control plane. Create a slug, push files (index.html + assets, text or binary), and it is published instantly at both app.nz/sites/<slug>/ and its own subdomain <slug>.app.nz. No build step, no DNS wait. The subdomain is the right home for SPAs — bundlers emit absolute /assets/… paths that only resolve from a site root — and it is served straight from Cloudflare R2 at the edge, so static traffic never touches an origin. A fresh site is seeded with a working starter (index.html, styles.css, app.js). Slugs are 2–40 chars: lowercase letters, numbers, and hyphens, and a few reserved names are blocked. Files are up to 8 MB each; binary assets (images, fonts, audio) are stored too.

basehttps://app.nz
GET/api/sitesList your sitesAPI key
POST/api/sitesCreate a site (seeds a starter)API key
GET/api/sites/{id}Get a site with its filesAPI key
DELETE/api/sites/{id}Delete a siteAPI key
PUT/api/sites/{id}/filesCreate or update a file (publishes)API key
DELETE/api/sites/{id}/files?path=app.jsDelete a fileAPI key
GET/sites/{slug}/{path}Public serving — no auth, defaults to index.htmlpublic
GEThttps://{slug}.app.nz/{path}Public serving on the site’s own subdomain (SPA-friendly)public
Request bodies
slug*stringPOST /api/sites — public name; normalized to a valid slug.
titlestringPOST /api/sites — display title (max 120 chars).
path*stringPUT files — file path, e.g. index.html or css/app.css.
contentstringPUT files — UTF-8 file contents (max 8 MB). Use for text files.
contentBase64stringPUT files — base64 bytes for binary files (images, fonts, audio).
contentTypestringPUT files — overrides the type inferred from the extension.
Deploy a built site with the CLI (or raw curl)
# Easiest: push a whole build directory with the app CLI. It creates the
# site on first run, uploads every text file, and prunes anything removed.
app login --api-key app_live_...
npm run build                         # e.g. Vite -> dist/
app sites deploy my-app dist --title "My app"
#   Live at https://app.nz/sites/my-app/
#     and  https://my-app.app.nz/

# Or drive the REST API directly:
SITE=$(curl -sX POST https://app.nz/api/sites \
  -H "Authorization: Bearer app_live_..." \
  -H "Content-Type: application/json" \
  -d '{"slug":"my-landing","title":"My landing"}')

ID=$(echo "$SITE" | jq -r .site.id)

# Publish index.html — live at /sites/my-landing/ and my-landing.app.nz
curl -sX PUT https://app.nz/api/sites/$ID/files \
  -H "Authorization: Bearer app_live_..." \
  -H "Content-Type: application/json" \
  -d '{"path":"index.html","content":"<!doctype html><h1>Hi</h1>"}'

Billing & plans

Everything is paid from one prepaid credit balance (credits are ~$0.001 each). On top of pay-as-you-go, a Pro ($20), Ultra ($60), or Max ($200) plan grants monthly credits, a guaranteed number of concurrent machines, and per-product free quotas. Plan credits are used before purchased credits and roll over for one month.

basehttps://app.nz
GET/api/pricingUsage-based pricing: model token rates, compute, search, credit unitpublic
GET/api/plansList plan catalog (price, credits, machines, quotas)public
GET/api/plans/meYour plan, credit balance, and product quota usageAPI key
POST/api/plans/subscribeStart a Pro/Ultra/Max checkoutsession
POST/api/plans/cancelCancel at period endsession
POST/api/plans/portalOpen the Stripe billing portalsession
GET/api/credits/balancePrepaid credit balance + auto-topupAPI key
POST/api/credits/checkoutBuy credit packssession
POST/api/credits/autotopupConfigure automatic top-upssession
Plan tiers
freeplan$0 — pay-as-you-go credits, shared worker pool.
proplan$20/mo — 25,000 credits, 1 guaranteed machine.
ultraplan$60/mo — 80,000 credits, 3 machines + priority.
maxplan$200/mo — 280,000 credits, 6 machines + top priority.
Check your plan and subscribe from the CLI
# Inspect the catalog
curl -s https://app.nz/api/plans | jq

# From the CLI (app login first)
app plan show
app plan subscribe ultra
app billing usage

First-party products

RA1 art generation, paper search, and agentic search are first-party APIs metered against the same balance. Plan subscribers get a monthly free quota per product, consumed before any credits are charged. All three accept a Bearer key or a signed-in session.

basehttps://app.nz
POST/api/ra1/generateGenerate images with RA1 — prompt, count, aspect, style, negative (50 credits each)API key
GET/api/ra1/statusPoll a queued render by jobId for status + image URLsAPI key
GET/api/papers/searchSearch 200M+ papers (1 credit each)API key
POST/api/searchAgentic web search (10 credits per depth)API key
Call the products from the CLI
app chat "research R2-backed model hosting" --web --deep --papers
app ra1 generate --prompt "a cat astronaut" --count 2
app papers search "diffusion transformers" --limit 5
app search "best vector database 2026" --depth 2

Conventions

  • • Auth: Authorization: Bearer app_live_... on every non-public route.
  • • Bodies and responses are JSON; successful writes return { "success": true, ... }.
  • • Errors return a non-2xx status with { "error": "message" }.
  • • Get a key with the CLI: app keys create --name "deploy bot".