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:
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.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"}],
)Quick copy for any LLM
Give an agent a complete, safer brief.
Read https://app.nz/llms-full.txt, especially “Launch a cloud coding agent”.
Use app.nz to complete this outcome: <describe the outcome>.
- Repository: <owner/repo>
- Constraints: preserve unrelated work; never expose secrets; ask before destructive or costly actions.
- Execution: choose an appropriate agent/model route, inspect existing instructions, implement the smallest coherent change, and run relevant tests.
- Visual changes: capture desktop and mobile evidence in VisualBench and inspect it.
- Return: summary, changed files, tests, remaining risks, and PR/deploy URL when created.Also available offline as app guide agent and through the app.nz MCP server.
CLI + MCP handoff
Give any LLM the same platform context.
Generate a deployment brief offline, or connect the app.nz MCP server so an agent can retrieve instructions and use platform tools directly.
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.
/api/keysList keys (metadata only, no secrets)API keyPOST/api/keysCreate a key; response includes the one-time secretAPI keyPOST/api/keys/rotateRotate by id, by name, or all at onceAPI keyDELETE/api/keys?id=key_123Revoke a keyAPI keyGET/api/meCurrent account for the supplied key or sessionAPI key# 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_..."The app CLI
Every endpoint in these docs is scriptable from one small binary. The CLI shares keys with the API and web app, streams chat, deploys apps and sites, drives coding agents, and mirrors the gh command layout for repos, issues, PRs, and releases. Any command takes --json; anything without a dedicated command is reachable via app api. The full command reference lives at /cli.
app login --api-key <key>authSave a key (or set APP_API_KEY); app whoami verifies.app apps deploy [dir]hostingPackage + build + release an appnz.yaml app (static or server runtime) at <name>.app.nz.app apps logs <slug>hostingBuild and runtime logs for the latest (or a given) deploy.app apps marketplace [query]hostingBrowse apps and games built on or showcased by app.nz.app apps publish [slug] --url <url>hostingInstantly enrich a hosted app card or publish an external community app with automatic OG metadata discovery.app sites deploy <slug> <dir>hostingMirror a directory of static files to a hosted site.app agent run --prompt "..." --repo o/nagentsLaunch a cloud coding agent; get/list/cancel manage tasks.app chat "..." [--web] [--deep]modelsStreamed chat through the gateway; --model pins a route.app api <METHOD> <path> [json]escape hatchCall any documented endpoint directly.curl -fsSL https://app.nz/cli.sh | sh
app login --api-key pk_live_...
# hand the build to a cloud agent
app agent run --prompt "build a neon snake HTML5 game" --repo you/neon-snake
# pull the agent's files, then ship to https://neon-snake.app.nz
app agent apply <task-id> --dir ./neon-snake
app apps deploy ./neon-snakeModels 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.
/v1/chat/completionsChat completions (streaming + tools)API keyPOST/v1/messagesAnthropic-compatible messages (supports thinking)API keyGET/v1/modelsList routable models and aliasesAPI keyPOST/v1/embeddingsText embeddingsAPI keyPOST/v1/images/generationsImage generationAPI keyPOST/v1/videos/generationsVideo generationAPI keyPOST/v1/videos/editsVideo editingAPI keyPOST/v1/videos/extensionsVideo extensionAPI keyGET/v1/videos/{request_id}Poll xAI video jobsAPI keyPOST/v1/music/generationsMusic generationAPI keyPOST/v1/audio/generationsAudio and SFX generationAPI keyPOST/v1/3d/generationsImage-to-3D GLB generationAPI keyPOST/v1/panoramas/generationsImage-to-360 panorama or spatial-world generationAPI keyPOST/v1/audio/speechText-to-speechAPI keyPOST/v1/audio/transcriptionsAudio transcriptionAPI keyPOST/v1/searchWeb and papers searchAPI keyPOST/api/audio/generateGenerate music or SFX and save to the indexed audio libraryAPI keyGET/api/audio/search?q=rainSemantic + keyword search over generated public/own audiopublicGET/api/audioList recent public/own generated audiopublicapp/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.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.
/api/agents/configOption lists for the agent formpublicPOST/api/agents/tasksLaunch an agent taskAPI keyGET/api/agents/tasksList your agent tasksAPI keyGET/api/agents/tasks/{id}Get a task with its current statusAPI keyGET/api/agents/tasks/{id}/eventsStep-by-step events and statusAPI keyPOST/api/agents/tasks/{id}/cancelCancel a running taskAPI keyPOST/api/agents/tasks/{id}/retryRetry a finished or failed taskAPI keyGET/api/agents/tasks/{id}/filesList files the agent changedAPI keyPUT/api/agents/tasks/{id}/files/{fileId}Edit a changed file before reviewAPI keyprompt*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 | xhigh | 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.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.
/api/agents/configSources + which are configured, plus models/enginespublicPOST/api/agents/tasksLaunch on any provider via the source fieldAPI keyGET/api/agents/tasksList your runs across all providersAPI keyGET/api/agents/tasks/{id}Normalized trace: steps, messages, diff, PRAPI keyPOST/api/agents/tasks/{id}/cancelCancel a running taskAPI keyopenpathssourceDefault. 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.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 traceLocal workers — run agent tasks on your own machines
Run `app worker` on any computer after `app login` and it becomes a private worker for your account: it polls app.nz, leases agent tasks created with provider "local", executes them with local engines (our codex fork with automatic fallback to mainline codex, claude, cursor-agent, gemini, grok), and reports steps/diffs/PRs into the normal task trace. Leasing is user-scoped: your workers authenticate every /api/worker call with your API key and only ever see jobs whose user matches your account; fleet workers use the shared X-Worker-Token and never lease provider=local jobs. Job payloads and logs pass through secret redaction, and only allowlisted engines execute. By default a local worker takes only your provider=local jobs; --any-provider opts it into all of your jobs.
/api/agents/workersList your registered machines with online state and activeJobssession/api/worker/registerWorker announces itself (Bearer API key for user workers; X-Worker-Token for the fleet)API key/api/worker/heartbeatLiveness + active job count; drives the online indicatorAPI key/api/worker/leaseAtomically claim the oldest runnable job you ownAPI key/api/worker/completeReport a leased job resultAPI key/api/worker/job-credsShort-lived credentials for a leased jobAPI key--name <name>stringMachine display name; defaults to the hostname.--dir <path>stringWorking directory for repo checkouts.--engines <list>stringComma-separated engine allowlist, e.g. codex,claude. Defaults to every installed engine.--any-providerbooleanAlso lease your non-local (cloud-queued) jobs, not just provider=local.--poll <dur>durationPoll interval for the lease loop.--lease <n>integerMax jobs to run concurrently.--oncebooleanLease at most one job, run it, exit (cron-friendly).--dry-runbooleanShow what would be leased and run without executing.app worker statuscommandList your machines, online state, and active jobs from the CLI.# on the machine that will do the coding
app login
app worker --name desktop --dir ~/agent-work --engines codex,claude
# from any device (or the /agent composer with provider "Your machine")
app agent run --prompt "add a /health endpoint with a test" \
--repo you/api --provider local --model app/auto-code
# see your machines (same data as the studio chips)
app worker status
curl -s https://app.nz/api/agents/workers -H "Authorization: Bearer pk_live_..."Artifacts API
Create, update, list, share, and delete user artifacts. Supported kinds are drawing, doc, sheet, pdf, image, and file. Documents store Markdown text and open in /write; sheets store JSON grid data and open in /sheets, so agents can produce editable office documents directly.
/api/artifactsList artifacts visible to you; optional ?kind=doc or ?kind=sheetAPI keyPOST/api/artifactsCreate an artifactAPI keyGET/api/artifacts/{id}Fetch one visible artifactAPI keyPUT/api/artifacts/{id}Update one of your artifactsAPI keyDELETE/api/artifacts/{id}Delete one of your artifactsAPI keyPOST/api/artifacts/{id}/shareCreate or rotate a public share tokenAPI keyDELETE/api/artifacts/{id}/shareRemove the public share tokenAPI keyGET/api/artifacts/shared/{token}Fetch a shared artifact by tokenpublickind*stringdrawing | doc | sheet | pdf | image | file.title*stringDisplay title.mimestringMIME type, e.g. text/markdown for doc or application/json for sheet.datastringInline data. Documents use Markdown; sheets use JSON grid data.urlstringOptional https:// or app-relative URL for binary artifacts.teamIdstringOptional team visibility scope.curl -sX POST https://app.nz/api/artifacts \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"kind":"doc","title":"Runbook","mime":"text/markdown","data":"# Runbook\n\nShip it."}'
curl -sX POST https://app.nz/api/artifacts \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"kind":"sheet","title":"Budget","mime":"application/json","data":"[{"name":"Sheet1","rows":{"0":{"cells":{"0":{"text":"Item"},"1":{"text":"Cost"}}}}}]"}'Media optimizer API
Cloudflare-style image resizing and AV1-first video re-encoding over your app.nz artifact filesystem. Optimize an existing artifact or a public HTTPS URL, save generated variants back into /artifacts, and serve best-size images through a dynamic URL that negotiates AVIF, WebP, JPEG, or PNG from the Accept header. The same optimizer is available as a Cog image for isolated GPU worker pools.
/api/media/optimizer/configOptimizer presets, encoder availability, and public pricing metadatapublicPOST/api/media/optimizer/estimateEstimate variants and credits without running an encodepublicPOST/api/media/optimizeGenerate image/video variants and save them into your artifact filesystemAPI keyPOST/v1/media/optimizationsOpenAI-style alias for POST /api/media/optimizeAPI keyGET/api/media/image/{artifact_id}Dynamic best-size image transform: ?w=640&format=auto&q=85API keyartifactIdstringSource artifact to read. Required unless url is supplied.urlstringPublic HTTPS source URL. Private/reserved network targets are rejected.kindstringimage | video. Inferred from MIME/extension when omitted.widthsint[]Image widths to generate. Default: [320,640,960,1280].heightsint[]Video ladder heights. Default: [360,720,1080].formatsstring[]Image: webp | avif | jpeg | png. Video: webm | av1 | mp4.qualityint1-100 quality target; defaults to 85 for images.outputPathstringArtifact directory for generated variants; defaults to /optimized.dryRunbooleanReturn the plan and estimated credits without encoding.# Save responsive image variants back into /artifacts.
curl -sX POST https://app.nz/api/media/optimize \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{
"artifactId": "artifact_123",
"kind": "image",
"widths": [320, 640, 1280],
"formats": ["webp"],
"outputPath": "/optimized"
}'
# Dynamic best-size image URL.
curl -L "https://app.nz/api/media/image/artifact_123?w=640&format=auto&q=85" \
-H "Authorization: Bearer pk_live_..."
# CLI equivalents.
app media optimize --artifact-id artifact_123 --width 640 --width 1280 --format webp
app media pricing
app builds media-optimizer-cogCharacter 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.
/api/search-ais?q=luna&limit=20Find characters by name, title, tags, or descriptionpublicGET/api/get-ai-by-name?name=lunaLoad one character by url_name or display namepublicPOST/api/charactersCreate a user-owned character and ingest text/Markdown docsAPI keyPATCH/api/characters/{url_name}Update your character and optionally replace indexed docsAPI keyPOST/api/assistant/chatsCreate a chat for a character with a chosen modelAPI keyPOST/api/assistant/chats/{id}/messagesSend a turn and stream the character replyAPI keyGET/api/assistant/chats/{id}Reload a chat and its active branchAPI keyname*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 | xhigh.content*stringMessage text for POST /messages.# 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?"}'Repos API — git & GitHub parity
GitHub-parity repo hosting on real bare git repositories: clone and push over standard git smart HTTP (git clone https://app.nz/{owner}/{name}.git), plus issues, pull requests with inline line-anchored review comments, a git-backed wiki, releases, labels, Actions-style secrets/variables, and branch-protection rulesets. Read endpoints (repo detail, git browsing, issues/pulls/releases/labels/rulesets, wiki) work with no key at all for public repos — the same code path renders the showcase browser for signed-out visitors — and need a key with read access (owner or a team member) for private ones. Everything that mutates state needs a key with write access, except fork and star, which only need any signed-in reader. Mentioning @agent (or @codex, @claude, @bot, /agent, /fix, /review) in a pull-request comment launches a coding agent on that PR's branch and posts a bot reply linking the task.
/api/reposList your reposAPI keyPOST/api/reposCreate a repo (name, description, visibility, org)API keyGET/api/repos/explorePublic repos for the showcase grid (?kind=code|dataset|model&sort=stars|recent)publicGET/api/repos/searchSearch public repos by name/description (?q=)publicGET/api/repos/lookup/{owner}/{name}Resolve owner/name to a repo (for pretty URLs)publicGET/api/repos/{id}Repo detail — issues, pulls, branches, recent commitspublicPATCH/api/repos/{id}Edit name, description, visibility, defaultBranch, imageUrlAPI keyDELETE/api/repos/{id}Archive (soft-delete) a repoAPI keyPOST/api/repos/{id}/forkFork into your namespace (real bare-git clone, full history)API keyGET/api/repos/{id}/starViewer’s star state and total countpublicPUT/api/repos/{id}/starStar the repoAPI keyDELETE/api/repos/{id}/starUnstar the repoAPI keyGET/api/repos/{id}/git/branchesList branchespublicGET/api/repos/{id}/git/treeDirectory listing (?ref=&path=&withCommits=1)publicGET/api/repos/{id}/git/pathsFlat file-path list for a fuzzy finder (?ref=)publicGET/api/repos/{id}/git/blobFile content, size, language, latest commit (?ref=&path=)publicGET/api/repos/{id}/git/rawRaw file bytes with a sniffed content-type (?ref=&path=)publicGET/api/repos/{id}/git/logCommit history (?ref=&path=&limit=)publicGET/api/repos/{id}/git/commit/{sha}Commit metadata plus its file diffpublicGET/api/repos/{id}/git/diffDiff and commit range between two refs (?base=&head=)publicGET/api/repos/{id}/git/readmeRendered README lookup for a ref/pathpublicGET/api/repos/{id}/git/searchCode search — semantic by default, ?mode=keyword for git grep (?q=&limit=)publicPOST/api/repos/{id}/branchesCreate a branch (name, from)API keyPOST/api/repos/{id}/commitsRecord a commit entry (branch, message) — bookkeeping only, not a real git commitAPI keyGET/api/repos/{id}/issuesList issues (?state=open|closed|all)publicGET/api/repos/{id}/issues/{number}Issue detail with its comment threadpublicPOST/api/repos/{id}/issuesOpen an issue (title, body)API keyPATCH/api/repos/{id}/issues/{number}Set state (state: open|closed)API keyPOST/api/repos/{id}/issues/{number}/commentsComment on an issue (body)API keyGET/api/repos/{id}/pullsList pull requests (?state=open|closed|all)publicGET/api/repos/{id}/pulls/{number}Pull request detail with its comment threadpublicPOST/api/repos/{id}/pullsOpen a PR (title, body, sourceBranch, targetBranch)API keyPATCH/api/repos/{id}/pulls/{number}Set state (state: open|closed|merged — merged performs a real git fast-forward or merge commit)API keyGET/api/repos/{id}/pulls/{number}/commentsList PR comments, including line-anchored review commentspublicPOST/api/repos/{id}/pulls/{number}/commentsPost a PR comment, optionally anchored to a diff line (body, filePath, lineStart, lineEnd, side)API keyGET/api/repos/{id}/wikiList wiki pagespublicGET/api/repos/{id}/wiki/pages/{slug}Get a wiki pagepublicGET/api/repos/{id}/wiki/pages/{slug}/historyPage history from the wiki git repopublicGET/api/repos/{id}/wiki/searchSearch wiki pages (?q=)publicPUT/api/repos/{id}/wiki/pages/{slug}Create or update a page (title, body, message)API keyDELETE/api/repos/{id}/wiki/pages/{slug}Delete a pageAPI keyGET/api/repos/{id}/releasesList releasespublicGET/api/repos/{id}/releases/{tag}Get one releasepublicPOST/api/repos/{id}/releasesCreate a release (tag, name, body, target, prerelease, draft)API keyPATCH/api/repos/{id}/releases/{tag}Update a releaseAPI keyDELETE/api/repos/{id}/releases/{tag}Delete a releaseAPI keyGET/api/repos/{id}/labelsList labelspublicPOST/api/repos/{id}/labelsCreate a label (name, color, description)API keyDELETE/api/repos/{id}/labels/{name}Delete a labelAPI keyGET/api/repos/{id}/secretsList secret names — values are write-only and never returnedAPI keyPOST/api/repos/{id}/secretsSet a secret (name, value)API keyDELETE/api/repos/{id}/secrets/{name}Delete a secretAPI keyGET/api/repos/{id}/variablesList variables (values are readable)API keyPOST/api/repos/{id}/variablesSet a variable (name, value)API keyDELETE/api/repos/{id}/variables/{name}Delete a variableAPI keyGET/api/repos/{id}/rulesetsList branch-protection rulesetspublicPOST/api/repos/{id}/rulesetsCreate a ruleset (name, targetBranch, requirePr, requireChecks, blockForcePush)API keyDELETE/api/repos/{id}/rulesets/{name}Delete a rulesetAPI keyhttps://app.nz/{owner}/{name}.git/info/refsgit clone/pull ref advertisement (git clone https://app.nz/{owner}/{name}.git)publichttps://app.nz/{owner}/{name}.git/git-receive-packgit push — HTTP Basic auth, an API key as the passwordAPI keyreadlevelAnyone, for public repos; owner + team viewers for private ones. Covers repo detail, git browsing, issues/pulls/releases/labels/rulesets, and wiki reads.writelevelOwner, global admins, or a team member/admin on the repo’s governing org. Required for branches, commits, issues, pulls, wiki writes, labels, secrets, variables, rulesets, releases.fork / starlevelAny signed-in reader — no write access required.adminlevelOwner or global admin. Required to edit or delete the repo itself.# Create the repo (private by default)
curl -sX POST https://app.nz/api/repos \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"my-app","description":"demo","visibility":"public"}'
# -> {"repo":{"id":"repo_...","fullName":"you/my-app",...}}
# Real git — clone/push over smart HTTP, an API key as the Basic-auth password
git clone https://app.nz/you/my-app.git
cd my-app && git checkout -b feature/x && git commit --allow-empty -m x
git push https://token:[email protected]/you/my-app.git feature/x
# Open a PR against main
curl -sX POST https://app.nz/api/repos/repo_.../pulls \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"title":"Add feature x","sourceBranch":"feature/x","targetBranch":"main"}'
# @mention an agent on the PR thread — it launches on the PR branch and replies
curl -sX POST https://app.nz/api/repos/repo_.../pulls/1/comments \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"body":"@agent add input validation and a test for the empty case"}'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.
/api/sitesList your sitesAPI keyPOST/api/sitesCreate a site (seeds a starter)API keyGET/api/sites/{id}Get a site with its filesAPI keyDELETE/api/sites/{id}Delete a siteAPI keyPUT/api/sites/{id}/filesCreate or update a file (publishes)API keyDELETE/api/sites/{id}/files?path=app.jsDelete a fileAPI key/sites/{slug}/{path}Public serving — no auth, defaults to index.htmlpublichttps://{slug}.app.nz/{path}Public serving on the site’s own subdomain (SPA-friendly)publicslug*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.# 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>"}'Cogs API — GPU model hosting
Run an arbitrary Cog (Replicate-style) container as an autoscaling, scale-to-zero GPU inference endpoint. Register a model once (image, hardware, optional input schema); the first prediction cold-starts a GPU pod (RunPod on-demand instances under the hood, or free local GPU headroom when the host opts in), proxies to the container’s /predictions endpoint, and an idle reaper scales it back to zero — an idle model costs nothing. Every prediction is billed at machine time times the same platform markup used across app.nz. GET /api/cogs/config is public so the studio can render before sign-in. One-click deploy: link (or badge) any cog with https://app.nz/deploy?image=…&name=…&hardware=… — the studio opens pre-filled, one press to register. Media in and out ride the JSON body as data: URIs or https URLs, so audio-to-audio models work first-class: the audex-s2s template (NVIDIA Nemotron-Labs-Audex-2B, open source at replicatecog/audex) takes a spoken turn and returns transcript, reply text, and reply audio in one prediction — it powers /spaces/audio-to-audio.
/api/cogs/configGPU hardware catalogue, starter templates, output kinds, markuppublicGET/api/cogsList your registered modelsAPI keyPOST/api/cogsRegister a model (name, image, hardware, schema, idleSeconds, minVramGb)API keyGET/api/cogs/{id}Model detail plus its 20 most recent predictionsAPI keyDELETE/api/cogs/{id}Delete a model (tears down any warm pod first)API keyPOST/api/cogs/{id}/warmProactively cold-start the podAPI keyPOST/api/cogs/{id}/sleepScale the model to zero nowAPI keyPOST/api/cogs/{id}/predictRun a prediction asynchronously (input) — poll for the resultAPI keyGET/api/cogs/{id}/predictionsList a model’s recent predictions (up to 50)API keyGET/api/cogs/predictions/{id}Poll a prediction by id — status, output, cost, timingAPI keyname*stringModel display name.image*stringContainer image, e.g. r8.im/owner/model or your own registry image.hardwarestringA GPU machine id (gpu-t4, gpu-rtx3090, gpu-rtx4090, gpu-a40, gpu-l40s, gpu-a100, gpu-h100), or "auto"/omitted to pick the cheapest GPU that fits minVramGb.schemaobjectOptional { inputs: [{name,type,description,default,required,choices,min,max,order}], outputKind }. Omitted schemas are introspected from the container’s /openapi.json on first warm-up.idleSecondsintegerIdle window before scale-to-zero (default 120).minVramGbintegerModel’s VRAM floor, used for auto hardware selection.curl -sX POST https://app.nz/api/cogs \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"fast-vfx","image":"r8.im/lee101/fast-vfx","hardware":"gpu-rtx4090"}'
# -> {"model":{"id":"cog_...","status":"idle",...}}
curl -sX POST https://app.nz/api/cogs/cog_.../predict \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"input":{"video":"https://example.com/clip.mp4","num_levels":25}}'
# -> {"prediction":{"id":"pred_...","status":"starting"}}
# Poll for the result (a cold start can take a couple of minutes)
curl -s https://app.nz/api/cogs/predictions/pred_... \
-H "Authorization: Bearer pk_live_..."
# Audio-to-audio (audex-s2s template): one spoken turn per prediction
curl -sX POST https://app.nz/api/cogs/cog_.../predict \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"input":{"task":"converse","audio":"data:audio/webm;base64,...","system_prompt":"You are a cheerful pirate captain."}}'
# -> output: {"transcript":"...","response_text":"...","audio":"data:audio/mpeg;base64,..."}Notebooks & datasets
Hosted marimo notebooks run free in the browser (Pyodide) or on per-minute cloud machines that stop when idle. Datasets accept csv, json, jsonl (agent traces auto-detected), parquet, sqlite .db files, images, and browser-playable video; binary formats stream from the CDN and table previews open in the Sheets editor. Machine rates include the platform margin — what /api/notebooks/pricing returns is what you pay.
/api/notebooksList your notebooks plus public examplesAPI keyPOST/api/notebooksCreate a notebook ({name, source?, forkOf?})API keyGET/api/notebooks/{slug}Fetch a notebook with its marimo sourceAPI keyPUT/api/notebooks/{slug}Update name, source, visibility, runtimeAPI keyDELETE/api/notebooks/{slug}Delete a notebook (stops its sessions)API keyGET/api/notebooks/{slug}/sessionsList cloud sessions with status and endpointAPI keyPOST/api/notebooks/{slug}/sessionsStart a cloud session ({machineType}), billed per minuteAPI keyDELETE/api/notebooks/sessions/{id}Stop a session and settle billingAPI keyGET/api/notebooks/pricingMachine catalogue with hourly/credit rates and storage pricingpublicPOST/api/datasets/uploadUpload a table, database, image, or video datasetAPI keyGET/api/datasets/u/{id}/notebookGenerated marimo starter notebook for a datasetAPI keycurl -sX POST https://app.nz/api/notebooks \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"fraud analysis"}'
curl -sX POST https://app.nz/api/notebooks/nb-1a2b3c4d/sessions \
-H "Authorization: Bearer pk_live_..." \
-d '{"machineType":"gpu-rtx3090"}'
# -> {"session":{"id":"...","status":"provisioning","priceHourly":"$0.264"}}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.
/api/pricingUsage-based pricing: model token rates, compute, search, credit unitpublicGET/api/plansList plan catalog (price, credits, machines, quotas)publicGET/api/plans/meYour plan, credit balance, and product quota usageAPI keyPOST/api/plans/subscribeStart a Pro/Ultra/Max checkoutsessionPOST/api/plans/cancelCancel at period endsessionPOST/api/plans/portalOpen the Stripe billing portalsessionGET/api/credits/balancePrepaid credit balance + auto-topupAPI keyPOST/api/credits/checkoutBuy credit packssessionPOST/api/credits/autotopupConfigure automatic top-upssessionfreeplan$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.# 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 usagePayments — let your app earn
Accept payments in anything you build on app.nz. Under the hood it is Stripe Connect with direct charges: you are the merchant of record on your own connected account, Stripe handles KYC/verification and risk, and app.nz white-labels the whole experience. You pay one flat retail rate per plan (Free 5% + 30¢, Pro 4%, Ultra 3.5%, Max 3% — see /api/payments/config), collected automatically as an application fee on each charge. Standard payouts are free; instant payouts cost 1.5% (min 50¢). Earnings can be converted into app.nz credits so an app that earns pays for its own hosting.
/api/payments/configFee schedule per plan, limits, instant-payout pricingpublicPOST/api/payments/enableCreate your payment account; returns a hosted onboarding linkAPI keyGET/api/payments/accountOnboarding status: chargesEnabled, payoutsEnabled, your fee rateAPI keyPOST/api/payments/checkoutSell: one-time or recurring checkout; returns a Stripe-hosted payment urlAPI keyGET/api/payments/salesList checkouts with paid totals and feesAPI keyGET/api/payments/balanceAvailable / pending / instant-eligible balanceAPI keyPOST/api/payments/payoutPay out to your bank; {"instant": true} arrives in ~30 min for a feeAPI keyPOST/api/payments/offsetConvert earnings into app.nz credits (1¢ = 10 credits) to pay hostingAPI keyPOST/api/payments/settingsToggle automatic hosting offsetAPI key/api/payments/webhookStripe Connect webhook receiver (platform-facing)publicamount*intUnit price in cents (50 – 5,000,000).descriptionstringWhat the customer is buying; shows on the checkout page.recurringstringOmit for one-time; "month"/"year"/"week"/"day" for a subscription.currencystringISO currency, default usd.quantityintLine-item quantity, default 1.successUrlstringWhere the buyer lands after paying (your app).cancelUrlstringWhere the buyer lands if they abandon checkout.metadataobjectYour own keys (order id, plan) echoed back on the sale.# One-time setup: onboard (opens Stripe-hosted KYC, bank account)
app payments enable --country NZ --description "Pro subscriptions"
# From your app's server (never expose the key in browser code):
curl -sX POST https://app.nz/api/payments/checkout \
-H "Authorization: Bearer $APP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 2900, "description": "Pro plan", "recurring": "month",
"successUrl": "https://myapp.app.nz/thanks"}'
# → redirect the buyer to the returned "url"
app payments sales # who paid
app payments balance # available / pending / instant
app payments payout --amount 100.00 --instant # ~30 min, 1.5% fee
app payments offset --amount 50.00 # $50 earnings → 50,000 hosting creditsOpen animation and spatial asset API
Search the public motion, VFX, terrain, procedural-object, and image-to-3D index by stable ID. Agents can inspect source and license metadata, download portable JSON recipes, fetch OBJ meshes, build deterministic terrain, or prepare an image reconstruction job without parsing the web gallery.
/api/animation-librarySearch the indexed asset manifest with q, kind, and limitpublicGET/api/animation-library/index.jsonFetch the complete cacheable index for offline agent searchpublicGET/api/animation-library/{id}/download?format=jsonDownload a recipe; use format=obj for terrain and 3D objectspublicPOST/api/animation-library/terrainBuild a deterministic terrain recipepublicPOST/api/animation-library/image-to-3dBuild an image-to-3D reconstruction recipepublicPOST/v1/3d/generationsRun an authenticated 3D generation job from image or text inputAPI keyqstringSubstring matched against stable id, name, description, and tags.kindenumpose, motion, vfx, terrain, object, or image3d.formatenumjson for every asset; obj for terrain, object, and image3d.target_polycountintegerRequested reconstruction budget, clamped to 500,000.# Find downloadable image-to-3D assets
curl -s 'https://app.nz/api/animation-library?q=product&kind=image3d&limit=10' | jq
# Download portable geometry
curl -L 'https://app.nz/api/animation-library/image3d-sneaker/download?format=obj' -o sneaker.obj
# Equivalent CLI flow
app animation search product --kind image3d
app animation download image3d-sneaker --format obj --output sneaker.obj
# MCP tools: search_animation_library, download_animation_asset,
# create_image_to_3d_recipe, generate_terrain_recipeFirst-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.
/api/ra1/generateGenerate images with RA1 — prompt, count, aspect, style, negative (50 credits each)API keyGET/api/ra1/statusPoll a queued render by jobId for status + image URLsAPI keyGET/api/papers/searchSearch 200M+ papers (1 credit each)API keyPOST/api/searchAgentic web search (10 credits per depth)API keyPOST/api/packing/solve3D bin packing — container + items in, placements/utilization/unplaced out (free)publicapp 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 2Conventions
- • 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".