> This page is for Developer Documentation.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.benchling.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.benchling.com/_mcp/server.

# Find Users Using the V3 SDK

This recipe uses the [V3 API](/docs/v3-api-overview) through the
[V3 Python SDK](/docs/getting-started-with-the-v3-sdk). For creating, suspending, and reactivating
users, see [User Management via the API](/docs/user-management-via-the-api).

> **Info**
>
> The V3 user endpoints are beta. Set `early_access="true"` on the client, as in the example below,
> or send the `EARLY-ACCESS: true` header on raw HTTP requests. See the
> [V3 Stability Guidelines](/docs/stability-guidelines).

#### SDK boilerplate

Import the V3 SDK and instantiate the client. Pass your tenant's root URL and your API key; the
SDK adds `/api/v3` itself.

**`Python (lines 1-7)`**

```python Python (lines 1-7)
from benchling_v3_sdk import Benchling

benchling = Benchling(
    base_url="https://yourcompany.benchling.com",
    api_key="<your-api-key>",
    early_access="true",
)
```

#### Look a user up with user.list()

`user.list()` returns a pager that fetches pages as you iterate it. How you find the user
depends on what you already know about them.

**By username**

`user.list()` has no username filter, so this walks the users and compares `username` on each
one. `page_size=100` is the maximum and keeps the number of requests down.

**`Python (lines 9-15)`**

```python Python (lines 9-15)
username = "benchlingsupport"
def username_to_id(username):
    for user in benchling.user.list(page_size=100):
        if user.username == username:
            return user.id
    return None
print(username_to_id(username))
```

**By display name**

`name_any_of_case_sensitive` takes a list of full display names as they appear in Benchling.
`next(iter(...), None)` returns the first match, or `None` if there isn't one. Use
`name_any_of` instead for a case-insensitive match.

**`Python (lines 17-22)`**

```python Python (lines 17-22)
name = "Benchling Support"
def name_to_id(name):
    user = next(iter(benchling.user.list(name_any_of_case_sensitive=[name])), None)
    return user.id if user else None
print(name_to_id(name))

```

#### Look a user up by API ID

Going the other direction, `user.get()` takes an API ID and returns the user, so you can read
their username off it. This is a direct fetch rather than a filtered list, so there is no pager
to iterate.

**`Python (lines 24-27)`**

```python Python (lines 24-27)
def id_to_username(api_id):
    user = benchling.user.get(api_id)
    return user.username
print(id_to_username(api_id))
```

#### Complete files

**`Python`**

```python title="Python"
from benchling_v3_sdk import Benchling

benchling = Benchling(
    base_url="https://yourcompany.benchling.com",
    api_key="<your-api-key>",
    early_access="true",
)

username = "benchlingsupport"
def username_to_id(username):
    for user in benchling.user.list(page_size=100):
        if user.username == username:
            return user.id
    return None
print(username_to_id(username))

name = "Benchling Support"
def name_to_id(name):
    user = next(iter(benchling.user.list(name_any_of_case_sensitive=[name])), None)
    return user.id if user else None
print(name_to_id(name))

api_id = "ent_FooBar"
def id_to_username(api_id):
    user = benchling.user.get(api_id)
    return user.username
print(id_to_username(api_id))
```

**`Response Example`**

```json title="Response Example"
{
  "__typename": "User",
  "createdAt": "2020-01-01T00:00:00.000000+00:00",
  "email": "benchlingsupport@benchling.com",
  "id": "ent_JsTCtLxb",
  "lastSeen": "2026-09-01T00:00:00.000000+00:00",
  "modifiedAt": "2026-09-01T00:00:00.000000+00:00",
  "name": "Benchling Support",
  "status": "ACTIVE",
  "username": "benchlingsupport"
}
```

## What changed from V2

| V2                                    | V3                                                                                                        |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `benchling.users.list(handles=[...])` | No username filter. Iterate `benchling.user.list()` and compare `username`.                               |
| `benchling.users.list(name=...)`      | `benchling.user.list(name_any_of=[...])` or `name_any_of_case_sensitive=[...]`, up to 100 names per call. |
| `benchling.users.get_by_id(id)`       | `benchling.user.get(id)`                                                                                  |
| `handle`                              | `username`                                                                                                |
| `isSuspended: true` / `false`         | `status: "SUSPENDED"` / `"ACTIVE"`                                                                        |

The other filters on `user.list()` are `id_any_of` and the `modified_at_*` range filters. There is
no filter on email or status, so filter on those client-side.