endpoint
PUT

/api/sites/{id}/files

Create or update a file (publishes)

auth: API keybase https://app.nz
Request
curl -sX PUT https://app.nz/api/sites/{id}/files \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{}'

Sites API

Publish a static app at <slug>.app.nz. Create with AI or upload a ZIP in the web UI, deploy a folder with `app sites deploy my-site ./dist`, or use the API below. Static publishing needs no funds. Files publish immediately; each file can be up to 64 MB.

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
bun 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>"}'