Let someone who is not on this Energon replace bytes at a published URL without Access, a minted token, or /connect. Use a write password because the collaborator already edits in their own tools and only needs to PUT the public link. This is not a guest account, not a browser editor, and not a substitute for write_policy among people who already have tokens.
Let an outside agent update a URL
When to use this door
Use a write password when an outside contractor or another team’s agent should update one published object. Keep them off /v1. Teammates who already have tokens still follow write policy. Recipients who should only read still use an optional share password.
A file write password only replaces that file, including an empty body, and cannot delete it. A site write password can add, replace, or delete paths under that slug, including index.html, and cannot delete the site. The site address still opens after every path is gone.
1. Creator: set the write password
Only the creating account may set or clear it. Duplicate does not copy it. Empty string clears.
export ENERGON_ORIGIN="https://hub.your-company.example"
test -n "$ENERGON_TOKEN" || { echo "Set a human-authorized ENERGON_TOKEN" >&2; exit 1; }
SITE_JSON=$(curl -fsS "$ENERGON_ORIGIN/v1/sites" \
-H "Authorization: Bearer $ENERGON_TOKEN" \
-H "Content-Type: application/json" \
--data '{"slug":"shared-draft","overwrite":false,"write_password":"demo-only-write","ttl":"7d"}')
printf '%s' "$SITE_JSON" | jq '{url, write_password_protected, write_password}'The create response echoes write_password because this request set it. Later /v1 GET and list responses expose only write_password_protected. In the hub, open Link access, turn the write door On, and copy the phrase; Off and Save clears it. Do not empty the field to remove it.
On an existing loose file, use JSON PATCH or the create header:
curl -fsS "$ENERGON_ORIGIN/v1/files/$FILE_ID" \
-X PATCH \
-H "Authorization: Bearer $ENERGON_TOKEN" \
-H "Content-Type: application/json" \
--data '{"write_password":"demo-only-write"}'In the browser, URL, expiration, Who can write, and Publish stay visible. Share and write passwords sit behind the closed Link access disclosure, which opens when either door is on.
2. Human: send the public URL and the phrase
Give the outside agent the returned public content URL in url and the write password. Do not mint them a token. Do not send them to /connect. Do not put the phrase in the published file.
Tell them to read /llms.txt on the content origin, not hub /v1/help. When the two origins differ, content-host /v1/help and /auth.md return 404 naming GET /llms.txt on that host.
3. Outside agent: discover, then PUT
No Authorization header. Raw bytes only.
export CONTENT_ORIGIN="https://content.your-company.example"
export PUBLIC_URL="https://content.your-company.example/ada/s/shared-draft/notes.md"
export WRITE_PASSWORD="demo-only-write"
curl -fsS "$CONTENT_ORIGIN/llms.txt"
curl -fsS "$PUBLIC_URL" \
-X PUT \
-H "X-Energon-Write-Password: $WRITE_PASSWORD" \
--data-binary @notes.mdSite-path DELETE uses the same header and returns 200 JSON { deleted: true, path }:
curl -fsS "$PUBLIC_URL" \
-X DELETE \
-H "X-Energon-Write-Password: $WRITE_PASSWORD"GET with the write header reads the object even if a share password is set. The HTML gate form also accepts the write password for reading. A cookie never authorizes PUT or DELETE. X-Energon-Password never authorizes PUT or DELETE, even when the phrases match.
Recover from the usual failures
| Status | error | What it means |
|---|---|---|
401 | password_required | Missing or wrong write header on an allowed method. Read content /llms.txt. Stop guessing. |
405 | method_not_allowed | Unset write password, directory URL, or a method that kind does not allow (loose-file DELETE, site DELETE). |
404 | file_not_found / site_not_found | Wrong handle, id, filename segment, or missing path. Loose-file filename mismatch is 404, not a redirect. |
409 | file_busy, file_write_lost, site_write_lost | Retry the same public URL. |
410 | expired | Content lifetime passed. Do not retry that URL. |
400 | too_many_files / bad_content_type / bad_request | New site path at the 200-file ceiling, or guest PUT sent multipart or X-Energon-* create headers. |
429 | rate_limited | Too many wrong write secrets. Wait for the gate window. |
Guest JSON on the content host has no hub field and no api_url. Success PUT returns the content-origin url.
Do not mint the outsider a token, default to overwrite: true, or treat the write password as membership. The phrase is a sharing secret: rotate it with PATCH or turn the Hub door Off and Save. A leaked correct phrase cannot be stopped except by rotate or clear.
After a guest write, the Hub last writer stays the last account and shows Updated via shared write. Catalog involvement does not change because guest writes do not rewrite parent last_written_by. For field-level /v1 details, see HTTP API. For how this door sits next to share passwords and write policy, read Sharing, access, and expiry.