---
updatedAt: 2026-09-09T19:27:00.000Z
---

Fetch the complete documentation index at: https://docs.benchling.com/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Authentication

Learn which authentication methods the Benchling API supports for apps and automation, and when to use each one. This page covers app credentials, Delegated Auth, personal API keys, and the setup details needed to make secure requests to Benchling.

> ### 📘 Protecting your API credentials
>
> Keep API credentials in a password manager or your organization's secrets manager. Never commit API keys or client secrets to source control — use environment variables or a secrets management service instead. If you leak a key, rotate it immediately: personal API keys can be rotated in Profile Settings; app client secrets can be rotated in the Developer Console.

## Authentication Methods

This page covers authenticating to the Benchling public API. It does not cover how people sign in to the Benchling web application — username and password, SAML, and Google OAuth are configured by tenant administrators and are not covered here.

Every API call is tied to a user or an app. Anything a user can do in the Benchling UI, their API key can do via the API; apps follow the same model, and an app's OAuth token can do anything the app has been permissioned to do.

Benchling supports four API authentication methods. Jump to [Which one should I use?](#which-one-should-i-use) if you want a quick recommendation.

| Method                             | Best for                                                                      |
| ---------------------------------- | ----------------------------------------------------------------------------- |
| **OAuth Bearer (App credentials)** | Apps and automation acting as themselves                                      |
| **Delegated Auth**                 | Apps acting on behalf of the currently signed-in user                         |
| **Basic Auth (API key)**           | Generally discouraged; available for temporary uses like trying out a new API |
| **OIDC**                           | Legacy — existing implementations only                                        |

## OAuth Bearer Authentication (App Credentials)

Benchling Apps authenticate using the OAuth 2.0 client credentials grant type. Request a token with your app's client ID and secret, then send it as a Bearer token on every subsequent call.

**1. Request an access token**

```bash Raw API
curl -X POST "https://{tenant_name}.benchling.com/oauth/token" \
  -H "accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&\
client_id={client_id}&\
client_secret={client_secret}"
```
```python Python SDK
from benchling_sdk.auth.client_credentials_oauth2 import ClientCredentialsOAuth2
from benchling_sdk.benchling import Benchling

auth_method = ClientCredentialsOAuth2(
    client_id="{client_id}",
    client_secret="{client_secret}",
)
benchling = Benchling(url="https://{tenant_name}.benchling.com", auth_method=auth_method)
# No explicit token request: the SDK fetches one on your first API call
```

Response from the raw endpoint:

```json
{
  "token_type": "Bearer",
  "access_token": "<string>",
  "expires_in": 900
}
```

**2. Use the access token**

Send the `access_token` in the `Authorization` header on all subsequent calls:

```bash Raw API (V3)
curl -X GET "https://{tenant_name}.benchling.com/api/v3/entry/items?pageSize=5&sort=modifiedAt%3Adesc" \
  -H "accept: application/json" \
  -H "Authorization: Bearer {access_token}"
```
```bash Raw API (V2)
curl -X GET "https://{tenant_name}.benchling.com/api/v2/entries?pageSize=5&sort=modifiedAt%3Adesc" \
  -H "accept: application/json" \
  -H "Authorization: Bearer {access_token}"
```
```python Python SDK (V2)
from benchling_sdk.models import ListEntriesSort

# The SDK sets the Authorization header for you
exampleEntries = benchling.entries.list_entries(
    sort=ListEntriesSort.MODIFIEDATDESC,
    page_size=5,
)
print(next(exampleEntries))  # prints the first page
```

The same token works against both API versions. Use [V3](https://docs.benchling.com/docs/v3-api-overview) for new development; the Python SDK currently targets V2.

**3. Request a new token when it expires**

Access tokens expire after 15 minutes (`expires_in`, in seconds). The client credentials grant type does not issue a refresh token — request a new access token the same way as step 1.

The [Python SDK](https://docs.benchling.com/docs/getting-started-with-the-sdk) handles token acquisition and refresh automatically. It defaults to `/api/v2/token`, which continues to work, but it accepts a `token_url` — pass `/oauth/token` so your integration isn't tied to a versioned path, as the app guides do. For a longer walkthrough, see [Getting Started with Benchling Apps](https://docs.benchling.com/docs/getting-started-benchling-apps#calling-the-api-as-an-app).

**When to use app credentials:**

* The app should act as itself, with its own identity and its own permissions. Actions should be attributed to the app in audit logs and `createdBy` fields
* No user is present — scheduled syncs, background jobs, webhook handlers

**When not to use app credentials:**

* Actions should reflect the permissions of the signed-in user, or be attributed to that user in audit logs. Use [Delegated Auth](#delegated-auth-oauth-20-authorization-code-flow) instead.

### Managing app access

By default a new app has no access to any data. Grant access by adding the app to the relevant organizations, teams, and projects. See [Granting an App Access](https://docs.benchling.com/docs/getting-started-benchling-apps#granting-an-app-access).

Archiving an app immediately revokes its API access. Unarchiving restores access without needing to regenerate the client secret.

Apps are not tied to users and are not suspended when a user is, so if a suspended user had access to an app's client secret, rotate the secret in the Developer Console.

## Delegated Auth (OAuth 2.0 Authorization Code Flow)

Delegated Auth allows a Benchling App to act on behalf of the user who is currently interacting with it. When a user authorizes your app, the app receives an access token scoped to that user's permissions. Actions taken by the app are attributed to the user in audit logs and `createdBy` fields, and the user's permission scope determines what the app can access — not the app's own permissions.

**When to use Delegated Auth:**

* Your integration needs to reflect individual user permissions (e.g. a user can only access their own projects). Audit logs and `createdBy` fields should show the actual user rather than the app itself.

* You're building a user-facing external tool that connects to Benchling on behalf of the signed-in user — for example, a data entry app or equipment scheduling tool.

**When not to use Delegated Auth:**

* Headless bulk sync or background processes with no user interaction — the user needs to be present to complete the authorization flow. Use app credentials instead. You need the integration to access data the current user can't access, and you're comfortable enforcing appropriate user access within your app instead

### How to configure an app for Delegated Auth

Delegated Auth requires a Benchling App created with the new (non-legacy) app format. Apps created from a manifest after May 2024 on continuous release tenants use the new format automatically.

**1. Add redirect URIs to your app**

In the Developer Console, navigate to your app's settings and add one or more redirect URIs — the URLs Benchling will redirect to after a user authorizes your app. For local development, `http://localhost:{port}` is permitted. All production redirect URIs must be HTTPS.

**2. Direct the user to the authorization URL**

Start the authorization flow by directing the user to the Benchling authorization endpoint. We recommend a "Sign in with Benchling" button in your app's UI to initiate this:

```text
https://{tenant_name}.benchling.com/oauth/authorize?
  client_id={client_id}&
  redirect_uri={redirect_uri}&
  response_type=code&
  state={optional_state_value}
```

This prompts the user to sign in (if not already) and consent to your app acting on their behalf. If the user already has an active Benchling session and has previously consented to your app, this step is invisible to them.

`state` is strongly recommended: generate a cryptographically random value tied to the user's session and verify it on return to prevent CSRF. Benchling returns it unchanged on the redirect, so you can also use it to carry opaque app state you need when the user comes back.

**3. Exchange the authorization code for an access token**

After the user consents, Benchling redirects to your `redirect_uri` with a `code` parameter. Exchange it for an access token:

```bash
curl -X POST "https://{tenant_name}.benchling.com/oauth/token" \
  -H "accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&\
client_id={client_id}&\
client_secret={client_secret}&\
redirect_uri={redirect_uri}&\
code={authorization_code}"
```

Response:

```json
{
  "token_type": "Bearer",
  "access_token": "<string>",
  "expires_in": 900,
  "refresh_token": "<string>",
  "refresh_token_expires_in": 2592000
}
```

Access tokens expire after 15 minutes (`expires_in`, in seconds). Rather than sending the user back through the authorization flow, have your app exchange the `refresh_token` for a new access token, as described in step 5. No user has to be present for that exchange, but it is not automatic — your app has to make the call itself.

**4. Use the access token**

Use the `access_token` in the `Authorization` header exactly as you would an app credential token:

```bash
curl -X GET "https://{tenant_name}.benchling.com/api/v3/entry/items?pageSize=5&sort=modifiedAt%3Adesc" \
  -H "accept: application/json" \
  -H "Authorization: Bearer {access_token}"
```

Since each token represents a single Benchling user, store it in a way that associates it with that specific user — for example, in the user's session. Never use a token obtained for one user to make calls on behalf of another.

**5. Refresh the access token before it expires**

Access tokens last 15 minutes, so a long-lived session needs to refresh rather than re-prompt. Exchange the `refresh_token` from step 3 for a new access token using the `refresh_token` grant type:

```bash
curl -X POST "https://{tenant_name}.benchling.com/oauth/token" \
  -H "accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token&\
client_id={client_id}&\
client_secret={client_secret}&\
refresh_token={refresh_token}"
```

The response has the same shape as step 3, including a **new** `refresh_token`. Refresh tokens are single-use: each refresh invalidates the token you just sent and issues a replacement, so always persist the new one. Reusing a spent refresh token returns `invalid_grant`.

Refresh tokens are valid for 30 days (`refresh_token_expires_in`, in seconds). Because each refresh issues a fresh 30-day token, a session that refreshes regularly continues without further user interaction. Send the user back through the authorization flow only if the refresh token has expired or been invalidated — for example, after 30 days of inactivity, or if the app was uninstalled.

### Using Delegated Auth with App Canvas

There is no built-in way to generate a delegated auth token directly from a canvas interaction. However, apps can work around this by managing the authorization flow outside the canvas:

1\. When rendering the initial canvas, check if you have a valid access token for the current user (identified by `userId` in the webhook payload). If so, proceed normally.
2\. If no token exists, render the canvas with a link to your app's authorization endpoint. Include the `userId` and the resource ID from the canvas payload in the `state` parameter (encrypted), so you can associate the resulting token with the correct user.
3\. The user clicks the link and completes the consent flow, and Benchling redirects to your redirect URI with the authorization code.
4\. Store the resulting access token server-side, associated with that user's ID.
5\. Redirect the user back to `https://{tenant}.benchling.com/editor` to return them to where they started.
6\. For subsequent canvas interactions, use the stored user access token for API calls that should reflect the user's permissions and be attributed to the user. Continue using app credentials for canvas update calls (POST/PATCH canvas).

<Callout icon="📘" theme="info">
  ### This flow requires the user to leave the page and return during initial authorization. Benchling plans to add native support for delegated auth in canvas experiences in the future.
</Callout>

### Suspended users

If a user is suspended in Benchling, the access tokens and refresh tokens issued for them stop working. Suspending a user in your IdP does not automatically suspend them in Benchling — you must suspend them explicitly in the Benchling admin console.

### Known Limitations

* **No SDK support.** The Python SDK currently only supports the client credentials flow. Implement the authorization code flow in your app layer and pass the resulting access token to API calls directly — including the step 5 refresh exchange, which you have to manage yourself. Note the contrast with client credentials, where the SDK does renew tokens on its own, requesting a new one whenever the current one is close to expiring. Benchling plans to handle delegated auth tokens the same way once the SDK supports the flow; until then, trade in refresh tokens explicitly.
* **No consent revocation UI.** There is no interface for admins to view or revoke which users have consented to an app. To prevent an app from acting on behalf of users who have already consented, uninstall the app from the tenant. If the app is reinstalled, users will need to re-consent.

## Basic Authentication (Personal API Key)

Personal API requests are authenticated with HTTP Basic auth. Use your API key as the username with an empty password:

```bash
curl -u sk_YOUR_API_KEY: https://{tenant_name}.benchling.com/api/v3/plate/items
# The colon after the key indicates an empty password
```

API keys are tied to the user who generated them — calls made with an API key are attributed to that user in audit logs. Generate or rotate your API key in **Profile Settings**.

API keys created after August 7, 2026 expire 30 days after they are created. API keys created before that date do not expire.

If a user is suspended in Benchling, their API key stops working. Suspending a user in your IdP does not automatically suspend them in Benchling — you must suspend them explicitly in the Benchling admin console. Un-suspending a user restores their API key without needing to regenerate it, though the Warehouse does require un-suspended users to generate a new Warehouse login.

## OpenID Connect (OIDC)

<Callout icon="🚧" theme="warn">
  ### OIDC is a legacy authentication method

  It remains fully supported and Benchling has no current plans to remove it, but no active investment is being made in it. For new implementations, use [Delegated Auth](#delegated-auth-oauth-20-authorization-code-flow) instead — it covers the same scenarios in a more modern and complete way.
</Callout>

OIDC allows your integration to authenticate to Benchling using tokens issued by an external identity provider (IdP) such as Okta or Azure Active Directory. The Benchling API verifies the token signature against your IdP's OpenID configuration endpoint and authenticates the request as the user associated with the token's `email` claim.

```bash
curl -H "Authorization: Bearer YOUR_ID_TOKEN" \
  https://{tenant_name}.benchling.com/api/v3/plate/items
```

**Requirements:**

*An external IdP that supports OpenID Connect (Okta and Azure Active Directory are confirmed to work)* The IdP must include `email` as a claim in the token

*The user must already exist in Benchling — in most cases this means signing in to the Benchling web app at least once before making API calls* OIDC setup requires Benchling Support — contact <developer-platform@benchling.com> to get started

<br />

**Migrating from OIDC to Delegated Auth**

The scenarios OIDC supports are fully covered by Delegated Auth. The technologies don't map 1:1, but the use cases do. OIDC will remain supported with significant advance notice before any removal. To migrate, reach out to your account team for guidance.

## Which One Should I Use?

**Should the app act as itself, with its own identity and permissions?** → [OAuth Bearer (App credentials)](#oauth-bearer-authentication-app-credentials).

**Building a user-facing tool where actions should reflect individual user permissions and appear in audit logs under that user?** → [Delegated Auth](#delegated-auth-oauth-20-authorization-code-flow).

**Running a quick one-off script or personal test?** → [Basic Auth](#basic-authentication-personal-api-key), though app credentials are the better long-term choice.

**Already using OIDC?** → Keep it for now; migrate to Delegated Auth when it makes sense for your team.

## Warehouse Authentication

The Benchling Warehouse does not use these authentication methods. See [Overview & Getting started](https://docs.benchling.com/docs/getting-started) for how to connect to it.