Roles and Permissions
The Sent platform defines four user roles for organizations and Sender Profiles: owner, admin, developer, and billing. Roles gate a small set of API operations (profile management and user management) and sections of the Sent Dashboard. A request that fails a role check returns HTTP 403 with error code AUTH_004.
Role catalog
| Role | Assignable via API | Access |
|---|---|---|
owner | No | The account that created the organization or profile. The owner is implicit: it has no entry in the user list and satisfies every role check, including the checks that require admin. |
admin | Yes | Passes all role checks: profile management, user management, and read operations. |
developer | Yes | Passes any-role checks: reading profiles and listing users. In the dashboard, has access to development and messaging sections but not user, profile, or billing management. |
billing | Yes | Passes any-role checks: reading profiles and listing users. In the dashboard, has access to the Billing section only. |
Role values are lowercase in API requests and responses: admin, billing, developer. The owner role cannot be requested in an invitation or role update: only the original creator of the organization or profile carries it.
How the API evaluates roles
Every API key belongs to an account. Role checks are evaluated against the email address of the account that owns the API key:
- The check passes immediately when that email matches the owner email of the organization or profile being accessed.
- Otherwise, the check passes when an active user with that email exists on the organization or profile and holds an allowed role.
- For Sender Profiles, checks cascade to the parent organization: owner or role access at the organization level also grants access to its profiles.
- Users with
invited,suspended, orrejectedstatus fail role checks. Onlyactiveusers count, including toward the rule that protects the last activeadmin.
A failed check returns HTTP 403 with error.code AUTH_004 and a doc_url pointing to the authentication reference.
API operations gated by role
The following v3 operations perform a role check. All other v3 operations (messages, contacts, conversations, templates, campaigns, webhooks, number lookup, and /v3/me) require only a valid API key and are not role-gated.
| Operation | Required role | 403 AUTH_004 message |
|---|---|---|
POST /v3/profiles | admin (on the organization) | "You do not have admin access to this organization" |
PATCH /v3/profiles/{profileId} | admin | "You do not have admin access to this profile" |
DELETE /v3/profiles/{profileId} | admin | "You do not have admin access to this profile" |
GET /v3/profiles/{profileId} | Any role | "You do not have access to this profile" |
POST /v3/users | admin | "You do not have admin access to this organization or profile" |
PATCH /v3/users/{userId} | admin | "You do not have admin access to this organization or profile" |
DELETE /v3/users/{userId} | admin | "You do not have admin access to this organization or profile" |
GET /v3/users | Any role | "You do not have access to this organization or profile" |
GET /v3/users/{userId} | Any role | "You do not have access to this organization or profile" |
"Any role" means any active user of the organization or profile, regardless of role. The owner passes every check in this table.
User management enforces three hard constraints: you cannot change your own role, you cannot remove yourself, and you cannot demote or remove the last active admin.
Invitations sent with POST /v3/users expire after 7 days. Assignable roles for invitations and role updates are admin, billing, and developer.
Dashboard access by role
The dashboard gates its sections by the signed-in user's role:
| Dashboard section | Roles with access |
|---|---|
| Overview | All roles |
| Templates, Playground, Contacts | owner, admin, developer |
| Profiles | owner, admin |
| Number Lookup | owner, admin, developer |
| Activities, API Keys, Webhooks | owner, admin, developer |
| Compliance | owner, admin |
| Channels, Settings | owner, admin, developer |
| Users | owner, admin |
| Billing | owner, admin, billing |
Organization keys and the x-profile-id header
Every v3 operation accepts the optional x-profile-id request header (a profile UUID). It scopes the request to a child profile, so an organization API key can act on behalf of one of its profiles.
| Condition | Result |
|---|---|
| Organization key + UUID of one of its profiles | The request executes as that profile. The response echoes the X-Profile-Id header. |
Profile API key + x-profile-id | 403 AUTH_004: "Profile API keys cannot use x-profile-id. Only organization API keys can act on behalf of profiles." |
| Header value is not a valid UUID | 400 VALIDATION_003 |
| Profile does not exist or belongs to another organization | 404 RESOURCE_013: "Profile not found." |
| Header equals the caller's own account ID | Ignored (no-op) |
Role checks on a profile-scoped request are evaluated against the profile, with the usual cascade to the parent organization.
Resolving AUTH_004
AUTH_004 means the account behind the API key failed the role check for the operation. The messages in the preceding table identify which check failed. The relevant lookups:
| Fact needed | Source |
|---|---|
| Which account the API key belongs to | GET /v3/me returns the account, including its type: organization, user, or profile. |
| Which users exist and their roles | GET /v3/users lists all users of the organization or profile with role and status. Callable by any active role. |
| Who can grant access | The owner or an admin invites users with POST /v3/users and changes roles with PATCH /v3/users/{userId}. |
An account whose email is neither the owner email nor an active entry in the GET /v3/users list has no role, and fails every check in the operations table.
Example
Listing users to look up a role:
curl https://api.sent.dm/v3/users \
-H "x-api-key: YOUR_API_KEY"{
"success": true,
"data": {
"users": [
{
"id": "880e8400-e29b-41d4-a716-446655440003",
"email": "admin@acme.com",
"name": "John Admin",
"role": "admin",
"status": "active",
"invited_at": "2026-01-24T15:25:20.114144+00:00",
"last_login_at": "2026-07-24T13:25:20.1141456+00:00",
"created_at": "2026-01-24T15:25:20.1141459+00:00",
"updated_at": "2026-07-23T15:25:20.114146+00:00"
},
{
"id": "990e8400-e29b-41d4-a716-446655440004",
"email": "developer@acme.com",
"name": "Jane Developer",
"role": "developer",
"status": "invited",
"invited_at": "2026-07-22T15:25:20.1141463+00:00",
"last_login_at": null,
"created_at": "2026-07-22T15:25:20.1141464+00:00",
"updated_at": "2026-07-22T15:25:20.1141465+00:00"
}
]
},
"error": null,
"meta": {
"request_id": "req_7X9zKp2jDw",
"timestamp": "2026-07-24T15:25:20.1141776+00:00",
"version": "v3"
}
}A role-check failure returns the standard error envelope:
{
"success": false,
"data": null,
"error": {
"code": "AUTH_004",
"message": "You do not have admin access to this organization or profile",
"details": null,
"doc_url": "https://docs.sent.dm/reference/api/authentication"
},
"meta": {
"request_id": "req_7X9zKp2jDw",
"timestamp": "2026-07-24T15:25:20.1199882+00:00",
"version": "v3"
}
}Related reference
- Authentication: API keys, environments, and credential management
- Error Catalog: all error codes, including the other
AUTH_*codes - Sender Profiles: the organization and profile model
Authentication
Sent API v3 authentication reference covering the API key request header, standard response headers, and AUTH error codes with statuses and causes.
Idempotency
Idempotency-Key contract for the Sent API v3: supported methods, key format, response caching, replay headers, and concurrency behavior.