Roles, members and user groups
Invite your team, pick a base role for each person, build custom roles per module, group people and check what someone can do.
Each member of a workspace has a base role. A custom role starts from a base role and adds or removes scopes. A user group gives one custom role to many people.
What you need first
To invite people or change their base role: an owner or admin signed in to the web app.
For custom roles and groups through the API: a key with
members:write(members:readto look only).
1. Invite people
Invites and base-role changes are made in the web app, under Settings → Members. With an API key those calls answer 403 and say a signed-in user is needed.
The base roles:
Role | Can do |
|---|---|
| Everything |
| Build and send campaigns, journeys, templates, forms and newsletters; read analytics and settings |
| Prospects, sequences, contacts and sends; read segments, templates and analytics |
| Read everything and build reports and dashboards |
| Read only, without connections, integrations or settings |
List members with GET /v1/members.
2. See the permission grid
curl -s "$BASE/v1/roles/matrix" -H "Authorization: Bearer $HERMETICA_API_KEY"You get every base and custom role, with read and write per module.
3. Create a custom role
curl -s -X POST "$BASE/v1/roles" \
-H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"GTM Operator","baseRole":"marketer","grant":["campaigns:approve"],"deny":["connections:read"]}'
# 201, with the role's effective scopesbaseRolecannot beowner.You can only grant scopes you hold yourself. Anything else answers
403"Cannot grant scope you lack".A second role with the same name answers
409.
Tune it one module at a time:
curl -s -X PUT "$BASE/v1/roles/<roleId>/matrix" \
-H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
-d '{"matrix":{"segments":{"read":true,"write":true}}}'4. Give it to a person
curl -s -X PUT "$BASE/v1/members/<userId>/custom-role" \
-H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
-d '{"roleId":"<roleId>"}'Send {"roleId":null} to go back to the base role. Owners cannot take a custom role (412).
5. Or give it to a group
curl -s -X POST "$BASE/v1/user-groups" \
-H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"GTM team","customRoleId":"<roleId>","userIds":["<userId>"]}'Limit what the group sees with PUT /v1/user-groups/<groupId>/access. A role that a group still uses cannot be deleted (412 "Role is still used by a user group"); move the group first.
6. Check what someone can do
curl -s "$BASE/v1/members/by-email/maya@example.com/permissions" -H "Authorization: Bearer $HERMETICA_API_KEY"This shows the effective scopes after base role, custom role and group.
See who changed what
Every role and member change is in the audit log:
curl -s "$BASE/v1/audit?targetType=custom_role&limit=50" -H "Authorization: Bearer $HERMETICA_API_KEY"It needs audit:read. Filter with action (for example role.created) and from (an ISO time such as 2026-11-01T00:00:00Z), and continue with &cursor=<nextCursor>. GET /v1/audit/export?format=csv (or ndjson) exports it.
Next: Billing and plans.