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:

FieldTypeRequired
domainstringβœ…

Response:

FieldType
domainstring
status"unclaimed" | "pendingVerification" | "verified" | "alreadyClaimed"
kind"wisp" | "custom"
verifiedboolean
siteRkeystring
lastCheckedAtstring (datetime)
lastErrorstring

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:

FieldTypeRequiredNotes
handlestringβœ…Subdomain label only, e.g. alice (3–63 chars, a-z0-9-)
siteRkeystringMap a site immediately after claim

Response:

FieldType
domainstring
kind"wisp"
status"verified" | "alreadyClaimed"
siteRkeystring

Errors: AuthenticationRequired, InvalidDomain, AlreadyClaimed, DomainLimitReached, RateLimitExceeded


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

Input:

FieldTypeRequiredNotes
domainstringβœ…Custom FQDN (3–253 chars)
siteRkeystringMap a site immediately after claim

Response:

FieldTypeNotes
domainstring
kind"custom"
status"alreadyClaimed" | "pendingVerification" | "verified"
challengeIdstringUsed to derive DNS targets
txtNamestringTXT record hostname for ownership proof
txtValuestringTXT record value (your DID)
cnameTargetstringAdvisory CNAME target
siteRkeystring

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:

FieldTypeRequired
domainstringβœ…
siteRkeystringβœ…

Response:

FieldType
domainstring
kind"wisp" | "custom"
status"pendingVerification" | "verified"
siteRkeystring
mappedtrue

Errors: AuthenticationRequired, InvalidDomain, InvalidRequest, NotFound


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

Params:

FieldTypeRequired
domainstringβœ…

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:

FieldTypeRequired
didstringβœ…
rkeystringβœ…

Response:

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

Deletes a site and detaches all mapped domains.

Input:

FieldTypeRequired
siteRkeystringβœ…

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:

FieldTypeRequiredNotes
namestringβœ…Display name, up to 128 characters
filesfileβœ…Repeat for each file; the filename is used as its path
expiryMinutesintegerOmit for seven days, 0 for no expiry, maximum 525600

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

Response:

FieldTypeNotes
siteIdstring (record-key)Stable private-site identifier
namestringDisplay name
fileCountinteger
totalBytesinteger
expiresAtstring (datetime)Omitted when the site does not expire
createdAtstring (datetime)
urlstringRequires 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:

FieldTypeRequired
siteIdstring (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:

FieldTypeRequiredNotes
siteIdstring (record-key)βœ…
labelstringHuman label, up to 128 characters
expiryMinutesintegerOmit for seven days; 0 for no independent expiry
audienceDidstring (DID)Restricts the link to this account; omit for an unrestricted link

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

Response:

FieldTypeNotes
shareIdstring
siteIdstring (record-key)
urlstringShort share URL; returned once
directUrlstring (URI)Equivalent URL on the private-site origin
expiresAtstring (datetime)Omitted when the share does not expire
createdAtstring (datetime)
audienceDidstring (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:

FieldTypeRequired
siteIdstring (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:

FieldTypeRequired
siteIdstring (record-key)βœ…
shareIdstringβœ…

Response:

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

Errors: AuthenticationRequired, InvalidRequest, NotFound


Server-managed HMAC signing secrets for webhooks. The server generates the token unless you supply your own on create or rotate, for example a secret your receiving system already generated. 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:

FieldTypeRequiredNotes
namestringβœ…Unique per DID; 1–64 ASCII letters, digits, ., _, or -
tokenstringYour own signing token: 32–256 printable ASCII characters, no whitespace. Omit it to have the server generate a wsk_ token

Response:

FieldTypeNotes
namestring
tokenstringThe generated wsk_ token, or the one you supplied β€” store this now, never shown again
createdAtstring (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


Replaces the token of an existing secret with a newly generated one, or with the token you supply. The old token is invalidated immediately.

Input:

FieldTypeRequiredNotes
namestringβœ…1–64 ASCII letters, digits, ., _, or -
tokenstringYour own signing token: 32–256 printable ASCII characters, no whitespace. Omit it to have the server generate one

Response:

FieldTypeNotes
namestring
tokenstringNew token β€” store this now, never shown again
rotatedAtstring (datetime)

Errors: AuthenticationRequired, InvalidRequest, NotFound, WebhookSecretEncryptionUnavailable


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

Input:

FieldTypeRequired
namestringβœ…

Response: {}

Errors: AuthenticationRequired, InvalidRequest, NotFound