Step 1: Choose a project and enable the BigQuery API
- Open the Google Cloud Console and create or select a project.
- Copy the project ID (not the project name). It is the lowercase identifier shown in IAM & Admin > Settings.
- In APIs & Services > Library, search for BigQuery API and click Enable.
Step 2: Create the dataset
- Open BigQuery > Explorer, select the project, and choose Create dataset.
- Choose a dataset ID, such as
openrouter. - Choose the dataset location carefully. A dataset’s region cannot be changed after creation, so pick a location allowed by your data-residency requirements.

Step 3: Create the traces table
Create theopenrouter_traces table in your dataset. You can find the exact SQL in the OpenRouter dashboard when configuring the destination — click View Setup Instructions. Replace my-gcp-project in the DDL with your project ID (and the dataset or table IDs if you chose different ones), then run it in the BigQuery SQL workspace:


Step 4: Create a service account
- Open IAM & Admin > Service Accounts in the project and click Create service account (e.g.,
openrouter-broadcast). - Grant it the BigQuery Data Editor role on the trace dataset (not at the organization or project level): open the dataset’s menu in BigQuery, choose Share > Permissions, add the service account email, and select BigQuery Data Editor. Do not grant BigQuery Job User — this destination uses streaming inserts and does not create query jobs.
- Open the service account’s Keys tab, choose Add key > Create new key, select JSON, and download the key.
Step 5: Enable Broadcast in OpenRouter
Go to Settings > Observability and toggle Enable Broadcast.
Step 6: Configure BigQuery
Click the edit icon next to Google BigQuery and enter:
- Google Cloud project ID: The project ID containing the dataset.
- Service-account key JSON: The complete contents of the downloaded JSON key file.
- BigQuery dataset: The dataset ID created above (default:
openrouter). - BigQuery table: The table ID created above (default:
openrouter_traces).
Step 7: Test and save
Click Test Connection to verify the setup. The connection test reads the table’s metadata to verify the project, dataset, table, and credentials, then checks that the credentials hold the row-insert permission, so read-only access fails the test rather than failing on every later trace. The configuration only saves if the test passes.Step 8: Send a test trace
Click Send Trace, or make an API request through OpenRouter, and query your BigQuery table to verify the trace was received:
Example queries
Cost analysis by model
User activity analysis
Error analysis
Provider performance comparison
Usage by API key
Accessing JSON columns
Theattributes, input, output, metadata, model_parameters, and resource_attributes columns are JSON typed. Use BigQuery’s JSON functions to query nested fields:
Schema design
The dashboard-generatedCREATE TABLE statement is the source of truth for setup. The field reference below describes the current schema without duplicating the generated SQL.
Field reference
Field ownership and custom metadata
OpenRouter populates all columns except for the following caller-controlled values:trace_idcan be set withtrace.trace_id. If supplied, the same trace ID can span multiple API requests.parent_span_idcan be set withtrace.parent_span_id.user_idcomes from the requestuserfield.session_idcomes from the requestsession_idfield.- Custom values are stored in the
metadataJSONcolumn.
trace are merged into metadata using their original keys. Top-level request metadata.<k> values are also placed in metadata, under the key metadata_<k>. There is no separate database column for each custom key. trace_name and generation_name affect internal trace and observation names but have no dedicated table columns. trace.span_name is accepted as a reserved request field but is currently ignored.
Rows and aggregation
Unlike the Snowflake and ClickHouse destinations, BigQuery receives one row per generation, not one row per observation. Each API request produces a singleGENERATION row:
span_idis the generation ID.parent_span_idisNULLunless the request settrace.parent_span_id.- Per-attempt provider detail is in
metadata.provider_responses, and phase timings are in theopenrouter_*fields ofattributes.
span_type. If you set trace.trace_id across requests, several rows share one trace_id, so count requests with span_id rather than trace_id.
BigQuery deduplicates streaming inserts on (trace_id, span_id) on a best-effort basis only, so a retried insert can still land a duplicate row. Deduplicate on (trace_id, span_id) to remove duplicates. Rows that BigQuery permanently rejects, or that still fail after transient retries, are dropped rather than redelivered, so deduplication can’t recover missing rows.
Typed columns
The field reference above identifies commonly queried identifiers, timestamps, model information, token metrics, and cost metrics as typed columns for efficient filtering and aggregation.JSON columns
Less commonly accessed and variable-structure data is stored in theJSON columns identified in the field reference above. The tags column is a repeated STRING column (ARRAY<STRING>). Use BigQuery’s JSON_VALUE and JSON_QUERY functions to query the JSON fields.
Custom Metadata
Custom metadata from thetrace field is stored in the metadata JSON column. You can query it using BigQuery’s JSON functions.
Supported Metadata Keys
Example
Querying Custom Metadata
Additional Context
- The
userfield maps to theuser_idtyped column - The
session_idfield maps to thesession_idtyped column - Additional custom keys from
traceare stored in themetadataJSON column for flexible querying trace_nameandgeneration_nameaffect internal names but have no dedicated table columnstrace.span_nameis reserved and currently ignored
Troubleshooting
- Project not found or permission denied: Confirm that the configured project ID is the project containing the dataset and that the service account belongs to the expected project.
- Table not found: Confirm the dataset and table IDs and that the table was created in the configured dataset location.
- 403 permission denied: Grant the service account BigQuery Data Editor on the dataset. Project-level access may be restricted by organization policy, so verify the dataset permission directly.
- 400 invalid or schema mismatch: Compare the table schema with the DDL from the setup instructions. In particular, timestamps must be
TIMESTAMP, nested trace fields must beJSON, andtagsmust beARRAY<STRING>.