# sHTMLs
> HTML hosting with optional password protection. Upload an HTML file, get a short shareable URL. Add a password to require visitors to authenticate before viewing. Leave the password blank to share publicly with no gate. Pages auto-expire after 30 days. No accounts, no tracking.
sHTMLs provides a JSON API at `https://shtmls.com/api/` that LLMs and agents can use to upload HTML content and retrieve it programmatically. All requests and responses use `Content-Type: application/json`.
## API Endpoints
### Upload a page
`POST https://shtmls.com/api/upload`
Request body:
- `html` (string, required): Base64-encoded HTML content. Maximum decoded size is 3 MB.
- `password` (string, optional): Password to protect the page. Minimum 4 characters. Omit or pass `null` to make the page public (no password required to view).
- `filename` (string, optional): Display name for the file. Defaults to `page.html`.
Response (200):
- `id` (string): Short URL identifier. The page is viewable at `https://shtmls.com/{id}`.
- `expires_at` (string): ISO 8601 expiration timestamp (30 days from creation).
Example — password-protected upload:
```
POST https://shtmls.com/api/upload
Content-Type: application/json
{
"html": "PGgxPkhlbGxvPC9oMT4=",
"password": "mypassword",
"filename": "hello.html"
}
```
Example — public upload (no password):
```
POST https://shtmls.com/api/upload
Content-Type: application/json
{
"html": "PGgxPkhlbGxvPC9oMT4=",
"filename": "hello.html"
}
```
Response:
```json
{
"id": "a1b2c3d4",
"expires_at": "2026-04-16T12:00:00+00:00"
}
```
Rate limit: 10 uploads per IP per hour. Returns 429 when exceeded.
### Retrieve content
`POST https://shtmls.com/api/verify/{id}`
For password-protected pages, supply the password. For public pages, send an empty body or omit the password field entirely.
Request body:
- `password` (string, optional): Required only for password-protected pages.
Response (200):
- `html` (string): The raw HTML content of the page.
- `filename` (string): The original filename.
Returns 400 if password is missing for a protected page, 403 for incorrect password, 404 if the page does not exist or has expired.
### Get page metadata
`GET https://shtmls.com/api/page/{id}`
No authentication required. Returns public metadata only.
Response (200):
- `id` (string): Page identifier.
- `filename` (string): Display filename.
- `expires_at` (string): ISO 8601 expiration timestamp.
- `is_public` (boolean): `true` if the page has no password. Use this to skip the password prompt in your UI.
Returns 404 if the page does not exist or has expired. Does not return password, hash, or any sensitive data.
### Get usage stats
`GET https://shtmls.com/api/stats`
Response (200):
- `pages_created` (integer): Total pages uploaded.
- `pages_viewed` (integer): Total pages viewed after password verification.
## Constraints
- Maximum file size: 3 MB (after base64 decoding)
- Password minimum length: 4 characters (if provided)
- Pages expire after 30 days (automatic deletion)
- Rate limit: 10 uploads per IP per hour
- HTML content is stored encrypted at rest
- Passwords are hashed with PBKDF2-SHA256 (150,000 iterations)
## Optional
- [Website](https://shtmls.com): Browser-based upload interface