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

RoleAssignable via APIAccess
ownerNoThe 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.
adminYesPasses all role checks: profile management, user management, and read operations.
developerYesPasses 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.
billingYesPasses 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, or rejected status fail role checks. Only active users count, including toward the rule that protects the last active admin.

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.

OperationRequired role403 AUTH_004 message
POST /v3/profilesadmin (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/usersadmin"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/usersAny 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 sectionRoles with access
OverviewAll roles
Templates, Playground, Contactsowner, admin, developer
Profilesowner, admin
Number Lookupowner, admin, developer
Activities, API Keys, Webhooksowner, admin, developer
Complianceowner, admin
Channels, Settingsowner, admin, developer
Usersowner, admin
Billingowner, 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.

ConditionResult
Organization key + UUID of one of its profilesThe request executes as that profile. The response echoes the X-Profile-Id header.
Profile API key + x-profile-id403 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 UUID400 VALIDATION_003
Profile does not exist or belongs to another organization404 RESOURCE_013: "Profile not found."
Header equals the caller's own account IDIgnored (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 neededSource
Which account the API key belongs toGET /v3/me returns the account, including its type: organization, user, or profile.
Which users exist and their rolesGET /v3/users lists all users of the organization or profile with role and status. Callable by any active role.
Who can grant accessThe 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"
  }
}

On this page