A Project's members are the people who may open it. Membership is by email address, and the role decides what each one may do.
The four roles
owner and admin are the management roles. analyst and viewer are read roles: they can open every report in the Project and change nothing about the Project itself.
There is exactly one thing only a platform administrator can do: archive a Project, and set its plan. Both change what a Project costs or whether it exists, so they are deliberately not a customer-side action.
Adding and removing
curl -X POST https://t.intelligent.page/v1/projects/acme-shop/members \
-H 'content-type: application/json' \
-H 'Authorization: Bearer ipa_sec_REPLACE_ME' \
-d '{ "email": "ada@example.com", "role": "analyst" }'
The answer is the Project's full member list, so a UI can render it without a second call:
{ "members": [
{ "projectId": "acme-shop", "email": "owner@example.com", "role": "owner", "addedAt": "2026-02-01T…" },
{ "projectId": "acme-shop", "email": "ada@example.com", "role": "analyst", "addedAt": "2026-09-28T…" }
] }
Posting an email that is already a member changes their role: there is no separate update call.
curl -X DELETE https://t.intelligent.page/v1/projects/acme-shop/members/ada%40example.com \ -H 'Authorization: Bearer ipa_sec_REPLACE_ME'
{ "ok": true }
404 if that email is not a member. URL-encode the @.
Emails are stored and compared lowercased, so Ada@Example.com and ada@example.com are one member. A 400 comes back if email or role is missing or the role is not one of the four.
How a caller is recognised
Three ways to reach the management routes, and they answer to different scopes:
A Server key is therefore an admin in permission terms, for one Project. That is the reason a Server key never belongs in a browser: it is not just a write credential, it can add a member.
Adding someone as a member does not send them anything. Tell them yourself, and tell them which Project id to open.
Seeing your own Projects
curl -s https://t.intelligent.page/v1/me/projects \ -H 'Authorization: Bearer <read token>'
{ "projects": [ { "project": { "id": "acme-shop", "name": "Acme Shop", "plan": "starter", … }, "role": "owner" } ] }
This is what the Project switcher is built from. It needs a read token minted for a person: a Server key is a single-Project credential and gets 401 here.
Changing the owner
Set the new person to owner, confirm they can manage the Project, then change the previous owner to admin or remove them. There is no single transfer call.
Keep at least two people with owner or admin. A Project whose only manager has left needs a platform administrator to intervene.
A practical arrangement
- owner: the person accountable for the data, usually one or two people.
- admin: whoever maintains the integration and rotates keys.
- analyst: everyone who builds reports.
- viewer: everyone else who reads them.
Review the list whenever someone leaves. Membership is by email address and nothing expires it.