The Share HTML REST API publishes HTML and manages the pages and API keys associated with a Share HTML account. All endpoints are versioned under /api/v1; responses are JSON.
Base URL - https://share-html.com/api/v1
Authentication#
The API uses a single credential: an account-scoped API key, sent as a bearer token.
| Credential | Header | Format | Scope | Lifetime |
|---|---|---|---|---|
| API key | Authorization: Bearer … | sh_live_ + 48 hex characters | Every page owned by the calling account | Long-lived. Create and revoke at share-html.com/app/keys. |
Every endpoint requires the API key except GET /pages/{slug}, which is public. Publishing without an account is available only in the browser editor - it is a first-party convenience, not part of this API.
Rate limits#
Authenticated operations are limited per account; the public read is limited per client IP. All buckets are one-hour rolling windows.
| Operation | Limit |
|---|---|
POST /pages | 200 / hour per account |
PATCH /pages/{slug} | 200 / hour per account |
DELETE /pages/{slug} | 200 / hour per account |
GET /me/* | 200 / hour per account |
GET /pages/{slug} | 600 / hour per IP |
When a limit is exceeded the API returns 429 rate_limited with a Retry-After: 3600 header.
Errors#
Every error response shares the same envelope. Validation failures additionally carry a details array of field issues.
{
"error": {
"code": "bad_request",
"message": "Validation failed",
"details": [{ "path": "ttl", "message": "Invalid enum value" }]
}
}
| HTTP | code | Meaning |
|---|---|---|
| 400 | bad_request | Request body is not valid JSON or fails schema validation. |
| 401 | unauthorized | A bearer credential is required but was missing or unrecognized. |
| 403 | forbidden | The API key is valid but is not associated with a user account. |
| 404 | not_found | The page does not exist. Also returned when an API key authenticates successfully but does not own the requested page - ownership and existence are intentionally indistinguishable from the caller's perspective. |
| 409 | conflict | The request would violate a uniqueness or self-revocation rule. |
| 413 | payload_too_large | The HTML body exceeds the 5 MB limit. |
| 429 | rate_limited | A rate-limit bucket is full. Retry after the Retry-After interval. |
| 500 | internal | An unexpected server error occurred. |
Create a page#
POST/api/v1/pages
Publishes an HTML document and returns its public URL and slug.
Authentication - Required. Authorization: Bearer sh_live_…. The page is associated with the calling account.
Body parameters#
| Field | Type | Required | Description |
|---|---|---|---|
html | string | yes | Full HTML document. 1 byte to 5 MB. |
slug | string | no | Custom slug. 4 to 40 characters, lowercase alphanumeric plus -. Defaults to an 8-character slug from an alphabet that excludes ambiguous characters (no 0, 1, i, l, o). |
ttl | enum | no | "24h", "7d", "30d", or "never". Defaults to "never". |
password | string | no | Password gate. 1 to 128 characters. |
Request#
curl -X POST https://share-html.com/api/v1/pages \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<!DOCTYPE html><h1>Launch notes</h1>",
"slug": "launch-notes",
"ttl": "30d"
}'
const res = await fetch("https://share-html.com/api/v1/pages", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
html: "<!DOCTYPE html><h1>Launch notes</h1>",
slug: "launch-notes",
ttl: "30d",
}),
});
const { url, slug } = await res.json();
import requests
res = requests.post(
"https://share-html.com/api/v1/pages",
headers={"Authorization": f"Bearer {api_key}"},
json={
"html": "<!DOCTYPE html><h1>Launch notes</h1>",
"slug": "launch-notes",
"ttl": "30d",
},
)
data = res.json()
Response201#
{
"url": "https://pages.share-html.com/launch-notes",
"slug": "launch-notes"
}
Errors#
Get page metadata#
GET/api/v1/pages/{slug}
Returns non-secret metadata for a page. The HTML body itself is served at https://pages.share-html.com/{slug} and is not exposed through the REST API.
Authentication - None. Anyone with the slug can read its metadata.
Path parameters#
| Field | Type | Description |
|---|---|---|
slug | string | The slug returned by POST /pages. |
Request#
curl https://share-html.com/api/v1/pages/launch-notes
Response200#
{
"slug": "launch-notes",
"url": "https://pages.share-html.com/launch-notes",
"title": "Launch notes",
"owner": "user",
"size_bytes": 4217,
"has_password": false,
"discoverable": false,
"view_count": 132,
"expires_at": null,
"created_at": "2026-05-12T09:31:00.000Z",
"updated_at": "2026-05-19T14:02:00.000Z"
}
owner is "anonymous" or "user". title is extracted from the HTML at publish time and may be null. expires_at is null when ttl is "never". discoverable mirrors the indexing hint set on the page.
Errors#
Update a page#
PATCH/api/v1/pages/{slug}
Updates one or more fields on a page owned by the calling account. Any field omitted from the body is left unchanged. Sending "password": null clears an existing password gate.
Authentication - Required. Authorization: Bearer sh_live_….
Path parameters#
| Field | Type | Description |
|---|---|---|
slug | string | The slug to update. |
Body parameters#
At least one field is required.
| Field | Type | Description |
|---|---|---|
html | string | Replacement HTML document. 1 byte to 5 MB. |
ttl | enum | "24h", "7d", "30d", or "never". |
password | string | null | New password (1 to 128 characters), or null to clear an existing password. |
discoverable | boolean | Whether the page is included in search indexing hints. Defaults to false at publish time. |
Request#
curl -X PATCH https://share-html.com/api/v1/pages/launch-notes \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<!DOCTYPE html><h1>Launch notes - v2</h1>"}'
await fetch(`https://share-html.com/api/v1/pages/${slug}`, {
method: "PATCH",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ html: "<!DOCTYPE html><h1>Launch notes - v2</h1>" }),
});
import requests
requests.patch(
f"https://share-html.com/api/v1/pages/{slug}",
headers={"Authorization": f"Bearer {api_key}"},
json={"html": "<!DOCTYPE html><h1>Launch notes - v2</h1>"},
)
Response200#
{
"url": "https://pages.share-html.com/launch-notes",
"slug": "launch-notes"
}
Errors#
Delete a page#
DELETE/api/v1/pages/{slug}
Permanently removes a page owned by the calling account. After this call the page URL returns 404.
Authentication - Required. Authorization: Bearer sh_live_….
Path parameters#
| Field | Type | Description |
|---|---|---|
slug | string | The slug to delete. |
Request#
curl -X DELETE https://share-html.com/api/v1/pages/launch-notes \
-H "Authorization: Bearer $API_KEY"
await fetch(`https://share-html.com/api/v1/pages/${slug}`, {
method: "DELETE",
headers: { Authorization: `Bearer ${apiKey}` },
});
import requests
requests.delete(
f"https://share-html.com/api/v1/pages/{slug}",
headers={"Authorization": f"Bearer {api_key}"},
)
Response204#
No body. The page URL returns 404 immediately after.
Errors#
The endpoints below - GET /me/pages, GET /me/keys, POST /me/keys, and DELETE /me/keys/{id} - operate on the calling account and require an API key.
List your pages#
GET/api/v1/me/pages
Returns active pages owned by the calling account, newest first, with pagination.
Authentication - Required. Authorization: Bearer sh_live_….
Query parameters#
| Field | Type | Description |
|---|---|---|
limit | integer | Page size, 1 to 100. Defaults to 20. |
offset | integer | Number of items to skip. Defaults to 0. |
Request#
curl "https://share-html.com/api/v1/me/pages?limit=20&offset=0" \
-H "Authorization: Bearer $API_KEY"
Response200#
{
"data": [
{
"slug": "launch-notes",
"url": "https://pages.share-html.com/launch-notes",
"title": "Launch notes",
"owner": "user",
"size_bytes": 4217,
"has_password": false,
"discoverable": false,
"view_count": 132,
"expires_at": null,
"created_at": "2026-05-12T09:31:00.000Z",
"updated_at": "2026-05-19T14:02:00.000Z"
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total": 47,
"has_more": true,
"next_offset": 20
}
}
Each item is the same shape returned by GET /pages/{slug}. next_offset is present only when has_more is true.
Errors#
List API keys#
GET/api/v1/me/keys
Returns every API key on the calling account. The full key value is never returned; only the public prefix is exposed.
Authentication - Required. Authorization: Bearer sh_live_….
Request#
curl https://share-html.com/api/v1/me/keys \
-H "Authorization: Bearer $API_KEY"
Response200#
{
"data": [
{
"id": "key_01HZ…",
"name": "Production publisher",
"prefix": "sh_live_a3f",
"created_at": "2026-05-01T08:12:00.000Z",
"last_used_at": "2026-05-19T13:58:00.000Z"
}
]
}
Errors#
Create an API key#
POST/api/v1/me/keys
Mints a new API key on the calling account. The full key value is returned in the key field and is shown once only - store it immediately. Subsequent requests against GET /me/keys return only the prefix.
Authentication - Required. Authorization: Bearer sh_live_….
Body parameters#
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Human-readable label. 1 to 64 characters. Shown in the dashboard. |
Request#
curl -X POST https://share-html.com/api/v1/me/keys \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "CI deploy bot"}'
Response201#
{
"id": "key_01HZ…",
"name": "CI deploy bot",
"prefix": "sh_live_a3f",
"key": "sh_live_…"
}
Errors#
Revoke an API key#
DELETE/api/v1/me/keys/{id}
Revokes an API key on the calling account. The key cannot revoke itself - use a different key, or revoke through the dashboard.
Authentication - Required. Authorization: Bearer sh_live_….
Path parameters#
| Field | Type | Description |
|---|---|---|
id | string | Key ID from GET /me/keys. |
Request#
curl -X DELETE https://share-html.com/api/v1/me/keys/key_01HZ… \
-H "Authorization: Bearer $API_KEY"
Response204#
No body.
Errors#
OpenAPI#
The machine-readable schema is served at /api/openapi.json. It is generated from the same validation schemas the API enforces, so it cannot drift from behavior. Use it with SDK generators and tools such as Swagger UI, Redoc, and Stoplight.