htmlslop API

Upload an HTML page and get a stable, content-addressed URL. Create aliases โ€” stable redirect URLs you can repoint over time. All writes are signed with RFC 9421 HTTP Message Signatures.

๐Ÿค– Coding agents: the authoritative, copy-paste signing spec โ€” with every ambiguity resolved and a self-check test vector โ€” lives at /llms.txt. Verify your signature against the vector before calling the API to avoid opaque 401s.

Authentication

Every write is signed with HMAC-SHA256 using a key you've been issued (keyId + secret). The signature travels in standard headers:

Requests are rejected if created is more than 300s from server time, or if the nonce has been used before (single-use โ†’ no replay).

How to sign (bash + openssl)

Covered components are @method, @path, and content-digest. Build the signature base exactly as shown, HMAC it, and send the three headers.

KEY_ID="k1"; SECRET="your-secret"
BODY='{"html":"<h1>hi</h1>","title":"My Page"}'
PATH_="/api/v1/upload"; METHOD="POST"

CREATED=$(date +%s)
NONCE=$(openssl rand -hex 16)
DIGEST="sha-256=:$(printf %s "$BODY" | openssl dgst -sha256 -binary | base64):"
PARAMS="(\"@method\" \"@path\" \"content-digest\");created=$CREATED;keyid=\"$KEY_ID\";nonce=\"$NONCE\";alg=\"hmac-sha256\""

# Signature base โ€” one line per component, then the params line (no trailing newline)
BASE=$(printf '"@method": %s\n"@path": %s\n"content-digest": %s\n"@signature-params": %s' \
  "$METHOD" "$PATH_" "$DIGEST" "$PARAMS")
SIG=$(printf %s "$BASE" | openssl dgst -sha256 -hmac "$SECRET" -binary | base64)

curl -X POST https://$HOST$PATH_ \
  -H "Content-Digest: $DIGEST" \
  -H "Signature-Input: sig1=$PARAMS" \
  -H "Signature: sig1=:$SIG:" \
  -H "Content-Type: application/json" \
  --data "$BODY"

Endpoints

Upload a page

POST /api/v1/upload โ€” body {"html", "title", "ttl"?} (html โ‰ค 5 MiB; ttl seconds, default 7d).

Returns 201 {url, expiresAt, ttl}. The URL is /<contentHash>-<title>.html and is immutable + cached aggressively. Re-uploading identical content yields the same URL. Pages are served Brotli/gzip-compressed via content negotiation.

Create an alias

POST /api/v1/aliases โ€” body {"title", "target"} where target is an existing page path like /<hash>-title.html.

Returns 201 {aliasId, url}. The alias URL (/alias-<id>-<title>.html) is stable and 302-redirects to the target. Not cached, so updates take effect immediately.

Update an alias

PUT /api/v1/aliases/{aliasId} โ€” body {"target"}. Repoints the alias to a new (existing) page. The alias URL stays the same.

Delete an alias

DELETE /api/v1/aliases/{aliasId} โ€” no body. Removes the alias.

Machine-readable

GET /api/v1 returns this API's shape as JSON. GET /llms.txt is the full agent reference (signing spec, schemas, error shapes, test vector) as raw text.