Users (team members)
Esta página aún no está disponible en tu idioma.
Users in the BenchKey API represent your team members, the people who log in to your BenchKey account. The resource exposes your shop’s staff roster: technicians, admins, the account owner, and members holding tenant-defined custom roles. Sensitive auth fields (passwords, session tokens, third-party IDs) are never exposed.
Roles are slugs, the four builtins (owner, admin, tech, viewer) plus any custom roles your workspace defines. Discover the full catalog with the Roles resource.
The user object
Section titled “The user object”{ "object": "user", "id": 42, "email": "alex@shopname.com", "role": "tech", "display_name": "Alex Rivera", "queues": [{ "id": 1, "name": "General", "is_primary": true }], "queue_ids": [1], "primary_queue_id": 1, "location_ids": []}| Field | Type | Description |
|---|---|---|
id | integer | Unique team member ID |
email | string | The team member’s login email |
role | string | The member’s role slug, a builtin (owner, admin, tech, viewer) or a custom role slug. Resolve slugs to labels via GET /roles |
display_name | string|null | Display name, or null if not set |
queues | array | Queue assignments with id, name, and is_primary per entry |
queue_ids | integer[] | IDs of assigned queues |
primary_queue_id | integer|null | The member’s primary queue ID, or null |
location_ids | integer[] | IDs of assigned locations; empty array means unrestricted access |
List users
Section titled “List users”GET /api/v1/usersReturns a cursor-paginated list of team members, sorted by id descending.
Scope required: users.read
Query parameters
Section titled “Query parameters”| Parameter | Type | Description |
|---|---|---|
role | string | Filter by role slug, a builtin (owner, admin, tech, viewer) or a custom role slug. A well-formed slug that matches no member returns an empty list; a malformed value (not lowercase letters/digits/-/_, max 64 chars) returns 400 invalid_query |
limit | integer | Page size, 1–100 (default: 25) |
cursor | string | Opaque cursor from a previous response’s next_cursor |
curl "https://app.benchkey.com/api/v1/users?role=tech" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"Node.js
Section titled “Node.js”const res = await fetch( "https://app.benchkey.com/api/v1/users?role=tech", { headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" } });const { data, has_more, next_cursor } = await res.json();Response
Section titled “Response”{ "object": "list", "data": [ { "object": "user", "id": 42, "email": "alex@shopname.com", "role": "tech", "display_name": "Alex Rivera", "queues": [{ "id": 1, "name": "General", "is_primary": true }], "queue_ids": [1], "primary_queue_id": 1, "location_ids": [] } ], "has_more": false, "next_cursor": null}See Pagination for how to page through results.
Retrieve a user
Section titled “Retrieve a user”GET /api/v1/users/:idReturns a single team member by their integer id.
Scope required: users.read
curl "https://app.benchkey.com/api/v1/users/42" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"Node.js
Section titled “Node.js”const res = await fetch( "https://app.benchkey.com/api/v1/users/42", { headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" } });const user = await res.json();Response
Section titled “Response”Returns the user object. Returns 404 if no team member with that ID exists.
Invite a user
Section titled “Invite a user”POST /api/v1/usersSends a team invite to an email address and adds them to the tenant. Seat limits and role restrictions are enforced by the platform. The owner and admin roles cannot be granted through this endpoint.
Scope required: users.write
Request body
Section titled “Request body”| Field | Required | Description |
|---|---|---|
email | yes | Email address to invite |
role | no | tech or viewer (default: tech). admin and owner cannot be granted via the API. |
curl -X POST https://app.benchkey.com/api/v1/users \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" \ -H "Content-Type: application/json" \ -d '{ "email": "sam@shopname.com", "role": "tech" }'Node.js
Section titled “Node.js”const res = await fetch("https://app.benchkey.com/api/v1/users", { method: "POST", headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa", "Content-Type": "application/json", }, body: JSON.stringify({ email: "sam@shopname.com", role: "tech" }),});const user = await res.json(); // HTTP 201Response
Section titled “Response”Returns the user object with HTTP 201.
Update a user
Section titled “Update a user”PATCH /api/v1/users/by-email/:emailUpdates a team member’s display name, queue assignments, primary queue, and/or location assignments. The :email path parameter is the team member’s login email, URL-encode it.
Scope required: team.write
Request body
Section titled “Request body”At least one field must be included:
| Field | Type | Description |
|---|---|---|
display_name | string | Display name (must be a non-null string; passing null returns 400 invalid_field) |
queue_ids | integer[] | IDs of the queues this member is assigned to (each must be a positive integer in [1, 2,147,483,647]; non-positive or out-of-range values return 400 invalid_field) |
primary_queue_id | integer | The member’s primary queue (must be a positive integer in [1, 2,147,483,647]; non-positive or out-of-range values return 400 invalid_field) |
location_ids | integer[] | IDs of the locations this member is assigned to; requires expected_revision |
expected_revision | string | Required with location_ids, invalid without it. The opaque 64-character lowercase hexadecimal token from the latest X-Team-Locations-Revision response header |
To change locations, first read the users list or the user with users.read and retain the X-Team-Locations-Revision response header. Review the current assignments, then include that token as expected_revision alongside location_ids in the PATCH body. A client with only team.write can omit the token once to receive a nonmutating 428 location_revision_required response carrying the current header, then resubmit with it.
If the update returns 409 stale_location_revision, reload the assignments and revision, review the intervening changes, and submit the intended assignments with the new token. Do not automatically overwrite another person’s changes. Updates that do not include location_ids do not need a revision.
curl -X PATCH "https://app.benchkey.com/api/v1/users/by-email/sam%40shopname.com" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" \ -H "Content-Type: application/json" \ -d '{ "display_name": "Sam Chen", "queue_ids": [1, 3] }'Node.js
Section titled “Node.js”const email = "sam@shopname.com";const res = await fetch( `https://app.benchkey.com/api/v1/users/by-email/${encodeURIComponent(email)}`, { method: "PATCH", headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa", "Content-Type": "application/json", }, body: JSON.stringify({ display_name: "Sam Chen", queue_ids: [1, 3] }), });const user = await res.json();Response
Section titled “Response”Returns the updated user object.
Change a user’s role
Section titled “Change a user’s role”PATCH /api/v1/users/by-email/:email/roleChanges a team member’s role. The owner role cannot be changed via this endpoint, and admin cannot be granted via the API. Valid target roles are tech and viewer.
Members holding custom roles are fully visible in reads (their custom slug appears in role), but assigning a custom role through the public API is not currently supported, use the Roles resource to discover the catalog, and the in-app team settings to assign custom roles.
Scope required: team.write
Request body
Section titled “Request body”| Field | Required | Description |
|---|---|---|
role | yes | New role: tech or viewer. admin and owner cannot be granted via the API. |
curl -X PATCH "https://app.benchkey.com/api/v1/users/by-email/sam%40shopname.com/role" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" \ -H "Content-Type: application/json" \ -d '{ "role": "tech" }'Node.js
Section titled “Node.js”const email = "sam@shopname.com";const res = await fetch( `https://app.benchkey.com/api/v1/users/by-email/${encodeURIComponent(email)}/role`, { method: "PATCH", headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa", "Content-Type": "application/json", }, body: JSON.stringify({ role: "tech" }), });const user = await res.json();Response
Section titled “Response”Returns the updated user object.
Remove a user
Section titled “Remove a user”DELETE /api/v1/users/:idRemoves a team member from the tenant. The account owner (role: "owner") cannot be removed.
Scope required: users.write
curl -X DELETE "https://app.benchkey.com/api/v1/users/42" \ -H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"Node.js
Section titled “Node.js”const res = await fetch("https://app.benchkey.com/api/v1/users/42", { method: "DELETE", headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" },});const result = await res.json();// { "object": "user", "id": 42, "deleted": true }Response
Section titled “Response”{ "object": "user", "id": 42, "deleted": true}Error codes
Section titled “Error codes”| HTTP status | Code | Meaning |
|---|---|---|
400 | invalid_id | The :id is not a valid positive integer |
400 | invalid_query | A list filter parameter was supplied as an array or object instead of a single scalar value |
400 | invalid_field | A field value is invalid (e.g. bad role, invalid email format, bad email path param) |
400 | missing_field | A required field (email) is absent |
400 | cannot_remove_owner | The tenant owner cannot be removed |
400 | no_fields | PATCH body contains no recognized updatable fields |
400 | permission_denied | Insufficient permissions to grant, change, or remove that role |
400 | invite_failed | Invite could not be completed, see message for details |
400 | role_change_failed | Role change was rejected by the server, see message for details |
400 | update_failed | Profile update was rejected by the server, see message for details |
400 | location_update_failed | Location assignment was rejected by the server, see message for details |
400 | feature_required | Location assignment requires the multi-location feature, which is not enabled on this plan |
404 | not_found | No team member with that ID or email exists |
402 | seat_limit_reached | Plan seat cap reached, upgrade required |
409 | already_member | The email is already a member of this team |
428 | location_revision_required | A location update omitted expected_revision; no location or profile changes were made. Read the current token from X-Team-Locations-Revision |
409 | stale_location_revision | Location assignments changed since the supplied revision. Reload and review before resubmitting |
403 | insufficient_scope | API key lacks users.read, users.write, or team.write |
See Errors for the full error envelope format.