BountyHub Docs
Datasets API and CLI
DatasetService and DatasetViewService RPCs, request and response shapes, pagination, exports, describe, scopes, and the bh dataset commands.
Datasets API and CLI
Datasets are exposed through two ConnectRPC services:
bountyhub.dataset.v1.DatasetService— datasets, ingest, SQL, describe, export.bountyhub.dataset.v1.DatasetViewService— saved views.
The generated TypeScript SDK exposes datasetClient and datasetViewClient; the
bh CLI wraps the most common DatasetService calls. In Connect JSON, int64
and uint64 fields (for example rowCount) are encoded as strings.
#Authentication and scopes
| Access | Scope |
|---|---|
| Get, list, query, project-wide query, describe, export, execute view | DatasetRo |
| Create, update, delete, ingest, delete rows, clear, create/update/delete view | DatasetRw |
Create a Personal Access Token with the Datasets scope (and Projects read, which it requires). See Personal Access Token scopes.
#DatasetService
| RPC | Purpose | Pagination |
|---|---|---|
CreateDataset | Create a table and schema | — |
GetDataset | Read one dataset | — |
ListDatasets | List project datasets | Default 50, max 500 |
UpdateDataset | Change name or description | — |
DeleteDataset | Delete the dataset and its files | — |
IngestDatasetRows | Append observations | — |
DeleteDatasetRows | Soft- or hard-delete records selected by a filter | — |
ClearDataset | Remove every record and stored file | — |
QueryDataset | One read-only SELECT over dataset | Default 100, max 1,000 |
QueryDatasets | One SELECT over every dataset in a project | Default 100, max 1,000 |
DescribeDataset | Null/distinct counts and top values | — |
ExportDataset | Stream a full query result to a file | — |
#CreateDataset
Returns { "id": "<dataset-uuid>" }. Names must be unique per project, sharing
one case-insensitive namespace with saved views; up to 100 datasets are allowed.
See Schemas and identity.
#IngestDatasetRows
fieldsis keyed by column name; the service maps values by schema order.- Missing fields become
NULL; aNULLin a non-nullable column fails. - Values must match the column kind (see Structured filters for the value shape).
modeisDATASET_INGEST_MODE_UPSERT(default) orDATASET_INGEST_MODE_SYNC.- Returns
{ "rowCount": "<n>" }.
#DeleteDatasetRows
filter is required and selects records from the current logical state.
DATASET_DELETE_MODE_SOFT appends tombstones and requires identity columns;
DATASET_DELETE_MODE_HARD removes the matching observations from stored files.
Returns { "deletedRowCount": "<n>", "storageDeltaBytes": "<signed bytes>" }.
#ClearDataset
Removes every record and stored file. Returns { "deletedRowCount": "<n>", "storageDeltaBytes": "<negative bytes>" }.
#QueryDataset
| Field | Meaning |
|---|---|
sql | One read-only SELECT; a bare SELECT * becomes SELECT * FROM dataset. |
pageSize | Default 100, max 1,000. |
pageToken | Cursor from nextPageToken. |
includeHistory | Query raw observations instead of current state. |
ingestedAtFrom / ingestedAtTo | Bound __ingested_at. |
filter | Typed filter tree; see Structured filters. |
The response contains schema.columns, rows (values in schema order), and
nextPageToken.
#QueryDatasets
Returns { "result": { "columns", "rows", "nextPageToken" } }. Filter with the
SQL WHERE clause; the per-relation filters field is reserved and not
supported by the current execution path. This path has no history mode.
Project-wide SQL is API-only; the Hub UI's SQL box is scoped to one dataset.
#DescribeDataset
Returns one entry per schema column with:
| Field | Meaning |
|---|---|
nullCount | Rows where the column is NULL. |
distinctCount | Distinct non-null values. |
topValues | Up to 10 most frequent non-null values, most frequent first. |
bh dataset describe prints the first three top values.
#ExportDataset
| Format | Enum | Content type |
|---|---|---|
| CSV | DATASET_EXPORT_FORMAT_CSV | text/csv |
| JSON Lines | DATASET_EXPORT_FORMAT_JSONL | application/x-ndjson |
| JSON array | DATASET_EXPORT_FORMAT_JSON | application/json |
sqlis required; useSELECT * FROM datasetfor a full export.- Filters and time bounds use the same outer semantics as
QueryDataset. - Exports have no page size or row cap; rows stream to the file.
- The response returns
url(presigned, valid for 15 minutes),fileName,contentType,rowCount, andsizeBytes.
#DatasetViewService
| RPC | Scope | Notes |
|---|---|---|
CreateDatasetView | DatasetRw | Validates SQL, references, and cycles. |
GetDatasetView | DatasetRo | Returns valid and invalidReason. |
ListDatasetViews | DatasetRo | Default 50, max 500. |
UpdateDatasetView | DatasetRw | Changes name, description, and SQL; resets validity. |
DeleteDatasetView | DatasetRw | Invalidates dependent views. |
ExecuteDatasetView | DatasetRo | Default 100, max 10,000. |
ExecuteDatasetView returns { "result": { "columns", "rows", "nextPageToken" } }. Views run over the current state and have no filter,
history, or time-range fields; see Saved views.
#bh CLI
The CLI wraps DatasetService for the common read and manage paths:
bh dataset query prints a next page token line when more rows are available
and accepts --page-size (default 100). It has no page-token flag; use the API
(QueryDataset) to continue past the first page.
There are no CLI commands for project-wide SQL, saved views, exports, or row ingestion — use the API for those.
#Errors
| Connect code | Cause |
|---|---|
UNAUTHENTICATED | Missing or invalid token. |
PERMISSION_DENIED | The PAT lacks DatasetRo / DatasetRw. |
NOT_FOUND | Unknown dataset or view, or one outside the caller's projects. |
ALREADY_EXISTS | Dataset name already used in the project. |
INVALID_ARGUMENT | Invalid schema, SQL, filter, id, or page token; a view cannot be evaluated. |
RESOURCE_EXHAUSTED | Too many concurrent queries or too many per minute. |
#Related
- Schemas and identity — column kinds and identity.
- SQL reference — query language and limits.
- Structured filters — filter AST and value types.
- Saved views — view semantics.
- Personal Access Token scopes — scope names.