# pyquickbase API reference: Report This describes version 1.0.0rc13. Other pages: [Quickbase](https://matthew-williams-solutions.github.io/pyquickbase/reference/quickbase.txt), [App](https://matthew-williams-solutions.github.io/pyquickbase/reference/app.txt), [Table](https://matthew-williams-solutions.github.io/pyquickbase/reference/table.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). A [`Report`](https://matthew-williams-solutions.github.io/pyquickbase/reference/report/) runs a report that was built in the Quickbase interface. Get one from [`Table.report()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/table/#report), by name or ID. Getting one doesn't contact Quickbase, so a report that doesn't exist raises [`UnknownReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnknownReportError) on first use. The examples below use `tasks`, made as shown here. Every new table has a report named `List All`. A live test runs every example with both clients and checks its output. The exception is `summary_rows()`, because a summary report can only be built in the interface. [`AsyncReport`](https://matthew-williams-solutions.github.io/pyquickbase/reference/report/) has the same methods, which you `await`, but `run()` is called without it. Sync: ```python from pyquickbase import Quickbase with Quickbase( realm="acme", token="your_user_token" ) as qb: tasks = qb.app("bq1234567").table("Job Tasks") ``` Async: ```python from pyquickbase import AsyncQuickbase async with AsyncQuickbase( realm="acme", token="your_user_token" ) as qb: tasks = qb.app("bq1234567").table("Job Tasks") ``` ## What the methods return | Type | What it is | Returned by | |---|---|---| | [`Page`](https://matthew-williams-solutions.github.io/pyquickbase/reference/records/#Page) | One page of query results. | [`run_page()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/report/#run_page) | | [`RecordIterator`](https://matthew-williams-solutions.github.io/pyquickbase/reference/records/#RecordIterator) | Yields records from a query, fetching further pages as needed. | [`run()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/report/#run) | | [`ReportInfo`](https://matthew-williams-solutions.github.io/pyquickbase/reference/metadata/#ReportInfo) | A report's metadata. | [`info()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/report/#info) | ## Run a report For the full picture, see [Reading records](https://matthew-williams-solutions.github.io/pyquickbase/guides/reading/). ### `Report.run()` Iterate over the report's records, fetching further pages as needed. Records hold only the report's columns, so `record.id` raises `KeyError` if Record ID# isn't one of them. Each run adds to the report's usage count in Quickbase. ```python run( *, page_size: int = 1000, max_total: int | None = None ) -> RecordIterator ``` **Parameters** - **`page_size`** `int`, default `1000` Records to request per call to Quickbase. - **`max_total`** `int | None`, optional Stop after this many records in all, across pages. **Returns** [`RecordIterator`](https://matthew-williams-solutions.github.io/pyquickbase/reference/records/#RecordIterator) An iterator of [`Record`](https://matthew-williams-solutions.github.io/pyquickbase/reference/records/#Record), which only contacts Quickbase once you start iterating. **Raises** - [`UnknownReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnknownReportError): The table has no such report, or several share the name. - [`UnsupportedReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnsupportedReportError): It isn't a complete table report, such as a summary, chart, or ask-the-user report. Their raw results are available through `qb.request()`. Sync example: ```python report = tasks.report("List All") titles = [record["Title"] for record in report.run()] print(sorted(titles)) ``` Async example: ```python report = tasks.report("List All") titles = [record["Title"] async for record in report.run()] print(sorted(titles)) ``` Output: ```text ['Frame walls', 'Hang drywall', 'Pour slab'] ``` ### `Report.run_page()` Fetch one page of the report's records, for controlling paging yourself. Records hold only the report's columns, and each run adds to the report's usage count in Quickbase. ```python run_page(*, limit: int = 100, skip: int = 0) -> Page ``` **Parameters** - **`limit`** `int`, default `100` The most records to return. - **`skip`** `int`, default `0` How many records to pass over first. Use the previous page's `next_skip`. **Returns** [`Page`](https://matthew-williams-solutions.github.io/pyquickbase/reference/records/#Page) A [`Page`](https://matthew-williams-solutions.github.io/pyquickbase/reference/records/#Page), whose `total` counts every record in the report. **Raises** - [`UnknownReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnknownReportError): The table has no such report, or several share the name. - [`UnsupportedReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnsupportedReportError): It isn't a complete table report, such as a summary, chart, or ask-the-user report. Sync example: ```python report = tasks.report("List All") page = report.run_page(limit=2) print(page.total, page.has_more, page.next_skip) ``` Async example: ```python report = tasks.report("List All") page = await report.run_page(limit=2) print(page.total, page.has_more, page.next_skip) ``` Output: ```text 3 True 2 ``` ### `Report.summary_rows()` Get a summary or chart report's rows, as `{column label: value}`. Quickbase does the calculating, using the report as it was built in the UI. Values are what Quickbase returns, so a chart's dates are text in the app's format, such as `01-01-2026`. Each run adds to the report's usage count in Quickbase. ```python summary_rows( *, page_size: int = 1000, max_total: int | None = None ) -> list[dict[str, Any]] ``` **Parameters** - **`page_size`** `int`, default `1000` Rows to request per call to Quickbase. - **`max_total`** `int | None`, optional Stop after this many rows in all, across pages. **Returns** `list[dict[str, Any]]` The rows. A summary report's total column is labeled like `Hours (tot)`. **Raises** - [`UnknownReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnknownReportError): The table has no such report, or several share the name. - [`UnsupportedReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnsupportedReportError): It's a table report, which [`run()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/report/#run) reads as records. Or Quickbase can't run it, such as a report that asks the user for a value, or two of its columns have the same label. - [`InvalidResponseError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#InvalidResponseError): Quickbase stopped returning rows before the end. Sync example: ```python report = tasks.report("Hours by Status") for row in report.summary_rows(): print(row["Status"], row["Hours (tot)"]) ``` Async example: ```python report = tasks.report("Hours by Status") for row in await report.summary_rows(): print(row["Status"], row["Hours (tot)"]) ``` ## Look up the report's details For the full picture, see [Reading records](https://matthew-williams-solutions.github.io/pyquickbase/guides/reading/). ### `Report.info()` Get the report's metadata, from the table's cached list of reports. ```python info() -> ReportInfo ``` **Returns** [`ReportInfo`](https://matthew-williams-solutions.github.io/pyquickbase/reference/metadata/#ReportInfo) A [`ReportInfo`](https://matthew-williams-solutions.github.io/pyquickbase/reference/metadata/#ReportInfo). **Raises** - [`UnknownReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnknownReportError): The table has no such report, or several share the name. An ID takes priority over a name. Sync example: ```python report = tasks.report("List All") info = report.info() print(info.name, info.type) ``` Async example: ```python report = tasks.report("List All") info = await report.info() print(info.name, info.type) ``` Output: ```text List All table ``` ## Link to the Quickbase interface For the full picture, see [Using pyquickbase from an AI agent](https://matthew-williams-solutions.github.io/pyquickbase/agents/). ### `Report.url()` Link to the report in Quickbase, for viewing it or changing how it's built. It only contacts Quickbase to look up the report's and table's IDs, as [`info()`](https://matthew-williams-solutions.github.io/pyquickbase/reference/report/#info) does, and the client's cache usually has them. ```python url(*, edit: bool = False) -> str ``` **Parameters** - **`edit`** `bool`, default `False` Link to the page that changes the report's settings, rather than the report. **Returns** `str` The URL, on the client's realm. **Raises** - [`UnknownReportError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnknownReportError): The table has no such report, or several share the name, or the client's policy hides it. - [`UnknownTableError`](https://matthew-williams-solutions.github.io/pyquickbase/reference/errors/#UnknownTableError): The app has no such table, or the client's policy hides it. Sync example: ```python report = tasks.report("List All") print(report.url()) print(report.url(edit=True)) ``` Async example: ```python report = tasks.report("List All") print(await report.url()) print(await report.url(edit=True)) ``` Output: ```text https://acme.quickbase.com/nav/app/bq1234567/table/bqtasks123/action/q?qid=1 https://acme.quickbase.com/nav/app/bq1234567/table/bqtasks123/action/viewBuild?qid=1 ```