---
title: "Publish a web page or static site"
method: POST
path: "/sites"
tags: ["Uploads"]
---

# Publish a web page or static site

`POST /sites`

## Request

- Base URL: `https://putit.online/api/v1`
- URL: `https://putit.online/api/v1/sites`
- Auth: one of:
  - none
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://putit.online/oauth/authorize`, token URL `https://putit.online/oauth/token`, scopes: `links:read`, `links:write`, `account:read`)

Put a page or small site online from a map of path to content. index.html is required.

## Request body

- object
  - `files` object, required: Map of path -> text content, e.g. {"index.html": "<!doctype html>…", "style.css": "body{…}"}. Must include index.html.
  - `base64_files` object: Optional map of path -> base64 content for binary assets such as images.
  - `title` string: Name for the site (shown in the dashboard).
  - `slug` string: Custom link name (3-40 letters, digits, dashes); available on plans with custom names.
  - `password` string: Visitors must enter this password to open the link; available on plans with password protection.

## Response `201`

OK

- object
  - `slug` string, required
  - `url` string, required: The public link to share.
  - `status` 'awaiting_upload' | 'checking' | 'live' | 'in_review' | 'unpublished' | 'publishing' | 'removed' | 'expired' | 'deleted', required: checking = not live yet (poll get_link); live = shareable; unpublished = not published; publishing = will be live soon (poll get_link); in_review = not available right now; removed = removed by moderation (see removed_reason, appeal_url).
  - `status_message` string, required
  - `content_url` string: Only when live, for sites and single files: where the content itself is served (https://<slug>.putitcdn.com/…). Share `url` instead; it always works.
  - `checkout_url` string: Only with status unpublished: the page where the uploader can publish this link.
  - `removed_reason` string: Only with status removed: why, in plain words.
  - `removed_category` string, nullable: Only with status removed: the moderation category (malware, phishing, explicit, …); null when not disclosed.
  - `appeal_url` string: Only with status removed: mailto link to appeal to abuse@putit.online.
  - `kind` string, required: html | site | file | bundle | pending
  - `title` string, required
  - `size_bytes` number, required
  - `file_count` number, required
  - `views` number, nullable, required: View count; null when the link's account plan has no view counts, or the link has no account.
  - `permanent` boolean, required
  - `password_protected` boolean, required
  - `created_at` string, required
  - `expires_at` string, nullable, required: ISO time the link stops working; null for permanent links.
  - `manage_url` string: Private page to manage/delete the link. Only returned on creation; keep it secret.
  - `manage_token` string: Secret token returned on creation for every new link (keep it secret). Anonymous callers pass it to get_link/delete_link; a link in an account is managed by that account instead.

## Other responses

- `400`: Invalid request
- `401`: Authorization required or token invalid
- `402`: Subscription required (see upgrade_url)
- `403`: Blocked: VPN/proxy, banned uploader or missing scope
- `422`: Rejected by the safety check
- `429`: Rate limited (see Retry-After)

---

[API](https://skmtc.dev/putit/apis/put-it-online-api.md) · [All operations](https://skmtc.dev/putit/apis/put-it-online-api/llms.txt) · [OpenAPI document](https://skmtc.dev/putit/apis/put-it-online-api/revisions/a0c9fe8d4301?raw)
