Skip to content

Invites

Invites let a space’s creator add members without knowing their DIDs in advance: the creator hands out a token, and whoever accepts it joins the space.

Only the space’s creator or an operator with superadmin can create invites.

const response = await fetch("https://happyview.example.com/xrpc/dev.happyview.space.createInvite", {
method: "POST",
headers: {
"X-Client-Key": CLIENT_KEY,
"Authorization": `DPoP ${ACCESS_TOKEN}`,
"DPoP": DPOP_PROOF,
"Content-Type": "application/json",
},
body: JSON.stringify({
space: "at://did:web:happyview.example.com/space/com.example.forum/main",
access: { read: true, write: true },
maxUses: 10,
expiresAt: "2026-06-01T00:00:00Z",
}),
});
interface CreateInviteResponse {
inviteId: string;
token: string;
access: { read: boolean; write: boolean };
maxUses: number | null;
expiresAt: string | null;
}
const data: CreateInviteResponse = await response.json();

Input:

FieldTypeRequiredDefaultDescription
spacestringYesThe space this invite is for
accessobjectNo{ "read": true, "write": false }Access granted on acceptance: read and write booleans, both required when access is given
maxUsesintegerNounlimitedMaximum number of times the invite can be accepted
expiresAtstring (datetime)NoneverWhen the invite expires, in UTC (ending in Z or +00:00)

Response (201):

{
"inviteId": "uuid",
"token": "a1b2c3d4e5f6...",
"access": { "read": true, "write": true },
"maxUses": 10,
"expiresAt": "2026-06-01T00:00:00Z"
}

Any authenticated user can accept an invite token to join the space.

const response = await fetch("https://happyview.example.com/xrpc/dev.happyview.space.acceptInvite", {
method: "POST",
headers: {
"X-Client-Key": CLIENT_KEY,
"Authorization": `DPoP ${ACCESS_TOKEN}`,
"DPoP": DPOP_PROOF,
"Content-Type": "application/json",
},
body: JSON.stringify({
token: "a1b2c3d4e5f6...",
}),
});
interface AcceptInviteResponse {
uri: string;
access: { read: boolean; write: boolean };
}
const data: AcceptInviteResponse = await response.json();

Response (201):

{
"uri": "at://did:web:happyview.example.com/space/com.example.forum/main",
"access": { "read": true, "write": true }
}

Acceptance fails if:

  • The token is invalid (no matching hash found): 404
  • The invite has been revoked: 400
  • The invite has reached its maxUses: 400
  • The invite has expired: 400
  • The user is already a member of the space: 409
const response = await fetch("https://happyview.example.com/xrpc/dev.happyview.space.revokeInvite", {
method: "POST",
headers: {
"X-Client-Key": CLIENT_KEY,
"Authorization": `DPoP ${ACCESS_TOKEN}`,
"DPoP": DPOP_PROOF,
"Content-Type": "application/json",
},
body: JSON.stringify({
space: "at://did:web:happyview.example.com/space/com.example.forum/main",
inviteId: "uuid",
}),
});

Only the space’s creator or an operator with superadmin can revoke an invite. Revoking prevents future acceptances but does not remove members who already accepted it. A revoke answers {"success": true}, and an inviteId that is not one of the space’s invites fails with 404.

Only the space’s creator or an operator with superadmin can list invites.

const response = await fetch(
"https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=at://did:web:happyview.example.com/space/com.example.forum/main",
{
headers: {
"X-Client-Key": CLIENT_KEY,
"Authorization": `DPoP ${ACCESS_TOKEN}`,
"DPoP": DPOP_PROOF,
},
},
);
interface Invite {
id: string;
access: { read: boolean; write: boolean };
maxUses: number | null;
uses: number;
expiresAt: string | null;
revoked: boolean;
createdBy: string;
createdAt: string;
}
const data: { invites: Invite[] } = await response.json();

Parameters:

FieldTypeRequiredDescription
spacestringYesThe space to list invites for

Response:

{
"invites": [
{
"id": "uuid",
"access": { "read": true, "write": true },
"maxUses": 10,
"uses": 3,
"expiresAt": "2026-06-01T00:00:00Z",
"revoked": false,
"createdBy": "did:plc:abc123",
"createdAt": "2026-05-09T12:00:00Z"
}
]
}

List responses carry the invite metadata and never the token.