Overview
A client-mode connector for the BigQuery API v2 that streams MQTT telemetry into BigQuery tables and runs SQL from MQTT:
Default
BASE_ADDRESS is https://bigquery.googleapis.com. Replace YOUR_PROJECT_ID in the endpoints with your GCP project id. Topics use data/google-bigquery/<object>/<verb>.
Auth
BigQuery needs an OAuth 2.0 access token inAuthorization: Bearer …. The template reads it from the MQTT payload field access_token; keep the token in a Hub secret such as GET SECRET "GOOGLE_BIGQUERY_ACCESS_TOKEN" and never commit it.
- Minting the token is out of band. Exchange a service-account key (signed JWT) for an access token with
gcloud auth print-access-token, a Google auth SDK, or your own token service, then publish or refresh it. Access tokens expire after about 1 hour. - Scopes:
https://www.googleapis.com/auth/bigquery(full),https://www.googleapis.com/auth/bigquery.insertdata(streaming insert only), orhttps://www.googleapis.com/auth/cloud-platform. - IAM: the service account needs BigQuery Data Editor on the dataset and BigQuery Job User on the project to run queries.
401 UNAUTHENTICATED response with Request had invalid authentication credentials means the token is missing, malformed, or expired.
Basic Syntax
Request bodies come from
{value.json.body}, not {payload}. The MQTT payload carries control fields (access_token, datasetId, tableId, jobId, location, maxResults) next to a body object, and only body is sent to Google. Google APIs reject unknown top-level fields with 400 Invalid JSON payload received.Example MQTT payloads
Create a dataset (topicdata/google-bigquery/dataset/create):
data/google-bigquery/table/create):
data/google-bigquery/rows/insert). insertId gives best-effort de-duplication on retries:
{"kind":"bigquery#tableDataInsertAllResponse"}. Rejected rows return HTTP 200 with insertErrors (for example no such field: pressure.), so check the response body, not just the status.
Run SQL (topic data/google-bigquery/query/run):
data/google-bigquery/query/results, data/google-bigquery/job/get):
Quotas and limits
insertAll: up to 10 MB per request; Google recommends about 500 rows per request. Streamed rows are queryable within seconds, but they can’t be changed with DML for a short window after insert.jobs.querywaits up totimeoutMs(default 10 s). IfjobCompleteisfalse, pollGetQueryResultswithjobReference.jobId.- On-demand queries are billed by bytes scanned. Use partitioned tables and
WHEREfilters on high-rate telemetry. See BigQuery quotas.

