> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thinkplatform.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Choose User guide for browser tasks, Developers for CLI, SDK and external agents, and Administration for organization management.
> Confirm identity and organization/project context before operations. Documentation access does not grant ThinkPlatform permissions.
> Review side effects, verify changes with a read, and do not blindly retry an operation with an uncertain outcome.
> Use documented UI steps for the web app and documented public CLI or SDK interfaces for automation. Follow each page’s prerequisites and authentication requirements.

# Database tables and rows

> Inspect shared database tables, query sample rows, and update a row.

The SDK works with existing shared database tables through `client.db.tables` and `client.db.rows`. Table creation, schema changes, and row deletion are not exposed by these resource namespaces. For every method and its exact defaults, see the [API reference](https://docs.thinkplatform.ai/python-sdk/api-reference.md#database-tables); field types are in [models and results](https://docs.thinkplatform.ai/python-sdk/models.md#shareddbtable).

Use an API credential with access to the selected organization, project, and table. Context selects the scope; it does not grant database permissions.

## Inspect schema and query a sample

`db.tables.list()` returns `list[SharedDbTableSummary]` with no pagination arguments. `db.tables.get(table_id)` returns the full `SharedDbTable`, including `columns`, `schema_version`, and access metadata. Column definitions expose keys, types, required flags, options, and lifecycle metadata. Inspect them before choosing a column to read or write.

`db.rows.query(table_id, query)` forwards a query mapping to the deployed endpoint. The example below requests up to five rows using empty `filters` and `sort` arrays with `page` and `page_size`. Before adding filters or sorting, check which operators and sort directions your deployed API supports.

The result is `SharedDbRowQueryResult`: rows are in `items`, user column values are in each row's `data`, and optional page metadata is in `meta.page`, `meta.page_size`, and `meta.total`. These metadata fields can be absent; inspect them before traversing pages. Request each page explicitly; the SDK does not convert this query to offset or continuation-token pagination.

## Update a known row and read it back

Set `THINKPLATFORM_API_BASE_URL`, `THINKPLATFORM_ACCESS_TOKEN`, `THINKPLATFORM_ORG_ID`, `THINKPLATFORM_PROJECT_ID`, and `THINKPLATFORM_DB_TABLE_ID`. The sample first prints the schema and up to five rows.

To update a row, additionally set `THINKPLATFORM_DB_ROW_ID`, `THINKPLATFORM_DB_COLUMN_KEY`, and `THINKPLATFORM_DB_COLUMN_VALUE`. Choose an existing text column whose schema accepts the supplied string. Set `THINKPLATFORM_APPLY_UPDATE=yes` only after checking the table, row, key, and intended value. With that flag unset, the code only reads.

```python theme={"system"}
import os
from thinkplatform.sdk import StaticTokenCredential, ThinkPlatformClient

with ThinkPlatformClient(
    base_url=os.environ["THINKPLATFORM_API_BASE_URL"],
    credential=StaticTokenCredential(os.environ["THINKPLATFORM_ACCESS_TOKEN"]),
    org_id=int(os.environ["THINKPLATFORM_ORG_ID"]),
    project_id=int(os.environ["THINKPLATFORM_PROJECT_ID"]),
) as client:
    table_id = os.environ["THINKPLATFORM_DB_TABLE_ID"]
    table = client.db.tables.get(table_id)
    print(table.name, table.schema_version)
    for column in table.columns:
        print(column.key, column.type, column.required, column.status)

    sample = client.db.rows.query(
        table_id,
        {"filters": [], "sort": [], "page": 1, "page_size": 5},
    )
    for row in sample.items:
        print(row.id, row.data)
    print(sample.meta.page, sample.meta.page_size, sample.meta.total)

    if os.environ.get("THINKPLATFORM_APPLY_UPDATE") == "yes":
        row_id = os.environ["THINKPLATFORM_DB_ROW_ID"]
        column_key = os.environ["THINKPLATFORM_DB_COLUMN_KEY"]
        desired_value = os.environ["THINKPLATFORM_DB_COLUMN_VALUE"]
        if column_key not in {column.key for column in table.columns}:
            raise ValueError("The requested column key is absent from the table schema.")
        before = client.db.rows.get(table_id, row_id)
        desired_data = dict(before.data)
        desired_data[column_key] = desired_value
        client.db.rows.update(table_id, row_id, desired_data)
        verified = client.db.rows.get(table_id, row_id)
        if verified.data.get(column_key) != desired_value:
            raise RuntimeError("The stored value does not match the requested update.")
        print(verified.id, verified.data.get(column_key))
```

The example copies the current row data before changing one key. The SDK sends `data` inside the endpoint's `{"data": ...}` envelope; pass column-value mappings directly rather than wrapping them again.

`update()` has no `expected_schema_version`, row-version, or compare-and-swap parameter. A read followed by an update can race with another writer, including when resending copied data. The final GET verifies the observed stored value at that moment; it does not make the sequence atomic. When multiple clients write to the same rows, use the concurrency controls supported by your deployed service.

## Create one row or a batch

`db.rows.create(table_id, data)` returns a `SharedDbRow`. Supply the complete column-value mapping required by your table, without a surrounding `data` key. The server validates the table schema and permissions.

`db.rows.create_many(table_id, rows, *, expected_schema_version=None, org_id=None, project_id=None)` accepts an iterable of plain column-value mappings. The SDK wraps each mapping in a `data` envelope and sends the batch as `items`, together with `expected_schema_version`. Its result is a mapping, not `list[SharedDbRow]`; check your deployed batch endpoint documentation for the result keys and whether the batch is atomic.

If your deployment uses the batch schema-version check, obtain the current version from `db.tables.get(table_id).schema_version` and pass it as `expected_schema_version` to `create_many()`. This argument is specific to batch creation; `create()` and `update()` do not accept it. A schema version describes table structure and is not a row-concurrency token.

## Handle failures

See [SDK errors](https://docs.thinkplatform.ai/python-sdk/errors.md). Missing context raises `MissingContextError`; rejected HTTP requests raise `ThinkPlatformApiError` with a status and decoded error body. Do not assume every validation, access, or conflict failure has the same status across deployments. Re-read the table schema after a schema mismatch, and verify stored rows before retrying an uncertain write. A connection failure does not establish whether a write reached the service.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.