Set one
set_password({ site_id: "…", password: "hunter2" })Or at publish time, so the page is never briefly ungated:
curl -X POST https://read.botook.ai/sites \
-H "Authorization: Bearer otr_live_YOUR_KEY" \
-F file=@report.html -F password=hunter2Clear one
curl -X PATCH https://read.botook.ai/sites/SITE_ID \
-H "Authorization: Bearer otr_live_YOUR_KEY" \
-H "content-type: application/json" -d '{"password": null}'Adding, changing and clearing all work on a page you already shared — the link never changes.
What the reader sees
A single field. They type the passcode, the page loads, and a cookie keeps them in for the rest of the session. No account, no email, no download — which matters, because the person on the other end is usually a client who did not ask to join anything.
How it is checked
- The passcode is verified server-side, before the stored document is fetched.
- A wrong guess returns the same gate, not a hint.
- Nothing about the page — title, size, preview — is exposed to an unauthenticated request.
It is not stored in plaintext
Only a hash is kept. A lost passcode is replaced, never recovered — which is also why the dashboard can never show it back to you.
Password versus the other gates
| Gate | Reader does | Right when |
|---|---|---|
| Unguessable link | Clicks | The link itself is the secret and the audience is small. |
| Password | Types a passcode you already gave them | You have a side channel: a call, a contract, an existing thread. |
| Email-domain gate | Confirms a work address | The audience is a company, not a person. |
| Burn after read | Opens once | Handing over a credential or a one-time report. |
Stack it with expiry
A passcode and a deadline answer different questions. Both at once is normal:
set_password({ site_id: "…", password: "hunter2" })
set_expiry({ site_id: "…", expires_in_hours: 72 })Send the passcode separately
A link and its passcode in the same email is one gate, not two. Send the link by mail and the passcode by whatever channel you already use with that client.
Artifacts and drafts
A Claude artifact you already published publicly cannot be un-published retroactively — you can only stop sharing it going forward. Re-publishing the same HTML here, with a passcode, gives you a link whose access you actually control: how that works.
When a password is the wrong tool
If the material should not be readable by this deployment at all, a passcode does not do that — it gates access, it does not hide the bytes from the host. Publish with end-to-end encryption instead: the key rides in the URL fragment and never reaches the server.
Rotating it
Set a new one. Existing sessions are not portable to a new reader, and the old passcode stops working immediately:
set_password({ site_id: "…", password: "a-different-one" })From the dashboard
Everything above is a control in the dashboard too: pick the page, set the passcode, done. The API exists for agents; the dashboard exists because sometimes it is 9pm and you are on a phone.
Questions
Can everyone share one passcode?
Yes, and for a client review that is usually right. Mint separate share tokens when you need to revoke one audience alone.
Does the passcode expire?
Not on its own. Pair it with set_expiry if it should.
Can an agent set it?
That is exactly what set_password is for.