> 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.

# Convert SDK Objects to JSON

This example reads every plate in a tenant with the [V3 Python SDK](/docs/getting-started-with-the-v3-sdk)
and converts the resulting SDK objects to JSON. Plates are just the example; the same pattern works
for any object the SDK returns, because every V3 SDK model is a
[pydantic](https://docs.pydantic.dev/) model.

> **Info**
>
> The V3 plate list endpoint is 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).

#### Initialize the environment

Import the SDK and `json`, then create a Benchling client. Pass your tenant's root URL and your
API key; the SDK adds `/api/v3` itself.

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

```python Python (lines 1-9)
import json

from benchling_v3_sdk import Benchling

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

#### List plates

`plate.list()` requests the first page straight away and returns a pager that fetches the rest as
you go.

**`Python (line 11)`**

```python Python (line 11)
plates = benchling.plate.list()
```

#### Loop through the results

`iter_pages()` walks each page of results, and the inner loop walks the individual plates in
that page's `items` (50 per page by default, up to 100 with `page_size`). To skip the paging
detail, iterate `plates` directly instead. See
[Pagination](/docs/common-sdk-interactions-and-examples-v3#pagination).

**`Python (lines 13-14)`**

```python Python (lines 13-14)
for page in plates.iter_pages():
    for plate in page.items:
```

#### Convert each plate

`dict(mode="json")` turns an SDK model into a plain dictionary that `json` can write:
camelCase keys, as in the API response, and only the fields the API returned. Collecting them in
`serialized_plates` makes the whole set easy to serialize at the end, but this is the point where
you would instead reshape the data into whatever your use case needs.

**`Python (line 12)`**

```python Python (line 12)
serialized_plates = []
```

**`Python (line 15)`**

```python Python (line 15)
        serialized_plates.append(plate.dict(mode="json"))
```

#### Write the data to a file

The response tab shows the shape of the output. In V3, `wells` is a link rather than the well
contents; call `benchling.plate.list_wells()` with the plate's ID to read them.

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

```python Python (lines 16-17)
with open("output.json", "w") as f:
    json.dump(serialized_plates, f, indent=2)
```

#### Complete files

**`Python`**

```python title="Python"
import json

from benchling_v3_sdk import Benchling

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

plates = benchling.plate.list()
serialized_plates = []
for page in plates.iter_pages():
    for plate in page.items:
        serialized_plates.append(plate.dict(mode="json"))
with open("output.json", "w") as f:
    json.dump(serialized_plates, f, indent=2)
```

**`Response Example`**

```json title="Response Example"
[{
    "__typename": "Plate",
    "archiveReason": null,
    "archived": false,
    "barcode": "example2",
    "createdAt": "2022-03-04T22:57:23.163358+00:00",
    "creator": {"__typename": "User", "id": "USER_ID"},
    "id": "PLATE_ID",
    "modifiedAt": "2022-03-04T22:57:23.163358+00:00",
    "name": "Test Plate 2",
    "parentStorage": {"__typename": "Location", "id": "STORAGE_ID"},
    "project": null,
    "schema": {"__typename": "PlateSchema", "id": "SCHEMA_ID"},
    "type": "FIXED_PLATE",
    "wells": "https://yourcompany.benchling.com/api/v3/plate/PLATE_ID/wells/items"
}, {
    "__typename": "Plate",
    "archiveReason": null,
    "archived": false,
    "barcode": "example1",
    "createdAt": "2022-03-04T22:02:06.594242+00:00",
    "creator": {"__typename": "User", "id": "USER_ID"},
    "id": "PLATE_ID",
    "modifiedAt": "2022-03-04T22:02:06.594242+00:00",
    "name": "Test Plate 1",
    "parentStorage": {"__typename": "Location", "id": "STORAGE_ID"},
    "project": null,
    "schema": {"__typename": "PlateSchema", "id": "SCHEMA_ID"},
    "type": "FIXED_PLATE",
    "wells": "https://yourcompany.benchling.com/api/v3/plate/PLATE_ID/wells/items"
}]
```

## Other ways to serialize a model

The V3 SDK models are pydantic v2 models with snake\_case attribute names and camelCase aliases, so
the output depends on which method you call:

| Call                                           | Keys                                       | Fields included                                                 |
| ---------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------- |
| `plate.dict(mode="json")`                      | camelCase                                  | Only fields the API returned                                    |
| `plate.json()`                                 | camelCase, as a JSON string                | Only fields the API returned                                    |
| `plate.model_dump(mode="json", by_alias=True)` | camelCase                                  | Every field on the model, `null` where the API didn't return it |
| `plate.model_dump(mode="json")`                | snake\_case, with `typename` and `schema_` | Every field on the model                                        |

`mode="json"` converts values such as datetimes to strings. Without it, a model that holds a
`datetime` produces a dictionary that `json.dumps()` can't write.