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

# List all studies

GET https://acme-api.invivo.benchling.com/api/public/v1/studies

Returns a list of your studies.

Reference: https://docs.benchling.com/in-vivo/studies/study-list

## Authentication

- OAuth2 — send the obtained token as `Authorization: Bearer <token>`

## Request

### Query parameters

- `perPage` (integer, optional, default: 10) — The number of results to return per page, up to a maximum of 100.
- `page` (integer, optional, default: 1) — The page of results to return. The first page is 1.
- `code` (string, optional) — Filter studies to return by code.
- `metadata` (string, optional) — Filter results by metadata value, matching against any metadata key. To filter on a specific key instead, pass the metadata slug itself as a query parameter, e.g. `?study-internal-id=STUDY-1234`. Those slug parameters vary by team glossary and so cannot be enumerated here.

## Response

### 200

A page of studies.

- `data` (list of StudyV1, required) — The studies on this page of results.
- `links` (Links, required) — Absolute URLs for navigating a paginated collection.
- `meta` (Meta, required) — Pagination counters describing the returned page of results.

## Errors

### 400 Bad Request Error

The request was rejected. Validation failures return a `ValidationErrorResponse`; an unrecognised `X-Studies-Api-Version` header returns an `AuthErrorResponse` with the code `invalid_header`.

- `BadRequestErrorResponse`

### 401 Unauthorized Error

Authentication failed. The body is normally empty; when an otherwise valid access token is missing required claims the body is an `AuthErrorResponse` with the code `invalid_token`.

- `any`

### 403 Forbidden Error

The access token does not grant the scopes this operation requires. The body is normally empty; when the token's team is missing or deleted the body is an `AuthErrorResponse` with the code `invalid_data`.

- `any`

### 429 Too Many Requests Error

A rate limit was exceeded. Retry once the window resets; no `Retry-After` header is sent, so use `X-RateLimit-Reset`.

- `error` ("rate_limit_exceeded", required) — A machine-readable error code.
- `message` (string, required) — A human-readable explanation of the failure.

## Types

### StudyV1

A study conducted in your facility by your team. Retrieve it to see the name, the study design, average calculation for treatment groups, whether it is internally or externally conducted, and any metadata assigned.

- `id` (string, required) — Unique identifier for a study.
- `name` (string, required) — The name of the study.
- `code` (string, required, nullable) — The code of the study.
- `study_code_id` (string, required, nullable) — The unique identifier of the study code template.
- `type` (enum, required) — Whether the study is run in-house or by an external partner. The `all` value accepted by some filters is not a valid study type and is never returned.
  - Allowed values: `internal`, `external`
- `status` (enum, required) — Review status of a study.
  - Allowed values: `awaiting_approval`, `in_progress`, `rejected`
- `description` (string, required, nullable) — The description of the study.
- `timezone` (string, required, nullable) — The timezone of the study, as an IANA timezone identifier.
- `metadata` (map from string to any, required, nullable) — The metadata associated to the study.
- `author` (StudyAuthorUserV1, required, nullable) — The author of the study.
- `owner` (StudyAuthorUserV1, required, nullable) — The owner of the study.
- `project` (ProjectV1, required, nullable) — The project of the study.
- `started_on` (date, required) — Calendar date with no time or offset component, in ISO-8601 form.
- `tracking_day_base` (integer, required, nullable) — The day number assigned to the study's start date, from which all subsequent tracking days are counted.
- `completed_at` (datetime, required, nullable) — The completed timestamp of the study.
- `canceled_at` (datetime, required, nullable) — The canceled timestamp of the study.
- `created_at` (datetime, required) — UTC timestamp with microsecond precision, always suffixed with `Z`, in the form `yyyy-MM-ddTHH:mm:ss.SSSSSSZ`.
- `updated_at` (datetime, required) — UTC timestamp with microsecond precision, always suffixed with `Z`, in the form `yyyy-MM-ddTHH:mm:ss.SSSSSSZ`.

### Links

Absolute URLs for navigating a paginated collection.

- `first` (string, required) — The first page of results.
- `last` (string, required) — The last page of results.
- `prev` (string, required, nullable) — The previous page of results. Null on the first page.
- `next` (string, required, nullable) — The next page of results. Null on the last page.

### Meta

Pagination counters describing the returned page of results.

- `current_page` (integer, required) — The page of results returned.
- `from` (integer, required, nullable) — The index of the first result on this page, counted across the whole collection from 1. Null when the page is empty.
- `last_page` (integer, required) — The number of the last available page.
- `path` (string, required) — The collection URL, without any query string.
- `per_page` (integer, required) — The number of results per page actually applied, after the requested value is capped to the maximum.
- `to` (integer, required, nullable) — The index of the last result on this page, counted across the whole collection from 1. Null when the page is empty.
- `total` (integer, required) — The total number of results matching the request, ignoring pagination.

### ValidationErrorResponse

Returned when a request body or parameter fails validation.

- `message` (string, required) — A summary of the failure.
- `errors` (map from string to list of string, required) — Failure messages keyed by the offending field, using the field's name as it appears on the wire. Nested fields are dotted, e.g. `schedule.duration`.

### AuthErrorResponse

Returned when a request is rejected during authentication, before it is processed.

- `error` (enum, required) — A machine-readable error code.
  - Allowed values: `invalid_header`, `invalid_token`, `invalid_data`
- `error_description` (string, required) — A human-readable explanation of the failure.

### ProblemDetail

An RFC 9457 problem detail, returned when a request is rejected before it reaches a controller method — most commonly an unparseable or absent JSON body. Unlike the rest of this API, null members are omitted rather than serialised as `null`.

- `title` (string, required) — A short, human-readable summary of the problem type.
- `status` (integer, required) — The HTTP status code, repeated in the body.
- `detail` (string, required) — A human-readable explanation specific to this occurrence.
- `instance` (string, required) — The path of the request that produced the problem.

### StudyAuthorUserV1

A user referenced as the author or owner of a study.

- `id` (string, required) — Unique identifier for a user.
- `name` (string, required) — The name of the user.
- `email` (string, required) — The email address of the user.
- `timezone` (string, required) — The timezone of the user. Defaults to `UTC` when the user has none set.

### ProjectV1

A project that groups related studies.

- `id` (string, required) — Unique identifier for a project.
- `name` (string, required) — The name of the project.
- `metadata` (map from string to any, required, nullable) — The metadata associated to the project.
- `created_at` (datetime, required) — UTC timestamp with microsecond precision, always suffixed with `Z`, in the form `yyyy-MM-ddTHH:mm:ss.SSSSSSZ`.
- `updated_at` (datetime, required) — UTC timestamp with microsecond precision, always suffixed with `Z`, in the form `yyyy-MM-ddTHH:mm:ss.SSSSSSZ`.

## Examples

**Response**

```json
{
  "data": [
    {
      "id": "sdy_6y9Wop1uArRjD93UiQ5qFy",
      "name": "Benchling In Vivo",
      "code": "CD-26-445",
      "study_code_id": "sdc_n6vkWmmHoACZ15pTxztHk",
      "type": "internal",
      "status": "in_progress",
      "description": "Efficacy study in a xenograft model.",
      "timezone": "America/Los_Angeles",
      "metadata": {
        "study-internal-id": "STUDY-1234"
      },
      "author": {
        "id": "usr_72aeLmlraBB7Ekzu2zTsMW",
        "name": "Jo Harper",
        "email": "jo.harper@example.com",
        "timezone": "UTC"
      },
      "owner": {
        "id": "usr_5TSgutt2ZHPnKOdYbaNlRo",
        "name": "Sam Ellis",
        "email": "sam.ellis@example.com",
        "timezone": "UTC"
      },
      "project": {
        "id": "pjt_7IrvD7jMtAGvBl4AQUUr3g",
        "name": "Oncology",
        "metadata": {
          "project-internal-id": "PROJ-1234"
        },
        "created_at": "2026-09-10T07:27:34.118856Z",
        "updated_at": "2026-09-10T07:27:34.118856Z"
      },
      "started_on": "2026-09-10",
      "tracking_day_base": 0,
      "completed_at": null,
      "canceled_at": null,
      "created_at": "2026-09-10T07:27:34.132511Z",
      "updated_at": "2026-09-10T07:27:34.132511Z"
    }
  ],
  "links": {
    "first": "https://acme-api.invivo.benchling.com/api/public/v1/studies?page=1",
    "last": "https://acme-api.invivo.benchling.com/api/public/v1/studies?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://acme-api.invivo.benchling.com/api/public/v1/studies",
    "per_page": 10,
    "to": 1,
    "total": 1
  }
}
```

**SDK Code**

```python A page of one study
import requests

url = "https://acme-api.invivo.benchling.com/api/public/v1/studies"

querystring = {"code":"CD-26-445"}

headers = {"Authorization": "<token>."}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript A page of one study
const url = 'https://acme-api.invivo.benchling.com/api/public/v1/studies?code=CD-26-445';
const options = {method: 'GET', headers: {Authorization: '<token>.'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```