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 — click any one for its own reference page.

Use these docs with your AI agent

Every page here is machine-readable. Point a coding agent at /llms.txt for the index, or /llms-full.txt for a self-contained build-an-agent guide. Paste this prompt into any agent:

Build-an-agent prompt
Read https://app.nz/llms-full.txt and follow it to build an agent on app.nz: call the OpenAI-compatible gateway, launch a cloud coding agent, and ship a deploy.
Already have OpenAI code?
from openai import OpenAI

# Same OpenAI code — only the base URL and key change.
client = OpenAI(base_url="https://app.nz/v1", api_key="pk_live_...")
r = client.chat.completions.create(
    model="app/auto",  # router picks the model, or pin "provider/model"
    messages=[{"role": "user", "content": "Hello from app.nz"}],
)

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
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 pk_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
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.
routing_strategyparamprice by default; use config to preserve catalogue order or app/auto-fast for latency bias.
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 pk_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
POST /api/agents/tasks body
prompt*stringWhat the agent should do (max 20k chars).
sourcestringProvider that runs it: openpaths (default, our cloud) | devin | cursor | codex-cloud. See the Agents SDK section.
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 capability tier (see /config), e.g. auto, cpx32, gpu-a100, or win-cpx32 for a Windows worker.
providerstringExecution tier, e.g. shared (auto fleet), cloud CPU, or cloud GPU (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 pk_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": "auto",
    "provider": "shared",
    "skills": ["github", "visualbench"],
    "spendCapUsd": 2.00,
    "autoMergePr": false
  }'

Agents SDK — one API, every provider

The same /api/agents surface is a meta-agent router: set `source` to choose who runs the task. openpaths (the default) runs it on app.nz workers using our model credentials — which take precedence over any provider key when running in our cloud — and opens PRs through our GitHub app. devin, cursor, and codex-cloud launch the run on that vendor and the result (status, logs, diff, pull request) normalizes back into the same task — so every provider reads through one trace. GET /api/agents/config returns `sources` plus a `sourcesConfigured` map so a UI can disable providers that lack server credentials.

basehttps://app.nz
Source values
openpathssourceDefault. Runs on app.nz workers with our credentials; engine selects Claude Code / Codex / Gemini. Real PRs via our GitHub app.
devinsourceLaunches a Devin cloud session. Needs server DEVIN_API_KEY + DEVIN_ORG_ID.
cursorsourceLaunches a Cursor cloud agent with auto-PR. Needs server CURSOR_API_KEY.
codex-cloudsourceLaunches an OpenAI Codex Cloud task against a GitHub-connected repo. Needs CODEX_CLOUD_ENV_ID + the codex CLI.
Launch on Devin (or swap source for cursor / codex-cloud / openpaths)
curl -sX POST https://app.nz/api/agents/tasks \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "source": "devin",
    "prompt": "fix failing CI and open a pull request",
    "repo": "lee101/edukids",
    "baseBranch": "main",
    "autoMergePr": false
  }'

# CLI equivalent:
#   app agents-sdk run "fix failing CI and open a PR" --source devin --repo lee101/edukids
#   app agents-sdk providers      # see which providers are configured
#   app agents-sdk logs <id>      # read the normalized trace

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
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 pk_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 pk_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 pk_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
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 pk_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 pk_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 pk_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
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
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 pk_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".