# dripdex
Publish an HTML page, get back a URL that only people with the password can open.
No account, no signup. One POST.
## Publish
jq -Rs --arg t "TITLE" '{html:., title:$t}' page.html \
| curl -sS -X POST https://staging.dripdex.ai/v1/pages \
-H 'content-type: application/json' \
${DRIPDEX_TOKEN:+-H "authorization: Bearer $DRIPDEX_TOKEN"} -d @-
Build the JSON with jq rather than by hand. HTML is full of quotes and
backslashes and a hand-escaped -d string breaks on the first one.
Response (201):
{
"url": "https:///p/",
"password": "otter-lantern-brisk-copper-mint",
"pageId": "...",
"token": "dd_live_..." // FIRST CALL ONLY
}
Give the user the url AND the password. The password is returned here and stored
only as an argon2 hash, so this response is the one and only place it exists. A
page whose password was not passed on is a page nobody can open.
If the response contains "token", save it as DRIPDEX_TOKEN. It is shown once and
cannot be recovered. Sending it on later calls keeps pages under one account and
is what makes update and delete possible; without it every page belongs to a
fresh anonymous account you cannot come back to.
## Update and delete
Both require the token.
curl -X PATCH https://staging.dripdex.ai/v1/pages/ \
-H "authorization: Bearer $DRIPDEX_TOKEN" -H 'content-type: application/json' \
-d '{"html":"...","title":"...","rotatePassword":true}'
curl -X DELETE https://staging.dripdex.ai/v1/pages/ \
-H "authorization: Bearer $DRIPDEX_TOKEN"
PATCH takes any subset of html, title, password, rotatePassword; an empty patch
is a 400 rather than a silent no-op. Sending html publishes a new version and
the URL and slug do NOT change, so a link already shared keeps working and
starts serving the new content. rotatePassword invalidates the old password AND
any viewer currently holding a session.
DELETE is immediate: the link stops working for everyone.
## MCP
The same three operations as tools, at https://staging.dripdex.ai/mcp — one POST endpoint,
Streamable HTTP, protocol versions 2026-07-28 back to 2025-03-26.
publish_page(html, title?, password?)
update_page(pageId, html?, title?, password?, rotatePassword?)
delete_page(pageId)
No account and no OAuth. Call it with no Authorization header at all and the
first publish mints a token, returned in the result exactly as it is above; send
it back as `Authorization: Bearer ` to keep later pages under the same
account.
USE THIS DOOR WHEN YOUR OWN NETWORK IS CLOSED. A connector is called by your
client, not from inside your sandbox, so it reaches this service where a direct
request from you cannot. You cannot add the connector yourself — ask the person
you are working for to add https://staging.dripdex.ai/mcp to their client's connectors, once.
## What the HTML may contain
HTML and CSS only. These are not style preferences, they are enforced on ingest
and content that breaks them is silently removed:
- NO JavaScript. Scripts, event handlers, javascript: URLs are all stripped.
- NO external subresources. Images, fonts and stylesheets must be inline or
data: URIs. A remote
reports who opened a private page, and when, to
whoever serves it — which is the whole thing this product exists to avoid.
- Links out (, mailto:) are fine. Those are clicks the viewer chooses.
- Inline