Users

Run in Postman
Import the SparkPost API as a Postman collection

The Users API lets you list, invite, update, and remove the users on your account, and manage each user's subaccount access, using an API key rather than the web app.

Prerequisites

To call the Users API, an API key must hold one of two grants, and an admin must attach the grant to the key through the web app's API Keys page. A grant cannot be attached by another API key. Both are api_key-role grants.

  • Users: View — read-only access, covering the GET endpoints only: List Users, Retrieve a User, and List Pending Invites.

  • Users: Manage — full management. Every write endpoint (invite, update, delete, and the subaccount-mapping changes) requires this grant.

Requests made with a key that holds neither grant, or that attempt a write with only Users: View, are rejected with 403 Forbidden.

Roles

When you invite or update a user you assign a role through the access_level field. The primary-account roles are:

RoleDescription
adminFull access to the account, including user and billing management.
developerAccess to sending and configuration APIs, without account administration.
reportingRead-only access to reporting and analytics.
templatesAccess limited to managing templates.
customA role whose permissions are defined by the access_policies you supply.

Subaccount access levels (used only in the subaccounts array and in the subaccount-mapping endpoints) are subaccount_reporting and subaccount_developer.

Constraints

The following rules are enforced on every Users API request. They protect against privilege escalation and account lockout:

  • Role ceiling. You can never create or invite a user, or raise a user to a role, more privileged than the role of the user who owns the API key. An admin-owned key can assign up to admin; a key owned by a less-privileged user is bounded by that user's role.

  • Last admin protection. The last admin on an account cannot be deleted or demoted through the API. Such a request is rejected with 400.

  • Key revocation on owner deletion. If the admin user who owns a key holding the Users: Manage grant is deleted, that key is revoked rather than reassigned to another user.

User object

Returned by List Users.

User

name string

The user's display name, derived from their first and last name.

username string

Unique username that identifies the user.

email string

The user's email address.

access enum

The user's primary-account role. Empty for subaccount-scoped users.

Possible Values: admin, developer, reporting, templates, custom

access_policies array

The policies granted to the user when access is custom.

is_sso boolean

Whether the user signs in via single sign-on.

email_verified boolean

Whether the user has verified their email address.

tfa_enabled boolean

Whether the user has two-factor authentication enabled.

subaccount_id number

The subaccount the user is scoped to, if any.

subaccounts array, value is [{}]

The subaccounts a subaccount-scoped user has access to, and their access level on each. Present only for subaccount-scoped users.

options object

User-level options, present only when set.

Retrieved user object

Returned by Retrieve a User. This is a richer shape than the User object returned by List Users: it has first_name and last_name in place of name, uses access_level for the primary-account role, and adds created, updated, and an always-present subaccounts array.

RetrievedUser

username string

Unique username that identifies the user.

first_name string

The user's first name.

last_name string

The user's last name.

email string

The user's email address.

access_level enum

The user's primary-account role. Omitted for subaccount-scoped users.

Possible Values: admin, developer, reporting, templates, custom

access_policies (array) - The policies granted to the user when `access_level` is `custom`. string
subaccount_id number

The subaccount the user is scoped to, if any. Omitted when subaccounts is non-empty.

is_sso boolean

Whether the user signs in via single sign-on.

email_verified boolean

Whether the user has verified their email address.

tfa_enabled boolean

Whether the user has two-factor authentication enabled.

options object

User-level options, present only when set.

created string

ISO 8601 timestamp of when the user was created.

updated string

ISO 8601 timestamp of when the user was last updated.

subaccounts array, value is [{}]

The subaccounts the user has access to, and their access level on each. Always present; an empty array for a user with no subaccount mappings. When it is non-empty, the top-level access_level and subaccount_id fields are omitted.

Invite object

Returned by List Pending Invites.

Invite

id string

Unique ID for the pending invite. Use it to revoke the invite.

email string

The email address the invite was sent to.

from string

The email address of the user who created the invite.

access_level enum

The role the invited user will be assigned when they register.

Possible Values: admin, developer, reporting, templates, custom

expires number

Unix timestamp, in epoch seconds, at which the invitation expires.

Invite lifecycle

  • Invitations expire after 3 days. Once an invitation expires, its registration link no longer works.

  • Expired invitations are removed automatically. They stop appearing in List Pending Invites once they expire; you do not need to clean them up.

  • There is no resend. To give someone another chance to register, invite the same email address again. This creates a new, independent invitation with its own token and expiry; the earlier invitation keeps working until it expires or you revoke it.

  • Invite creation is rate limited. If you create invitations too quickly, requests are rejected with 429 Too Many Requests. Wait before retrying.

Request

GET /api/v1/users

Response

{
  "results": [
    {
      "name": "Ada Lovelace",
      "username": "ada",
      "email": "ada@example.com",
      "access": "admin",
      "is_sso": false,
      "email_verified": true,
      "tfa_enabled": false
    },
    {
      "name": "Grace Hopper",
      "username": "grace",
      "email": "grace@example.com",
      "access": "reporting",
      "is_sso": false,
      "email_verified": true,
      "tfa_enabled": true
    }
  ]
}
{
  "errors": [
    {
      "message": "Forbidden"
    }
  ]
}

List Users

GET/api/v1/users

Returns the users on your account.

Request

GET /api/v1/users/grace

Response

{
  "results": {
    "username": "grace",
    "first_name": "Grace",
    "last_name": "Hopper",
    "email": "grace@example.com",
    "access_level": "reporting",
    "is_sso": false,
    "email_verified": true,
    "tfa_enabled": true,
    "created": "2015-01-11T08:00:00.000Z",
    "updated": "2018-04-11T08:00:00.000Z",
    "subaccounts": []
  }
}
  A subaccount-scoped user.

  {
      "results": {
          "username": "joe",
          "first_name": "Joe",
          "last_name": "Mechanic",
          "email": "joe@example.com",
          "is_sso": false,
          "email_verified": true,
          "tfa_enabled": false,
          "created": "2015-01-11T08:00:00.000Z",
          "updated": "2018-04-11T08:00:00.000Z",
          "subaccounts": [
              {
                  "subaccount_id": 123,
                  "subaccount_name": "Joe's Garage",
                  "access_level": "subaccount_reporting",
                  "status": "active"
              }
          ]
      }
  }
{
  "errors": [
    {
      "message": "User does not exist"
    }
  ]
}

Retrieve a User

GET/api/v1/users/{username}

Parameters

username string required

Returns a single user by username. The response uses the Retrieved user object shape, which differs from the User object returned by List Users.

Request

POST /api/v1/users/invite
{
  "email": "newuser@example.com",
  "access_level": "reporting"
}

Response

{
  "results": {
    "id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
    "token": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
  }
}
{
  "errors": [
    {
      "message": "email is a required parameter",
      "param": "email",
      "value": null
    }
  ]
}
{
  "errors": [
    {
      "message": "Forbidden"
    }
  ]
}
{
  "errors": [
    {
      "message": "Too many invite requests. Please try again later."
    }
  ]
}

Invite a User

POST/api/v1/users/invite

There is no direct, password-based user creation through the API — users are created by invitation only. This endpoint creates an invitation and emails the invitee a registration link; the invitee completes registration through that link and sets their own password. The invited user's role is set by access_level and is bounded by the role ceiling.

Provide access_level for a primary-account user, or subaccounts to invite a subaccount-scoped user. When subaccounts is supplied, a top-level access_level is not required.

The response contains the invite token.

  • Data Structure

    • email (string, required) - Email address of the person to invite. Max length: 512 characters.
    • access_level (enum) - The primary-account role to assign. Required unless subaccounts is supplied.

      • admin
      • developer
      • reporting
      • templates
      • custom
    • access_policies (array) - The policies to grant. Only valid when access_level is custom.
    • subaccounts (array) - Invite the user with access to one or more subaccounts instead of the primary account. Between 1 and 25 entries.

      • (object)

        • subaccount_id (number, required) - The subaccount ID.
        • access_level (enum, required) - The subaccount access level.

          • subaccount_reporting
          • subaccount_developer

Request

GET /api/v1/users/pending-invites

Response

{
  "results": [
    {
      "id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
      "email": "newuser@example.com",
      "from": "ada@example.com",
      "access_level": "reporting",
      "expires": 1720656000
    }
  ]
}

List Pending Invites

GET/api/v1/users/pending-invites

Returns the invitations on your account that have not yet been accepted. Expired invitations are not included.

Request

DELETE /api/v1/users/pending-invites/3f2504e0-4f89-41d3-9a0c-0305e82c3301

Response

// Empty response body
{
  "errors": [
    {
      "message": "User invite ID does not exist"
    }
  ]
}

Revoke a Pending Invite

DELETE/api/v1/users/pending-invites/{id}

Parameters

id string required

Revokes a pending invitation so its registration link can no longer be used.

Request

PUT /api/v1/users/grace
{
  "access_level": "developer"
}

Response

{
  "results": {
    "message": "Successfully modified user grace"
  }
}
{
  "errors": [
    {
      "message": "Cannot change the access level of the last admin user on the account."
    }
  ]
}
{
  "errors": [
    {
      "message": "Forbidden"
    }
  ]
}

Update a User

PUT/api/v1/users/{username}

Parameters

username string required

Changes a user's role. The request accepts only access_level (and access_policies when access_level is custom); a request that contains any other field is rejected with 403 Forbidden.

Changing access_level is subject to the role ceiling, and demoting the account's last admin is rejected with 400.

  • Data Structure

    • access_level (enum, required) - The primary-account role to assign.

      • admin
      • developer
      • reporting
      • templates
      • custom
    • access_policies (array) - The policies to grant. Required when access_level is custom, and not allowed otherwise.

Request

DELETE /api/v1/users/grace

Response

// Empty response body
{
  "errors": [
    {
      "message": "Cannot delete the last admin user on the account."
    }
  ]
}
{
  "errors": [
    {
      "message": "Forbidden"
    }
  ]
}
{
  "errors": [
    {
      "message": "User does not exist"
    }
  ]
}

Delete a User

DELETE/api/v1/users/{username}

Parameters

username string required

Deletes a user from your account.

You cannot delete the user who owns the API key you are calling with, a user that belongs to a different account, or the account's last admin.

Request

POST /api/v1/users/grace/subaccounts
{
  "subaccount_id": 123,
  "access_level": "subaccount_reporting"
}

Response

{
  "results": {
    "message": "Subaccount access granted"
  }
}
{
  "errors": [
    {
      "message": "access_level must be one of: subaccount_reporting, subaccount_developer"
    }
  ]
}

Add a Subaccount Mapping

POST/api/v1/users/{username}/subaccounts

Parameters

username string required

Grants a user access to a subaccount at the given access level. If the user already has access to the subaccount, the access level is updated.

  • Data Structure

    • subaccount_id (number, required) - The subaccount to grant access to.
    • access_level (enum, required) - The access level to grant on the subaccount.

      • subaccount_reporting
      • subaccount_developer

Request

DELETE /api/v1/users/grace/subaccounts/123

Response

// Empty response body

Remove a Subaccount Mapping

DELETE/api/v1/users/{username}/subaccounts/{subaccountId}

Parameters

username string required
subaccountId number required

Removes a user's access to a subaccount.