Questions · Updated 2026-09-27
How do I invite a teammate and set their role?
Invite a teammate with POST /team/invites, passing their email and a role of owner, admin or viewer. They accept the link while signed in as that address, and PATCH /team/members/{id} changes the role later.
Invite a teammate by calling POST /team/invites with their email and a role of owner, admin or viewer; viewer is what they get when the field is left out. The operation summary says "Invite an address at a role. The mail carries a link that only works while signed in as that address." Set the role later with PATCH /team/members/{id}. Both calls need a signed-in session: an API key has no role and cannot invite anyone.
The three roles
GET /team/members lists everyone; its summary is "Everyone on this account and the role each one holds. Owner, admin, viewer — three roles, and seats are never billed per seat." The roles code says what each one may do:
- Owner — everything, including billing, closing the account, and changing another owner's role. At least one always exists.
- Admin — everything else: keys, domains, webhooks, budgets, the kill switch, approvals, invites.
- Viewer — reads everything, changes nothing.
A viewer who calls a write is refused with insufficient_role; the message is "Your role on this account is viewer, which can read everything and change nothing." An admin who calls a billing route or DELETE /account reads "Only an owner can close the account or change billing." Roles belong to people signed in to the console. A bearer API key's authority is its permission and its scopes, so a key an agent already holds keeps working when a viewer joins.
GET /team/me returns your role and seats: used, limit, plan and billed_per_seat, which is always false. used counts members plus live invitations, so an account cannot pass the cap by inviting. How many seats each plan allows is on the pricing page. At the cap, POST /team/invites is refused with seat_limit_reached, and the catalogue fix says "Remove a member with DELETE /team/members/:id, cancel a pending invite with DELETE /team/invites/:id, or move to a plan with more seats. Seats are never billed per seat."
Sending and accepting the invitation
curl -sS -X POST https://api.agentisend.com/team/invites \
-H "Authorization: Bearer $AGENTISEND_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"email":"customer@example.com"}'201
{
"created_at": "2026-09-04T09:14:00Z",
"email": "customer@example.com",
"expires_at": "2026-09-04T09:14:00Z",
"id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
"invited_by": "string",
"invited_by_email": "customer@example.com",
"role": "owner"
}The reply carries id, email, role, expires_at and invited_by_email. GET /team/invites lists the ones that have not been accepted, cancelled or expired. DELETE /team/invites/{id} cancels one: "The link in the email stops working immediately." Only an owner can invite another owner; an admin's attempt is refused with "Only an owner can invite another owner." In the console the same form is under Settings → Team.
The teammate opens the link and the console calls POST /invite/{token}/accept. Its summary: "Accept an invitation. Requires a session signed in as the invited address; a person who has never signed in before is provisioned into the inviting account, not a new one." Signed in as someone else, they read invite_email_mismatch, whose fix is "Sign out, sign in as the invited address, then open the invitation link again — POST /invite/:token/accept binds the membership to the signed-in address." An expired or cancelled link is invite_not_valid; an address that already belongs to another account is already_in_account.
Changing or removing a member
PATCH /team/members/{id} takes role. Its summary adds "The last owner cannot be demoted." — that refusal is last_owner_required, whose fix is "Promote another member to owner with PATCH /team/members/:id first, then retry." An admin cannot touch an owner's role or make anyone an owner; the code's message is "Only an owner can change an owner’s role, or make someone one."
DELETE /team/members/{id} — "Remove a member. Their sends and keys stay; only their access ends. The last owner cannot be removed." Removal also ends that person's console sessions and revokes any connection they granted an AI client over MCP. Every invite, role change and removal writes a row to GET /audit-log, so who changed whom is on record.