Skip to main content
For AI agents: a documentation index is available at https://docs.coverbase.com/llms.txt — this page is also available in markdown by appending .md to the URL.
The Users API provisions Coverbase accounts and manages their organization role and lifecycle. It is designed for identity-governance (SailPoint / IGA) integrations: the upstream system owns approval, this API creates the account + org membership so SSO can authenticate the user on first login.
Provisioning creates the Coverbase account and an org membership in invited status. It does not create a login session — the user is linked to your IdP by email on first SSO. SailPoint owns the upstream approval; this API only reflects role/lifecycle into Coverbase.
All endpoints are org-scoped to the API key. See API conventions for shared behavior.
MethodPathIdempotent
POST/v1/usersYes (Idempotency-Key)
GET/v1/users
GET/v1/users/{user_id}
PATCH/v1/users/{user_id}No
Syncing relationship owners, watchers, or risk analysts from an external system (e.g. ServiceNow)? Those vendor/service fields take Coverbase user IDs, not emails. Use GET /v1/users?email= to resolve an email to its cbuser_... ID, and POST /v1/users to create the user if they don’t exist yet — it returns the existing user if they do.

Org roles

The role field uses these values:
ValueRole
org:adminAdmin
org:memberMember
org:siloed_memberSiloed member
org:guestGuest
org:auxiliary_memberAuxiliary member
org:service_accountService account
The aliases member, basic_member, org:basic_member (→ org:member) and admin (→ org:admin) are also accepted. Any other value is rejected with 422.

Provision a user (create-or-get)

method
POST
POST /v1/users
Creates the account + org membership (invited), or returns the existing user. Returns 201 Created on create, or 200 OK if a user with that email already exists in the org — so this call is safe to use as create-if-missing and always yields the user’s cbuser_... ID.
Idempotent create-or-get: a same-org email match returns 200 with the existing user (not 409). A 409 user_exists is only returned when the email belongs to a user in a different org (emails are globally unique). The email match is case-insensitive.

Request body

email
string
required
The user’s email — validated as a proper email address. Used to link the account to your IdP on first SSO.
first_name
string
Given name.
last_name
string
Family name.
role
string
One of the org role values. Defaults to org:member.

Headers

Authorization
string
required
Bearer ak_...
Idempotency-Key
string
Optional. Replaying the same key within 24 hours returns the original 201 body. See Idempotency.

Example request

curl -X POST "https://sandbox.api.coverbase.app/v1/users" \
  -H "Authorization: Bearer ak_live_xxx" \
  -H "Idempotency-Key: acme-user-jordanlee" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jordan.lee@example.com",
    "first_name": "Jordan",
    "last_name": "Lee",
    "role": "org:admin"
  }'

Example response

201 Created (new user), or 200 OK (existing user — the stored object, whose status is its current membership state such as active):
{
  "id": "cbuser_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
  "email": "jordan.lee@example.com",
  "first_name": "Jordan",
  "last_name": "Lee",
  "role": "org:admin",
  "status": "invited",
  "is_archived": false,
  "created_at": 1746576000,
  "updated_at": 1746576000
}

User object

id
string
User ID (cbuser_...).
email
string
User email.
first_name
string | null
Given name.
last_name
string | null
Family name.
role
string | null
Org role value for this org (e.g. org:admin).
status
string | null
Org membership status: invited, active, or inactive.
is_archived
boolean
true once the user is deprovisioned.
created_at
integer
Unix timestamp (seconds).
updated_at
integer
Unix timestamp (seconds).

Error responses

StatusBodyWhen
409{"detail": {"code": "user_exists", "message": "A user with email ... already exists."}}The email belongs to a user in a different org (emails are globally unique). A same-org match now returns 200 with the existing user, not 409.
422Standard validation erroremail missing or not a valid email address, or role not a recognized value.

List users and look up by email

method
GET
GET /v1/users
Lists the org’s users, or resolves a single user by email. This is the supported way to build an email → user ID mapping when syncing assignments (relationship owners, watchers, risk analysts) from an external system such as ServiceNow — those fields take Coverbase user IDs, so resolve the email here first.

Query parameters

email
string
Case-insensitive exact-match lookup. Returns the matching user (even if archived, so it can be reactivated) or an empty list. Uses the same matching as the POST /v1/users duplicate check, so any email that exists is resolvable to its user ID. When supplied, include_archived/limit/offset are ignored.
include_archived
boolean
Include deprovisioned (archived) users in the list. Defaults to false.
limit
integer
Page size, 1200. Defaults to 50.
offset
integer
Number of users to skip, for paging. Defaults to 0.

Headers

Authorization
string
required
Bearer ak_...

Example: resolve a user by email

curl -X GET "https://sandbox.api.coverbase.app/v1/users?email=jordan.lee@example.com" \
  -H "Authorization: Bearer ak_live_xxx"

Example response

200 OK:
{
  "items": [
    {
      "id": "cbuser_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
      "email": "jordan.lee@example.com",
      "first_name": "Jordan",
      "last_name": "Lee",
      "role": "org:admin",
      "status": "active",
      "is_archived": false,
      "created_at": 1746576000,
      "updated_at": 1746576000
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

Response fields

items
object[]
Page of user objects. role and status reflect each user’s membership in the API key’s org.
total
integer
Total matching users in the org (for an email lookup this is 0 or 1).
limit
integer
Echo of the requested page size.
offset
integer
Echo of the requested offset.
To create-if-missing and always end up with the user’s ID: look up the email here, and if items is empty call POST /v1/users to provision them — or just call POST /v1/users directly, which returns the existing user (200) when the email is already present.

Retrieve a user

method
GET
GET /v1/users/{user_id}
Returns the user. The user must have a membership in the API key’s org.
cURL
curl -X GET "https://sandbox.api.coverbase.app/v1/users/cbuser_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
  -H "Authorization: Bearer ak_live_xxx"
Returns the user object. role and status reflect the current org membership.
StatusBodyWhen
404{"detail": {"code": "user_not_found", "message": "User not found."}}No such user, or the user has no membership in the API key’s org.

Update role / deprovision

method
PATCH
PATCH /v1/users/{user_id}
Changes a user’s org role and/or (de)provisions them. Returns the refreshed user object.

Request body

role
string
New org role (one of the role values). Omit to leave unchanged.
is_archived
boolean
true deprovisions: archives the user and sets org membership to inactive. false reactivates: membership back to active. Omit to leave unchanged.

Examples

Change role
curl -X PATCH "https://sandbox.api.coverbase.app/v1/users/cbuser_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
  -H "Authorization: Bearer ak_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "role": "org:member" }'
Deprovision
curl -X PATCH "https://sandbox.api.coverbase.app/v1/users/cbuser_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
  -H "Authorization: Bearer ak_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "is_archived": true }'

Behavior

  • is_archived: true → user archived, membership inactive.
  • is_archived: false → membership active (reactivation).
  • role set → membership role updated.
  • Combined (role + is_archived) is applied together.

Error responses

StatusBodyWhen
404{"detail": {"code": "user_not_found", "message": "User not found."}}No membership for this user in the API key’s org.
422Standard validation errorrole not a recognized value.