Projects

Add a project member

Adds a colleague to the project by email address. Free and uncapped on every plan: a member adds no run, no channel, no trigger and no byte, so every cost they cause is already billed through the project's owner. Members are counted nowhere.

The address does not need an account. Inviting one that has none creates it unverified and records the membership beside it, so the invitee is already a member with status pending. Their first sign-in code — which they request themselves, from the link in the invitation — is what makes them active. There is no separate acceptance step and no invitation to expire: the address is the credential, and the invitation reached it.

An owner may grant admin or member; an admin may grant member only, so administration cannot hand out its own authority. role: owner is refused — that is the billing owner, and ownership moves only through a transfer the new owner accepts (PUT /v1/projects/{project_id}/transfer).

The invitation email is a courtesy, not the grant: if it cannot be sent the membership still stands, and the response still says pending. Requires an account-wide credential — a project-scoped key cannot grant access that would outlive its own revocation.

post/v1/projects/{project_id}/members

Request

  • Base URL: https://api.naturali.ai
  • URL: https://api.naturali.ai/v1/projects/{project_id}/members
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://api.naturali.ai/authorize, token URL https://api.naturali.ai/token, scopes: mcp:access)

Request body

emailstring email required

The colleague's address, lower-cased before lookup. It does not need an account yet.

role'admin' | 'member' required

The roles a membership write may name. owner is absent by construction: it is the billing owner, so granting it would change who pays, and transferring that is a different act with its own decision.

Example request

{
  "email": "ana@acme.com",
  "role": "member"
}

Response

The member was added.

idstring required

Public membership ID (pmem_ prefix).

project_idstring required
user_idstring required
emailstring email nullable required

The member's address; null if the account no longer exists.

namestring nullable required
status'active' | 'pending' nullable required

pending until the member has signed in for the first time, active afterwards. Derived from the account, not stored, so it needs nothing to run when they arrive. Null if the account no longer exists — there is no status to report for somebody who is never arriving.

role'owner' | 'admin' | 'member' required

What the member may do in this project. owner — everything, including deleting it and paying for it; exactly one per project. admin — everything a member may do, plus managing who else is in the project and how the project itself is configured. member — every read and write on the project's own resources, including minting project API keys. When returned on a Project, this is your role, not a property of the project: it is what lets a client hide an action the request would refuse.

invited_by_user_idstring nullable required

Who added this member; null for the founding owner, who was added by the act of creating the project.

created_atstring date-time required

Example response

{
  "id": "pmem_V1StGXR8Z5jdHi6B",
  "project_id": "proj_V1StGXR8Z5jdHi6B",
  "user_id": "user_V1StGXR8Z5jdHi6B",
  "email": "ana@acme.com",
  "name": "Ana Silva",
  "status": "active",
  "role": "owner",
  "created_at": "2026-07-17T00:00:00.000Z"
}

Changes

No recorded changes to this operation across all 1 revision of this API.