API Reference

Publish files to the web with a single API call. No build step, no config, no waiting.

Quick Start

The fastest way to get a site live. Send your file contents inline and get a URL back instantly.

Request
curl -X POST https://onepu.sh/api/v1/push \
  -H "Content-Type: application/json" \
  -d '{"files": {"index.html": "<h1>Hello World</h1>"}}'
Response
{
  "url": "https://swift-cloud-fox.onepu.sh",
  "slug": "swift-cloud-fox",
  "updateToken": "tok_abc123...",
  "claimUrl": "https://onepu.sh/claim/abc123...",
  "expiresIn": "24 hours"
}

That's it. Your site is live. Anonymous sites expire in 24 hours — share the claimUrl with the user so they can keep it permanently.

Authentication

Authentication is optional. Without it, sites are anonymous and expire in 24 hours. With an API key, sites are permanent.

Getting your API key

Sign in at onepu.sh/dashboard/settings to find your API key. It starts with sk_.

Using it

Option 1 (header): Authorization: Bearer sk_your_api_key_here

Option 2 (body field): "apiKey": "sk_your_api_key_here"

If your HTTP client can't set custom headers, include apiKey in the JSON request body instead.

POST /api/v1/push

Single-call publish. Send file contents inline (up to 10MB total). Best for agent-generated HTML, dashboards, and reports.

Request body

FieldTypeRequiredDescription
filesobjectYesMap of filename → content string. e.g. {"index.html": "<h1>Hi</h1>"}
slugstringNoCustom slug (3-64 chars, lowercase, hyphens). Auto-generated if omitted.
urlstringNoLive URL of a site to update (e.g. "https://handle.onepu.sh/path"). Resolves to the correct slug automatically.
updateTokenstringNoToken from a previous push response. Required to update anonymous sites.
apiKeystringNoAPI key (sk_...) as alternative to Authorization header. Use if your HTTP client can't set custom headers.
namestringNoDisplay name. Defaults to slug.

Response

FieldDescription
urlLive URL of the published site
slugThe site's unique slug
updateTokenSave this — needed to update the site later
claimUrlURL to claim ownership (anonymous only)
expiresIn"24 hours" (anonymous only)

Authenticated example

Include your API key to make sites permanent. No claim step needed.

Request
curl -X POST https://onepu.sh/api/v1/push \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{
    "files": {
      "index.html": "<html>...</html>",
      "style.css": "body { font-family: sans-serif; }"
    },
    "name": "My Dashboard"
  }'
Response — no claimUrl or expiresIn
{
  "url": "https://bold-creek-owl.onepu.sh",
  "slug": "bold-creek-owl",
  "updateToken": "tok_xyz789..."
}

POST /api/v1/publish

For large files or binary assets (images, fonts, PDFs), use the presigned upload flow. This supports files up to 250MB each.

Three steps: create site and get upload URLs → upload files directly → finalize to go live.

Three-step flow
# Step 1: Create site and get upload URLs
curl -X POST https://onepu.sh/api/v1/publish \
  -H "Content-Type: application/json" \
  -d '{
    "files": [
      {"path": "index.html", "size": 2048, "contentType": "text/html"},
      {"path": "logo.png", "size": 51200, "contentType": "image/png"}
    ]
  }'

Claiming anonymous sites

When you publish without authentication, the response includes a claimUrl. This is a one-time link that lets the user enter their email and take permanent ownership of the site.

After claiming, the site appears in their dashboard, the 24-hour expiry is removed, and they get an API key for future publishes.

Important: The claim token is returned only once and cannot be recovered. Make sure to show the claimUrl to the user.

Versioning

Every publish creates a new version. Previous versions are preserved and can be restored from the dashboard or via the API.

Updating a site

To update an existing site, you can authenticate with an API key, or pass the updateToken from the original push response. Use slug or url to identify the site.

Update an existing site
# Option 1: By slug with API key
curl -X POST https://onepu.sh/api/v1/push \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{"slug": "my-existing-site", "files": {"index.html": "..."}}'

# Option 2: By live URL (resolves handle URLs automatically)
curl -X POST https://onepu.sh/api/v1/push \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{"url": "https://myhandle.onepu.sh/project", "files": {"index.html": "..."}}'

# Option 3: By slug with updateToken (no API key needed)
curl -X POST https://onepu.sh/api/v1/push \
  -H "Content-Type: application/json" \
  -d '{"slug": "my-existing-site", "updateToken": "tok_abc...", "files": {"index.html": "..."}}'

# Response
{
  "url": "https://my-existing-site.onepu.sh",
  "slug": "my-existing-site",
  "version": 2,
  "updated": true,
  "updateToken": "tok_abc..."
}

Handle URLs vs Slug URLs

Some sites use handle URLs like handle.onepu.sh/path where the subdomain is a username, not a site slug. To update these, use the urlfield with the full live URL — the API resolves it to the correct site automatically. Do not use the handle as a slug.

Restoring a version

Restore any previous version via the dashboard or the API. Restoring copies the old version's files into a new version, so nothing is lost.

Restore a version
curl -X POST https://onepu.sh/api/v1/sites/my-site/restore \
  -H "Content-Type: application/json" \
  -H "Cookie: sb-access-token=..." \
  -d '{"version": 1}'

# Response
{
  "restored": true,
  "fromVersion": 1,
  "newVersion": 3
}

Site settings

Update a site's name, visibility, or password protection via the settings endpoint. Requires authentication as the site owner.

Access levels

ValueDescription
publicVisible to everyone (default)
passwordRequires a password to view
teamOnly visible to team members
draftOnly visible to the site owner

Updatable fields

FieldTypeDescription
namestringDisplay name for the site
access_levelstringpublic, password, team, or draft
password_hashstringPassword for protected sites
handle_pathstringPath under your handle (e.g. /projects/demo)
Update site settings
# Set a site to password-protected
curl -X PATCH https://onepu.sh/api/v1/sites/my-site/settings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{"access_level": "password", "password_hash": "my-secret"}'

# Set a site to draft (only you can see it)
curl -X PATCH https://onepu.sh/api/v1/sites/my-site/settings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{"access_level": "draft"}'

# Rename a site
curl -X PATCH https://onepu.sh/api/v1/sites/my-site/settings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{"name": "My Awesome Project"}'

# Response
{"ok": true}

Deleting sites

Permanently delete a site, all its versions, and associated files. This action cannot be undone. Requires authentication as the site owner.

Delete a site
curl -X DELETE https://onepu.sh/api/v1/sites/my-site/settings \
  -H "Authorization: Bearer sk_your_api_key"

# Response
{"ok": true}

Warning: Deletion is permanent. All versions, team members, and files will be removed immediately.

All endpoints

MethodEndpointAuthDescription
POST/api/v1/pushOptionalSingle-call publish (inline content)
POST/api/v1/publishOptionalCreate site with presigned upload URLs
POST/api/v1/publish/:slug/finalizeNoneMark a version as live
PUT/api/v1/publish/:slugRequiredUpdate an existing site (new version)
GET/api/v1/publishRequiredList your sites
GET/api/v1/publish/:slugNoneGet site details
DELETE/api/v1/publish/:slugRequiredDelete a site
GET/api/v1/claim/:tokenNoneValidate a claim token
POST/api/v1/claim/:tokenNoneClaim a site with email
POST/api/v1/sites/:slug/restoreRequiredRestore a previous version
PATCH/api/v1/sites/:slug/settingsRequiredUpdate site settings
DELETE/api/v1/sites/:slug/settingsRequiredDelete a site permanently

Limits

AnonymousFree (authenticated)
SitesUnlimited (24h expiry)10 sites
Storage10MB inline / 250MB presigned1 GB total
Expiry24 hoursPermanent
AnalyticsPage viewsPage views
TeamsInvite members
Custom handleyourname.onepu.sh

Agent setup

Copy these instructions into your AI agent's system prompt or project config. This is all the agent needs to publish sites on your behalf.

Copy this into your agent's instructions
When asked to publish or deploy something to the web, use OnePush.

POST https://onepu.sh/api/v1/push
Content-Type: application/json

{"files": {"index.html": "<!DOCTYPE html><html>...</html>", "style.css": "..."}}

Response: {"url": "https://your-site.onepu.sh", "claimUrl": "https://onepu.sh/claim/..."}

Show the user the live URL. If they want to keep it, share the claimUrl
so they can enter their email and claim permanent ownership.

If you can't make HTTP requests, open https://onepu.sh/new in the browser instead.

Docs: https://onepu.sh/docs