# pyquickbase API reference: Quickbase This describes version 1.0.0rc13. Other pages: [App](https://matthew-williams-solutions.github.io/pyquickbase/reference/app.txt), [Table](https://matthew-williams-solutions.github.io/pyquickbase/reference/table.txt), [Report](https://matthew-williams-solutions.github.io/pyquickbase/reference/report.txt), [Operation](https://matthew-williams-solutions.github.io/pyquickbase/reference/operation.txt), [SchemaOperation](https://matthew-williams-solutions.github.io/pyquickbase/reference/schema-operation.txt), [Queries](https://matthew-williams-solutions.github.io/pyquickbase/reference/queries.txt), [Records and results](https://matthew-williams-solutions.github.io/pyquickbase/reference/records.txt), [Metadata](https://matthew-williams-solutions.github.io/pyquickbase/reference/metadata.txt), [Schema changes](https://matthew-williams-solutions.github.io/pyquickbase/reference/schema-changes.txt), [Policies](https://matthew-williams-solutions.github.io/pyquickbase/reference/policies.txt), [Rules](https://matthew-williams-solutions.github.io/pyquickbase/reference/rules.txt), [Retries](https://matthew-williams-solutions.github.io/pyquickbase/reference/retries.txt), [Tools for models](https://matthew-williams-solutions.github.io/pyquickbase/reference/tools.txt), [Errors](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors.txt). [`Quickbase`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/) is the client that everything else starts from. Use it as a context manager, so that its connections get closed. [`AsyncQuickbase`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/) takes the same options, except that `http_client` is an `httpx.AsyncClient`, and has the same methods, which you `await` where the examples show it. The examples below use `qb`, made as shown here. A live test runs every example with both clients and checks its output. Sync: ```python from pyquickbase import Quickbase with Quickbase( realm="acme", token="your_user_token" ) as qb: print(qb.realm) ``` Async: ```python from pyquickbase import AsyncQuickbase async with AsyncQuickbase( realm="acme", token="your_user_token" ) as qb: print(qb.realm) ``` ## What the methods return | Type | What it is | Returned by | |---|---|---| | [`App`](https://matthew-williams-solutions.github.io/pyquickbase/reference/app/) | A Quickbase app. Create one with `qb.app(app_id)`. This makes no network calls. | [`app()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/#app), [`create_app()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/#create_app) | | [`BoundPolicy`](https://matthew-williams-solutions.github.io/pyquickbase/reference/policies/#BoundPolicy) | A `Policy` resolved against one app, keyed by ID, which decides every request a client sends. It's frozen: a client that creates a table gets a new one, as `client.policy`. | [`policy`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/#policy) | | [`Quickbase`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/) | A Quickbase API client. Use it as a context manager so connections get closed. | [`from_env()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/#from_env) | ## Create and close a client For the full picture, see [Configuring clients](https://matthew-williams-solutions.github.io/pyquickbase/guides/clients/). ### `Quickbase()` A Quickbase API client. Use it as a context manager so connections get closed. ```python Quickbase( *, realm: str, token: str, base_url: str = "https://api.quickbase.com/v1", retry: RetryPolicy | None = None, timeout: float = 30.0, user_agent: str | None = None, http_client: httpx.Client | None = None, schema_ttl: float = 300.0, policy: Policy | BoundPolicy | None = None, confirmation_key: bytes | None = None, ) ``` **Parameters** - **`realm`** `str`, required Your realm, as `acme`, `acme.quickbase.com`, or a realm URL. - **`token`** `str`, required A Quickbase user token. - **`base_url`** `str`, default `'https://api.quickbase.com/v1'` The API root. Must use HTTPS, except for loopback addresses. - **`retry`** `RetryPolicy | None`, optional How to retry rate limits, connection failures, and reads that time out or get a 502, 503, or 504. A write isn't retried after anything that may have reached Quickbase. - **`timeout`** `float`, default `30.0` Seconds to allow for each step of a request, such as connecting or waiting for the response, as httpx applies it. Ignored if you pass `http_client`. - **`user_agent`** `str | None`, optional Identifies your application, placed before the SDK's own User-Agent. - **`http_client`** `httpx.Client | None`, optional Your own configured httpx client, for proxies, custom TLS, event hooks, or custom transports. You remain responsible for closing it. - **`schema_ttl`** `float`, default `300.0` Seconds to cache app, table, and field metadata. Use 0 to disable caching. - **`policy`** `Policy | BoundPolicy | None`, optional What the client may do, as a [`BoundPolicy`](https://matthew-williams-solutions.github.io/pyquickbase/reference/policies/#BoundPolicy) from `Policy.bind()`, or a [`Policy`](https://matthew-williams-solutions.github.io/pyquickbase/reference/policies/#Policy) that names no table or field, such as `Policy.read_only()`. Every request is checked before it's sent, including through [`request()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/#request), and a refused one raises [`PolicyRefusedError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#PolicyRefusedError). What the policy hides is left out of every response, so a hidden field acts as if it didn't exist. Without one, the client does whatever the token can. - **`confirmation_key`** `bytes | None`, optional The secret that signs the confirmations an operation's preview returns, at least 32 random bytes, such as from `secrets.token_bytes(32)`. Give several clients, or processes, the same key so that any of them accepts a preview another made. Without it, each client makes its own. **Raises** - [`ConfigurationError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#ConfigurationError): `realm`, `token`, or `base_url` can't be used, or `policy` names tables or fields but isn't bound. Sync example: ```python from pyquickbase import Quickbase, Policy with Quickbase( realm="acme", token="your_user_token", policy=Policy.read_only(), ) as qb: print(qb.realm) ``` Async example: ```python from pyquickbase import AsyncQuickbase, Policy async with AsyncQuickbase( realm="acme", token="your_user_token", policy=Policy.read_only(), ) as qb: print(qb.realm) ``` Output: ```text acme.quickbase.com ``` ### `Quickbase.from_env()` Create a client from the `QB_REALM` and `QB_USER_TOKEN` environment variables. It takes the same options as the constructor, other than `realm` and `token`. ```python from_env( *, base_url: str = "https://api.quickbase.com/v1", retry: RetryPolicy | None = None, timeout: float = 30.0, user_agent: str | None = None, http_client: httpx.Client | None = None, schema_ttl: float = 300.0, policy: Policy | BoundPolicy | None = None, confirmation_key: bytes | None = None, token_env: str = "QB_USER_TOKEN", ) -> Quickbase ``` **Parameters** - **`base_url`** `str`, default `'https://api.quickbase.com/v1'` The API root. Must use HTTPS, except for loopback addresses. - **`retry`** `RetryPolicy | None`, optional How to retry rate limits, connection failures, and reads that time out or get a 502, 503, or 504. A write isn't retried after anything that may have reached Quickbase. - **`timeout`** `float`, default `30.0` Seconds to allow for each step of a request, such as connecting or waiting for the response, as httpx applies it. Ignored if you pass `http_client`. - **`user_agent`** `str | None`, optional Identifies your application, placed before the SDK's own User-Agent. - **`http_client`** `httpx.Client | None`, optional Your own configured httpx client, for proxies, custom TLS, event hooks, or custom transports. You remain responsible for closing it. - **`schema_ttl`** `float`, default `300.0` Seconds to cache app, table, and field metadata. Use 0 to disable caching. - **`policy`** `Policy | BoundPolicy | None`, optional What the client may do, as a [`BoundPolicy`](https://matthew-williams-solutions.github.io/pyquickbase/reference/policies/#BoundPolicy) from `Policy.bind()`, or a [`Policy`](https://matthew-williams-solutions.github.io/pyquickbase/reference/policies/#Policy) that names no table or field, such as `Policy.read_only()`. Every request is checked before it's sent, including through [`request()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/#request), and a refused one raises [`PolicyRefusedError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#PolicyRefusedError). What the policy hides is left out of every response, so a hidden field acts as if it didn't exist. Without one, the client does whatever the token can. - **`confirmation_key`** `bytes | None`, optional The secret that signs the confirmations an operation's preview returns, at least 32 random bytes, such as from `secrets.token_bytes(32)`. Give several clients, or processes, the same key so that any of them accepts a preview another made. Without it, each client makes its own. - **`token_env`** `str`, default `'QB_USER_TOKEN'` The name of the variable that holds the token, for a program that has several. **Returns** [`Quickbase`](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase/) A new client. **Raises** - [`ConfigurationError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#ConfigurationError): A variable is missing or empty, or an option can't be used. Sync example: ```python from pyquickbase import Quickbase, Policy with Quickbase.from_env( policy=Policy.read_only() ) as qb: app = qb.app("bq1234567") print(app.id) ``` Async example: ```python from pyquickbase import AsyncQuickbase, Policy async with AsyncQuickbase.from_env( policy=Policy.read_only() ) as qb: app = qb.app("bq1234567") print(app.id) ``` Output: ```text bq1234567 ``` ### `Quickbase.close()` Close connections. Safe to call more than once. The async client calls this `aclose()`. ```python close() -> None ``` Sync example: ```python from pyquickbase import Quickbase client = Quickbase(realm="acme", token="your_user_token") try: print(client.realm) finally: client.close() ``` Async example: ```python from pyquickbase import AsyncQuickbase client = AsyncQuickbase(realm="acme", token="your_user_token") try: print(client.realm) finally: await client.aclose() ``` Output: ```text acme.quickbase.com ``` ## Use a client For the full picture, see [Configuring clients](https://matthew-williams-solutions.github.io/pyquickbase/guides/clients/). ### `Quickbase.app()` Get an app by ID, the `bq...` part of its URL. This makes no network calls. ```python app(app_id: str) -> App ``` **Parameters** - **`app_id`** `str`, required The app's ID, which contains only letters and numbers. **Returns** [`App`](https://matthew-williams-solutions.github.io/pyquickbase/reference/app/) An [`App`](https://matthew-williams-solutions.github.io/pyquickbase/reference/app/). An ID that doesn't exist only fails on first use. **Raises** - [`ConfigurationError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#ConfigurationError): `app_id` contains anything but letters and numbers. Sync example: ```python app = qb.app("bq1234567") print(app.id) ``` Async example: ```python app = qb.app("bq1234567") print(app.id) ``` Output: ```text bq1234567 ``` ### `Quickbase.realm` The full realm hostname, such as `acme.quickbase.com`. ```python realm: str ``` Sync example: ```python print(qb.realm) ``` Async example: ```python print(qb.realm) ``` Output: ```text acme.quickbase.com ``` ### `Quickbase.policy` The client's current policy. Creating a table replaces it with one that knows the table, so save this one with `to_json()` to use it elsewhere. ```python policy: BoundPolicy | None ``` Sync example: ```python from pyquickbase import Quickbase, Policy read_only = Policy.read_only() with Quickbase.from_env(policy=read_only) as qb: print(qb.policy.created) ``` Async example: ```python from pyquickbase import AsyncQuickbase, Policy read_only = Policy.read_only() async with AsyncQuickbase.from_env(policy=read_only) as qb: print(qb.policy.created) ``` Output: ```text () ``` ### `Quickbase.clear_schema_cache()` Forget cached metadata, for example after changing a table's fields. Use this after a change made outside this client, such as in the Quickbase interface. The client's own schema methods keep the cache current. ```python clear_schema_cache() -> None ``` Sync example: ```python qb.clear_schema_cache() ``` Async example: ```python qb.clear_schema_cache() ``` ### `Quickbase.request()` Call any Quickbase endpoint directly and return its decoded JSON body. This is the escape hatch for endpoints without a dedicated method. The client's retries and its policy still apply. ```python request( method: str, path: str, *, params: Mapping[str, Any] | None = None, json: Any = None, ) -> Any ``` **Parameters** - **`method`** `str`, required The HTTP method, such as `GET`. - **`path`** `str`, required The endpoint, relative to the API root, such as `/tables/abc123`. - **`params`** `Mapping[str, Any] | None`, optional Values to send in the query string. - **`json`** `Any`, optional The value to send as the JSON body. **Returns** `Any` The decoded JSON body, or None if the response is empty. **Raises** - [`PolicyRefusedError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#PolicyRefusedError): The client's policy doesn't allow this request. It wasn't sent. - [`APIError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#APIError): Quickbase returned an error. This is a subclass such as [`NotFoundError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#NotFoundError) or [`PermissionDeniedError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#PermissionDeniedError), for the status it returned. Sync example: ```python body = qb.request("GET", "/apps/bq1234567") print(body["id"]) ``` Async example: ```python body = await qb.request("GET", "/apps/bq1234567") print(body["id"]) ``` Output: ```text bq1234567 ``` ## Create an app For the full picture, see [Working with apps](https://matthew-williams-solutions.github.io/pyquickbase/guides/apps/). ### `Quickbase.create_app()` Create an empty app and return it. Use `app.copy()` to start from another app. ```python create_app( name: str, *, description: str | None = None, assign_token: bool = True, ) -> App ``` **Parameters** - **`name`** `str`, required The app's name. Quickbase allows several apps with the same name. - **`description`** `str | None`, optional The app's description. - **`assign_token`** `bool`, default `True` Let this client's token reach the app, which a token limited to some apps can't otherwise do. **Returns** [`App`](https://matthew-williams-solutions.github.io/pyquickbase/reference/app/) An [`App`](https://matthew-williams-solutions.github.io/pyquickbase/reference/app/) for the new app. **Raises** - [`InvalidValueError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#InvalidValueError): `name` is empty. Nothing was sent. - [`PermissionDeniedError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#PermissionDeniedError): The token's user can't create apps in this realm. - [`PolicyRefusedError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#PolicyRefusedError): The client has a policy, which covers one app. Nothing was sent. Sync example: ```python app = qb.create_app( "Field Jobs", description="Crews, sites, and tasks" ) print((app.info()).name) ``` Async example: ```python app = await qb.create_app( "Field Jobs", description="Crews, sites, and tasks" ) print((await app.info()).name) ``` Output: ```text Field Jobs ```