Skip to content
For developers

API & tokens

Prefer to publish from code? Tokens let scripts, pipelines, and agents act on your account without your password. Each one is scoped, shown once, and revocable in a click.

Create a token

Open API tokens under your account settings and create a new token. Give it a name you will recognize later, then copy the value right away. For security we show it only once, so store it in your secret manager or a CI secret.

A token is yours, not a workspace’s. Over MCP it reaches your personal space and every workspace you belong to (the AI passes a workspace_id); the REST API below publishes into your personal space.

Publish a site

Send the bundle as multipart form data along with a title and visibility. The bundle field takes a .zip, a single HTML page, or a single file of any rendered kind (.md, .ipynb, .pdf, .docx, .pptx, .xlsx, .csv, .mmd, an image, a video, an audio or a text file) under its own name. The response includes the site id and its live link.

POST /v1/sites
curl -X POST https://app.snaphost.ai/api/v1/sites \
  -H "Authorization: Bearer $SNAPHOST_TOKEN" \
  -F "title=Launch microsite" \
  -F "visibility=private" \
  -F "bundle=@site.zip"

Update in place

Push a new bundle to the same site id and the live link stays the same. Viewers see the update on their next load, with no new link to share.

PUT /v1/sites/:id
curl -X PUT https://app.snaphost.ai/api/v1/sites/$SITE_ID \
  -H "Authorization: Bearer $SNAPHOST_TOKEN" \
  -F "bundle=@site.zip"

Large bundles

A request body is capped at a few megabytes, so a bundle with video, audio, or many images is uploaded first and published by reference. Start an upload, PUT the .zip to the returned upload_url on SnapHost itself, then publish with the upload_id. Above max_part_bytes (4 MB), split the file and PUT each piece to upload_url/parts/0, /parts/1, and so on in order. The response also carries a presigned url straight to storage, which takes the whole bundle in one request if your network can reach that host. An upload is single use and expires after 15 minutes.

POST /v1/uploads
# 1. Start an upload: returns upload_id, upload_url, max_part_bytes, and a presigned url
curl -X POST https://app.snaphost.ai/api/v1/uploads \
  -H "Authorization: Bearer $SNAPHOST_TOKEN"

# 2. PUT the bundle to upload_url (whole, up to max_part_bytes)
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/zip" \
  --data-binary @site.zip

#    ...or, for a bigger bundle, as numbered parts in order
split -b 4m site.zip part-
i=0; for f in part-*; do
  curl -X PUT "$UPLOAD_URL/parts/$i" -H "Content-Type: application/zip" --data-binary "@$f"
  i=$((i+1))
done

# 3. Publish (or PUT /sites/:id) with the upload_id instead of a bundle file
curl -X POST https://app.snaphost.ai/api/v1/sites \
  -H "Authorization: Bearer $SNAPHOST_TOKEN" \
  -F "title=Launch microsite" \
  -F "upload_id=$UPLOAD_ID"

# A single file that is not a zip (Markdown, a notebook, a PDF, a video, a CSV) travels the same way,
# PUT as its own bytes. Open the upload with its name so it is rendered as its kind rather than
# served as a page (or pass filename= on the publish instead):
#   curl -X POST .../api/v1/uploads -H "Authorization: Bearer $SNAPHOST_TOKEN" \
#     -H "Content-Type: application/json" -d '{"filename":"talk.mp4"}'
#   curl -X PUT "$UPLOAD_URL" -H "Content-Type: video/mp4" --data-binary @talk.mp4
#   curl -X POST .../api/v1/sites -F "title=Talk" -F "upload_id=$UPLOAD_ID"
# A Word, PowerPoint or Excel file is shown as its page alone; add -F "include_original=true"
# (on POST /sites and on PUT /sites/:id/content alike) to let readers download the file itself,
# its notes, hidden sheets, formulas, comments and tracked changes included. Both answer with
# original_included and render_notices.

Keep tokens safe

Treat a token like a password. Never commit it to source control or embed it in a client. Rotate tokens on a schedule, and revoke any token immediately if it might have leaked. Revoking takes effect at once.