Skip to content
Hexel StudioDocs

Members and invitations

Invite people to your organization, give them a member role, change it, and remove them.

On this page

A member is a Hexel account that belongs to your organization. Every member has exactly one member role: owner, admin, member or viewer. The role decides the member's default access and which other members they can manage.

You add people in one of two ways:

  • Invite them by email. This is the usual way. The person accepts the invitation and joins with the org_member role.
  • Add them directly. Use this when the person already has a Hexel account and you know their user ID.

The examples on this page use $ACCESS_TOKEN (an access token for your organization) and $ORG_ID. See Authenticate to the API.

Member roles

RoleRankDefault access
org_owner4Everything in the organization, including deleting it.
org_admin3Manage members and invitations, organization details and settings, policies, groups, roles and service users, workspaces and environments, and billing. Cannot delete the organization.
org_member2Read the organization, its settings and billing. Create and manage workspaces, environments and deployments. Cannot invite or manage members.
org_viewer1Read-only access, including policies, workspaces, environments and billing.

Each role is backed by a group that Hexel Studio manages, such as Organization admins. The group's policies are the role's access. You can't add people to these groups or remove them yourself: change the member's role instead. To give a member more than their role allows, attach a policy to them or to one of your own groups.

The person who creates an organization is its first owner.

Rank rules

Ranks control who can manage whom:

  • Assigning a role. The role you assign must rank below your own. An admin can assign org_member and org_viewer. An owner can also assign org_admin. Nobody can assign org_owner with a role change, because no role ranks above it. An owner makes someone an owner by transferring ownership.
  • Changing or removing a member. You must outrank the member's current role. Two exceptions: an owner can change or remove any member, including another owner, and anyone can lower or remove their own membership.
  • The last owner. An organization always keeps at least one owner. Removing or demoting the only owner fails with 409 last_owner.

A request that breaks a rank rule fails with 403:

JSON
{ "error": "cannot assign role equal or higher than your own" }
JSON
{ "error": "cannot change a member whose role is equal to or higher than your own" }

Required permissions

OperationPermission
List membersorg:org:read
Add a member, or create, list, resend and revoke invitationsorg:member:invite
Change a member's role, or remove a member (including yourself)org:member:manage

By default, owners and admins hold all three. Members and viewers hold only org:org:read.

List members

Bash
curl https://api.hexelstudio.com/v1/organizations/$ORG_ID/members \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is an array of memberships:

JSON
[
  {
    "id": "<member-id>",
    "organization_id": "<org-id>",
    "user_id": "<user-id>",
    "role": "org_admin",
    "status": "ACTIVE",
    "joined_at": "2026-10-01T09:30:00Z",
    "created_at": "2026-10-01T09:30:00Z",
    "updated_at": "2026-10-01T09:30:00Z"
  }
]

The id is the membership ID. Use it to change or remove the member. It is not the user ID.

To include each member's profile, call /members/enriched. Each entry has the same fields plus email, display_name, first_name, last_name and profile_image_url when the profile has them.

Bash
curl https://api.hexelstudio.com/v1/organizations/$ORG_ID/members/enriched \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Invite people

Create an invitation

curl -X POST https://api.hexelstudio.com/v1/organizations/$ORG_ID/invitations \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "teammate@example.com"}'
emailstringbodyrequired

The address to send the invitation to.

The response is 201 Created with the invitation:

JSON
{
  "id": "<invitation-id>",
  "organization_id": "<org-id>",
  "email": "teammate@example.com",
  "invited_by_user_id": "<your-user-id>",
  "role_name": "",
  "role_id": "",
  "invitation_token": "<invitation-token>",
  "status": "PENDING",
  "expires_at": "2026-10-27T09:30:00Z",
  "created_at": "2026-10-20T09:30:00Z"
}

Hexel Studio emails the address a link to the console. The person signs in with their Hexel account and accepts. An invitation expires 7 days after it is created or last resent.

Accept an invitation

The console accepts the invitation when the person follows the link. To accept through the API, call this endpoint with an access token for the person's own account. The token does not have to be for the inviting organization.

Bash
curl -X POST https://api.hexelstudio.com/v1/invitations/<invitation-token>/accept \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is the new membership. The person joins with the org_member role. An owner or admin can then change the role.

Accepting fails with 400 when the token is unknown, already used, revoked or expired, and with 403 quota_exceeded when the organization is at its member limit.

Look up an invitation

Before accepting, the person can see what the invitation is for. Call this endpoint with an access token for the person's own account:

Bash
curl https://api.hexelstudio.com/v1/invitations/<invitation-token> \
  -H "Authorization: Bearer $ACCESS_TOKEN"
JSON
{
  "organization": { "id": "org_...", "name": "Acme" },
  "role": "org_member",
  "email": "dev@example.com",
  "status": "PENDING",
  "expires_at": "2026-10-31T12:00:00Z",
  "created_at": "2026-10-24T12:00:00Z",
  "invited_by": { "user_id": "...", "name": "Jane Doe" }
}

status is PENDING, ACCEPTED, REJECTED, EXPIRED or REVOKED; a pending invitation past its expiry reads EXPIRED. Like accepting, anyone signed in who has the link can look it up. The response never includes the token. An unknown token returns 404.

List invitations

Bash
curl https://api.hexelstudio.com/v1/organizations/$ORG_ID/invitations \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The list includes invitations in every state. status is one of:

StatusMeaning
PENDINGSent and not yet accepted.
ACCEPTEDThe person joined. accepted_at is set.
REVOKEDYou revoked it. revoked_at is set.
EXPIREDIt passed expires_at without being accepted. Hexel Studio marks expired invitations once an hour; an invitation past expires_at can't be accepted even before it is marked.

Resend an invitation

Resending emails the link again and moves expires_at to 7 days from now. Only pending invitations can be resent.

Bash
curl -X POST https://api.hexelstudio.com/v1/organizations/$ORG_ID/invitations/<invitation-id>/resend \
  -H "Authorization: Bearer $ACCESS_TOKEN"
JSON
{ "message": "invitation resent", "expires_at": "2026-10-27T09:30:00Z" }

Revoke an invitation

Bash
curl -X POST https://api.hexelstudio.com/v1/organizations/$ORG_ID/invitations/<invitation-id>/revoke \
  -H "Authorization: Bearer $ACCESS_TOKEN"
JSON
{ "message": "invitation revoked" }

Only pending invitations can be revoked. Anything else returns 404 with "invitation not found or not pending".

Add a member directly

If the person already has a Hexel account, you can add them with their user ID and a role. You need org:member:invite, and the role must rank below your own.

Bash
curl -X POST https://api.hexelstudio.com/v1/organizations/$ORG_ID/members \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "<user-id>", "role": "org_member"}'
user_idstringbodyrequired

The person's Hexel user ID. The account must exist.

rolestringbodyrequired

One of org_viewer, org_member or org_admin. Any other value returns 400 with "invalid role".

The response is 201 Created with the membership.

Change a member's role

Bash
curl -X PATCH https://api.hexelstudio.com/v1/organizations/$ORG_ID/members/<member-id> \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role": "org_viewer"}'
rolestringbodyrequired

The new role. It must rank below your own.

The response is the updated membership. The member's access changes right away: Hexel Studio moves them to the group for the new role.

Demoting the organization's only owner fails:

JSON
{
  "error": "last_owner",
  "message": "the organization must keep at least one owner"
}

Transfer ownership

An owner makes another member an owner. By default you become an admin in the same step, so the organization always has an owner:

Bash
curl -X POST https://api.hexelstudio.com/v1/organizations/$ORG_ID/transfer-ownership \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"member_id": "<member-id>"}'
member_idstringbodyrequired

The membership ID of the new owner, from List members. They must already be a member of the organization.

keep_ownershipbooleanbody

Stay an owner yourself, so the organization has two owners. Defaults to false.

The response has both memberships (shortened here):

JSON
{
  "previous_owner": { "id": "mem_...", "user_id": "...", "role": "org_admin" },
  "new_owner": { "id": "mem_...", "user_id": "...", "role": "org_owner" }
}

Both members' access changes right away. Only an owner can transfer ownership; anyone else gets 403 not_owner. Naming yourself fails with 400 transfer_to_self, and a member of another organization returns 404.

Transfer ownership before you leave an organization you own, or before you delete your account.

Remove a member

Bash
curl -X DELETE https://api.hexelstudio.com/v1/organizations/$ORG_ID/members/<member-id> \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is 204 No Content. To leave an organization, remove your own membership. This also needs org:member:manage. Removing the only owner fails with 409 last_owner.

Hexel Studio has no separate suspend for members. To cut off a person's access, remove them.

What happens to their access

When you remove a member, Hexel Studio:

  • Deletes the membership and the person's workspace memberships in the organization.
  • Removes all of their access in the organization: every group they belong to (their member role's group, the Default Team and your own groups), policies attached to them directly, permission-set assignments, permission boundaries, temporary credentials and open just-in-time requests.
  • Keeps the service users they created, because those belong to the organization, and keeps the audit history.
  • Stops issuing and refreshing access tokens for the organization to them. An access token they already hold stays valid until it expires. See Tokens.

If you invite them again later, they start with only the access of their new member role.

Member limits

Two plan limits apply. See Limits for your plan's values.

LimitWhat counts
members_per_orgMembers plus pending invitations. Creating an invitation or adding a member fails when the total has reached the limit. Accepting an invitation counts members only, because the invitation already held a place.
invitations_per_dayInvitations created or resent in the last 24 hours.

A request over a limit fails with 403:

JSON
{
  "error": "quota_exceeded",
  "quota_key": "members_per_org",
  "limit": 5,
  "current": 5,
  "message": "plan limit reached: this organization can have at most 5 members, including pending invitations; upgrade the plan or contact Hexel"
}

Revoke pending invitations you no longer need to free their places.