Skip to content

Configuring clients

This page covers choosing a client, limiting what it can read and write, retries, and connection settings. Quickbase and AsyncQuickbase take the same options. Use them as context managers so that connections get closed.

Sync or async

import asyncio

from pyquickbase import AsyncQuickbase, F, Quickbase

with Quickbase(realm="acme", token="your_user_token") as qb:
    print(qb.app("bq1234567").table("Tasks").count(F("Status") == "Open"))


async def main() -> None:
    async with AsyncQuickbase(realm="acme", token="your_user_token") as qb:
        tasks = qb.app("bq1234567").table("Tasks")
        async for task in tasks.query(where=F("Status") == "Open", max_total=5):
            print(task["Title"])


asyncio.run(main())

The clients have the same methods, and the sync client is a true sync client rather than a wrapper around asyncio. That means it works in notebooks, in threads, and inside a running event loop. One sync client can be shared across threads. The async client works with both asyncio and Trio.

Try it in the playground, with simulated data.

Using several tokens

Quickbase.from_env() reads QB_REALM and QB_USER_TOKEN. A program with more than one token can name the variable, such as a setup token and a restricted one:

qb = Quickbase.from_env(token_env="QB_SERVICE_TOKEN")

Limiting what a client can do

A client takes one policy, which says what it may read and change, such as Policy.read_only(). Every request is checked before it's sent. See Policies for how to write one, and what it does and doesn't protect against.

Retries

from pyquickbase import Quickbase, RetryPolicy

policy = RetryPolicy(max_retries=2, base_delay=0.5, max_delay=10, max_retry_after=30)
qb = Quickbase(realm="acme", token="your_user_token", retry=policy)

max_retry_after is the longest Retry-After the client will wait for. Past that, it raises RateLimitError. A missing Retry-After, or one of 0, uses the backoff from base_delay instead, because Quickbase can send 0 while still limiting. Use max_retries=0 to disable retrying.

Each retry counts toward max_retries. Once they're used up, the last error is raised.

What's retried:

Failure Reads Writes
429, rate limited Yes Yes
Couldn't connect, or no free connection in the pool Yes Yes, as nothing was sent
A timeout or dropped connection after sending Yes No, as it may have been applied
502, 503, or 504 Yes No
Any other error status No No

Reads are GET requests, record queries, report runs, and formula runs. Running a report again adds to its usage count again.

timeout applies to each step of a request separately, connecting, sending, and waiting for each part of the response, as httpx does, rather than to the whole request.

Using another API host

base_url sets the API root, which is https://api.quickbase.com/v1 by default. The right host for EU realms hasn't been confirmed, so pass base_url if yours differs. It must use HTTPS, except for loopback addresses.

Proxies, TLS, and logging

Pass your own httpx client for proxies, custom TLS, event hooks, or custom transports. You remain responsible for closing it.

import httpx
from pyquickbase import Quickbase

http_client = httpx.Client(proxy="http://proxy.internal:8080")
qb = Quickbase(
    realm="acme",
    token="your_user_token",
    user_agent="my-app/1.0",
    http_client=http_client,
)

Tokens are kept out of reprs, exceptions, and logs, and the client refuses to send them over plain HTTP, except to your own machine.

Calling any endpoint

For endpoints without a dedicated method, request() returns the decoded JSON body.

reports = qb.request("GET", "/reports", params={"tableId": "bq7654321"})