Invite an address
const url = 'https://beta-api.plune.ai/v1/members';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://beta-api.plune.ai/v1/members \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \Owner only (api.ts → inviteMember, the Invite form). Two outcomes, told apart by kind: an address that already has a Plune account is a member at once; any other address gets an invitation — a mail says where to sign in, the beta door lets the address through, and the sign-in itself turns the invitation into a membership. No token in the mail: the magic link is the proof. The address is lower-cased before it is compared or stored. Twice for the same address is 409, and so is a project at its member limit.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Header Parameters
Section titled “Header Parameters ”Which of your projects to act in — an id from GET /v1/projects. Absent, your default project. A project you are not a member of answers 404, the same as one that does not exist. Ignored under a bearer token, which is bound to the project it was minted in.
Request Body required
Section titled “Request Body required ”object
What a member may do (B8-team). owner runs the project — members, roles, its name; member does everything else; reader is refused every write at the boundary, before a handler runs.
Examples
An address without an account — an invitation
{ "role": "reader"}An address that already signed in — a member at once
{ "role": "member"}Responses
Section titled “ Responses ”Invited — kind says which of the two it became
What inviting an address produced: a member at once when an account holds it (kind: member), else an invitation for the address to sign in with (kind: invitation).
object
The display name, once people have one (T3); null until then.
What a member may do (B8-team). owner runs the project — members, roles, its name; member does everything else; reader is refused every write at the boundary, before a handler runs.
Who invited them (a userId); null for the person the project was created by.
What inviting an address produced: a member at once when an account holds it (kind: member), else an invitation for the address to sign in with (kind: invitation).
object
What a member may do (B8-team). owner runs the project — members, roles, its name; member does everything else; reader is refused every write at the boundary, before a handler runs.
Example
{ "kind": "invitation", "id": "6f1c2b3a-0000-4000-8000-0000000000a3", "role": "reader", "invitedBy": "u-shop", "createdAt": "2026-09-16T09:12:04.151Z"}Invalid body — an email address and one of the three roles
object
Example generated
{ "error": "example"}No / invalid token or session
A member or a reader asked
object
Example
{ "error": "project owner only"}The header names a project you are not in
object
Example generated
{ "error": "example"}Already in, already invited, or the project is at its member limit
object
Example
{}Rate-limited: either the per-route throttle or a tenant quota. Retry-After carries the seconds until the window rolls over.
object
Example generated
{ "error": "example"}Headers
Section titled “Headers ”Seconds until the window rolls over