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:
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:
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:
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:
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):
DNS TXT value format:
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:
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
POST /api/v1/sites/{site_id}/retirement
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 it returns 202 Accepted with { "target_type": "site", "target_id": "...", "state": "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 status is available at GET /api/v1/sites/{site_id}/retirement. The operator mirror is POST /api/v1/operator/sites/{site_id}/retirement (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 retirements create <id> --yes --confirm-site-id <id> [--wait].
Retire a page's comment room
POST /api/v1/sites/{site_id}/pages/{page_slug}/retirement
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 202 Accepted
with { "target_type": "page", "target_id": ".../...", "state": "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 status is available at
GET /api/v1/sites/{site_id}/pages/{page_slug}/retirement. The operator mirror
is POST /api/v1/operator/rooms/{room_id}/retirement (operator token), and the
CLI equivalent is cumments rooms retirements create ROOM_ID --yes [--wait].
Retiring an unknown or already-retired room returns 404.