Sites¶
Self-service site registration, domain verification and strict-mode secret issuance. The trust model behind these operations is covered in Site trust and the end-to-end walkthrough lives in Site verification.
Register a site¶
POST /api/v1/sites
Registration is the mandatory first step for every site: a site_id that is
neither registered here nor declared in the [sites] configuration can never
accept writes. The request body is optional:
{ "site_id": "my-blog" }
With a body, the caller picks the id (lowercase [a-z0-9-], 1-64
characters); ids are first-come, and a conflict returns 409. Without a
body, the server generates an unguessable random id (32 hex characters). The
chosen id is what shows up in Matrix: the Space alias
#_cumments_my-blog:server, each room alias
#_cumments_my-blog_<page>:server and the Space display name.
Chosen ids are a privilege: under the optional verification policy they
must verify at least one origin before they accept writes, while random ids
keep the relaxed migration behavior. The name stays reserved while
unverified (see Site trust).
The response carries the site_id and a one-time claim_token:
{ "site_id": "my-blog", "claim_token": "..." }
The claim token proves ownership of the site and must be sent in the
X-Cumments-Claim-Token header for verification and secret issuance. It is
shown once and only its hash is stored.
Start verification¶
POST /api/v1/sites/{site_id}/verifications
Headers: X-Cumments-Claim-Token: <claim_token>
Body:
{
"origins": ["https://blog.example.com"],
"methods": ["well-known", "dns"]
}
methods are tried in order by confirm; publishing the same token in every
chosen location gives an automatic fallback. The response contains the token,
the expiry, and concrete publishing instructions.
Confirm verification¶
POST /api/v1/sites/{site_id}/verifications/confirm
Body:
{ "origin": "https://blog.example.com", "token": "..." }
Cumments fetches {origin}/.well-known/cumments.json and/or queries the
_cumments.<host> TXT record. On the first matching proof it records the
origin and returns the updated verified_origins list.
Well-known document shapes (both accepted):
{ "site_id": "...", "token": "..." }
{ "sites": [ { "site_id": "...", "token": "..." } ] }
DNS TXT value format:
site_id=<site_id>,token=<token>
Issue an HMAC secret (strict mode)¶
POST /api/v1/sites/{site_id}/secret
Headers: X-Cumments-Claim-Token: <claim_token>
Body: { "rotate": false } (omit to issue; true replaces an existing
secret).
The site must be verified first. The secret is returned exactly once:
{ "site_id": "...", "secret": "..." }
It is used as the HMAC key in edge-function deployments (see Site trust); the same value must be set on the site backend and used to sign every write request.
Retire a site¶
DELETE /api/v1/sites/{site_id}
Headers: X-Cumments-Claim-Token: <claim_token>
Decommissioning is two-phase. The request marks the site retiring
synchronously: writes are rejected from that moment with
410 code=site-retired, the claim token is invalidated, and the response is
{ "site_id": "...", "status": "retiring" }. A background pass then retires
the Matrix Space and every comment room one by one — renaming them
[retired] ..., removing their aliases and leaving them as the AppService
sender — before clearing the local projections and the site row.
The operator mirror is
DELETE /api/v1/operator/sites/{site_id} (operator token). Sites declared in the
[sites] configuration cannot be retired through the API; remove them from
the config file instead. The CLI equivalent is
cumments sites retire <id> --yes [--wait].
Retire a page's comment room¶
DELETE /api/v1/sites/{site_id}/pages/{page_slug}
Headers: X-Cumments-Claim-Token: <claim_token>
Removes one page's comment section. Like site retirement, this is
two-phase: the request marks the room retired synchronously (new
writes to that room are rejected from that moment) and returns
{ "site_id": "...", "page_slug": "...", "status": "retiring" }. A
background pass then renames the Matrix room [retired] site/page, removes
its alias, leaves it as the AppService sender and every site virtual user,
and clears the local projections. The page's alias is released and a later
registration of the same page slug starts fresh.
The operator mirror is DELETE /api/v1/operator/rooms/{room_id} (operator
token), and the CLI equivalent is cumments rooms retire ROOM_ID --yes
[--wait]. Retiring an unknown or already-retired room returns 404.