Skip to content

XRPC API

The main app serves AT Protocol XRPC endpoints at /xrpc/{nsid}. All authenticated endpoints require a service JWT in the Authorization: Bearer <token> header, scoped to the called NSID (lxm claim).

Each endpoint also accepts kebab-case and lowercase NSID aliases (e.g. place.wisp.v2.domain.add-site, place.wisp.v2.domain.addsite).


Returns the registration status of any domain. Auth is optional β€” if authenticated, also returns ownership info for domains you own.

Params:

Field Type Required
domain string βœ…

Response:

Field Type
domain string
status "unclaimed" | "pendingVerification" | "verified" | "alreadyClaimed"
kind "wisp" | "custom"
verified boolean
siteRkey string
lastCheckedAt string (datetime)
lastError string

Returns all domains (wisp subdomains and custom domains) owned by the authenticated DID.

Response:

{
"domains": [
{
"domain": "alice.wisp.place",
"kind": "wisp",
"status": "verified",
"verified": true,
"siteRkey": "my-site"
},
{
"domain": "example.com",
"kind": "custom",
"status": "pendingVerification",
"verified": false,
"lastCheckedAt": "2024-01-15T10:30:00.000Z"
}
]
}

Errors: AuthenticationRequired


place.wisp.v2.domain.claimSubdomain β€” procedure πŸ”’

Section titled β€œplace.wisp.v2.domain.claimSubdomain β€” procedure πŸ”’β€

Claims a *.wisp.place subdomain for the authenticated DID. Max 3 wisp subdomains per DID.

Input:

Field Type Required Notes
handle string βœ… Subdomain label only, e.g. alice (3–63 chars, a-z0-9-)
siteRkey string Map a site immediately after claim

Response:

Field Type
domain string
kind "wisp"
status "verified" | "alreadyClaimed"
siteRkey string

Errors: AuthenticationRequired, InvalidDomain, AlreadyClaimed, DomainLimitReached, RateLimitExceeded


Claims a custom domain for the authenticated DID. Returns DNS challenge details for ownership verification.

Input:

Field Type Required Notes
domain string βœ… Custom FQDN (3–253 chars)
siteRkey string Map a site immediately after claim

Response:

Field Type Notes
domain string
kind "custom"
status "alreadyClaimed" | "pendingVerification" | "verified"
challengeId string Used to derive DNS targets
txtName string TXT record hostname for ownership proof
txtValue string TXT record value (your DID)
cnameTarget string Advisory CNAME target
siteRkey string

Errors: AuthenticationRequired, InvalidDomain, AlreadyClaimed, DomainLimitReached, RateLimitExceeded


place.wisp.v2.domain.addSite β€” procedure πŸ”’

Section titled β€œplace.wisp.v2.domain.addSite β€” procedure πŸ”’β€

Maps a site to a domain you own.

Input:

Field Type Required
domain string βœ…
siteRkey string βœ…

Response:

Field Type
domain string
kind "wisp" | "custom"
status "pendingVerification" | "verified"
siteRkey string
mapped true

Errors: AuthenticationRequired, InvalidDomain, InvalidRequest, NotFound


Deletes a domain (wisp subdomain or custom domain) owned by the authenticated DID.

Params:

Field Type Required
domain string βœ…

Response:

{ "domain": "alice.wisp.place", "deleted": true }

Errors: AuthenticationRequired, InvalidDomain, NotFound


Returns all sites owned by the authenticated DID, with their mapped domains.

Response:

{
"sites": [
{
"siteRkey": "my-site",
"displayName": "My Site",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"domains": [
{ "domain": "alice.wisp.place", "kind": "wisp", "status": "verified", "verified": true }
]
}
]
}

Errors: AuthenticationRequired


Returns all domains mapped to a specific site. Public β€” no auth required.

Params:

Field Type Required
did string βœ…
rkey string βœ…

Response:

{
"domains": [
{ "domain": "alice.wisp.place", "kind": "wisp", "status": "verified", "verified": true }
]
}

Deletes a site and detaches all mapped domains.

Input:

Field Type Required
siteRkey string βœ…

Response:

{
"siteRkey": "my-site",
"deleted": true,
"unmappedDomains": [
{ "domain": "alice.wisp.place", "kind": "wisp", "status": "verified" }
]
}

Errors: AuthenticationRequired, InvalidRequest, NotFound


Private-site methods are authenticated and only operate on sites owned by the calling DID. Private-site files are stored by wisp.place and are not written to the caller’s PDS. See Private Sites for the feature’s access and expiry rules.

place.wisp.v2.privateSite.create β€” procedure πŸ”’

Section titled β€œplace.wisp.v2.privateSite.create β€” procedure πŸ”’β€

Creates a private site from a multipart/form-data upload.

Input:

Field Type Required Notes
name string βœ… Display name, up to 128 characters
files file βœ… Repeat for each file; the filename is used as its path
expiryMinutes integer Omit for seven days, 0 for no expiry, maximum 525600

Uploads are limited to 500 files and 100 MB in total.

Response:

Field Type Notes
siteId string (record-key) Stable private-site identifier
name string Display name
fileCount integer
totalBytes integer
expiresAt string (datetime) Omitted when the site does not expire
createdAt string (datetime)
url string Requires an account with access or a share link

Errors: AuthenticationRequired, InvalidRequest, PayloadTooLarge


Lists private sites owned by the authenticated DID.

Response:

{
"sites": [
{
"siteId": "3mabc...",
"name": "review",
"fileCount": 12,
"totalBytes": 48321,
"expiresAt": "2026-08-22T12:00:00.000Z",
"createdAt": "2026-08-15T12:00:00.000Z",
"shareCount": 1,
"expired": false
}
]
}

expiresAt is omitted when the site does not expire. shareCount includes only active shares.

Errors: AuthenticationRequired


place.wisp.v2.privateSite.delete β€” procedure πŸ”’

Section titled β€œplace.wisp.v2.privateSite.delete β€” procedure πŸ”’β€

Deletes an owned private site, its files, and all of its share links.

Input:

Field Type Required
siteId string (record-key) βœ…

Response:

{ "siteId": "3mabc...", "deleted": true }

Errors: AuthenticationRequired, InvalidRequest, NotFound


place.wisp.v2.privateSite.createShare β€” procedure πŸ”’

Section titled β€œplace.wisp.v2.privateSite.createShare β€” procedure πŸ”’β€

Creates a share link for an owned private site. The returned URL contains the credential and is only returned once.

Input:

Field Type Required Notes
siteId string (record-key) βœ…
label string Human label, up to 128 characters
expiryMinutes integer Omit for seven days; 0 for no independent expiry
audienceDid string (DID) Restricts the link to this account; omit for an unrestricted link

A share’s expiry is clamped to the site’s expiry.

Response:

Field Type Notes
shareId string
siteId string (record-key)
url string Short share URL; returned once
directUrl string (URI) Equivalent URL on the private-site origin
expiresAt string (datetime) Omitted when the share does not expire
createdAt string (datetime)
audienceDid string (DID) Present for account-restricted links

Errors: AuthenticationRequired, InvalidRequest, NotFound


place.wisp.v2.privateSite.listShares β€” query πŸ”’

Section titled β€œplace.wisp.v2.privateSite.listShares β€” query πŸ”’β€

Lists share links for an owned private site. Share credentials are never returned.

Params:

Field Type Required
siteId string (record-key) βœ…

Response:

{
"shares": [
{
"shareId": "3mdef...",
"tokenPrefix": "wss_abcd",
"label": "review",
"audienceDid": "did:plc:...",
"expiresAt": "2026-08-22T12:00:00.000Z",
"createdAt": "2026-08-15T12:00:00.000Z",
"lastUsedAt": "2026-08-16T09:00:00.000Z",
"status": "active"
}
]
}

status is active, expired, or revoked. tokenPrefix is for identification only and does not grant access.

Errors: AuthenticationRequired, NotFound


place.wisp.v2.privateSite.revokeShare β€” procedure πŸ”’

Section titled β€œplace.wisp.v2.privateSite.revokeShare β€” procedure πŸ”’β€

Permanently revokes a share link.

Input:

Field Type Required
siteId string (record-key) βœ…
shareId string βœ…

Response:

{ "shareId": "3mdef...", "revoked": true }

Errors: AuthenticationRequired, InvalidRequest, NotFound


Server-managed HMAC signing secrets for webhooks. The token is returned once at creation time and is stored only as an AES-256-GCM encrypted server-side envelope. It cannot be retrieved again, only rotated. Operators must configure the webhook secret encryption key on both the main and delivery services; see Self-Hosting for deployment, rotation, and backup caveats.

All four endpoints require authentication (AuthenticationRequired on failure).

Creates a new signing secret scoped to the authenticated DID.

Input:

Field Type Required Notes
name string βœ… Unique per DID; 1–64 ASCII letters, digits, ., _, or -

Response:

Field Type Notes
name string
token string wsk_ prefixed β€” store this now, never shown again
createdAt string (datetime)

Errors: AuthenticationRequired, InvalidRequest, AlreadyExists, WebhookSecretEncryptionUnavailable

WebhookSecretEncryptionUnavailable is a stable generic 503 response. It does not reveal whether a key is missing, malformed, or unavailable.


Lists all secrets for the authenticated DID. Token values are never returned.

Response:

{
"secrets": [
{
"name": "my-secret",
"createdAt": "2024-01-15T10:30:00.000Z",
"lastRotatedAt": "2024-02-01T09:00:00.000Z"
}
]
}

Errors: AuthenticationRequired


Generates a new token for an existing secret. The old token is invalidated immediately.

Input:

Field Type Required
name string βœ…

Response:

Field Type Notes
name string
token string New token β€” store this now, never shown again
rotatedAt string (datetime)

Errors: AuthenticationRequired, InvalidRequest, NotFound, WebhookSecretEncryptionUnavailable


Deletes a signing secret. Any webhooks referencing this secretId will stop being signed.

Input:

Field Type Required
name string βœ…

Response: {}

Errors: AuthenticationRequired, InvalidRequest, NotFound