# Export audit logs
Source: https://api-docs.select.dev/v2-api-reference/audit-logs/export-audit-logs
https://api.select.dev/v2/openapi.json get /audit-logs
Append-only, oldest-first stream of audit log records, designed for continuous polling (e.g. SIEM export). Records are immutable once written.
The audit log records every create, update, and delete on your SELECT resources, plus events like login and org membership changes — who changed what, and when. Each record is tied to either a `resource` (something in SELECT that changed) or an `event_type` (something that happened with no resource).
| Name | Kind | What it is |
| --- | --- | --- |
| `actions` | resource | Cost-saving actions |
| `alert_destinations` | resource | Alert destinations (Slack channels, MS Teams webhooks, email addresses) |
| `alert_integrations` | resource | Alert notification integrations (Slack, MS Teams, email) |
| `api_keys` | resource | API keys |
| `budgets` | resource | Budgets |
| `connections` | resource | Data warehouse connections |
| `dashboards` | resource | Dashboards |
| `dashboard_digests` | resource | Scheduled dashboard digests |
| `insights` | resource | Insights |
| `monitors_v2` | resource | Monitors |
| `saved_views` | resource | Saved views |
| `snowflake_warehouses` | resource | Snowflake warehouse settings |
| `teams` | resource | Teams |
| `ticket_integrations` | resource | Ticketing tool integrations (Jira, etc.) |
| `ticket_links` | resource | Links between SELECT items and external tickets |
| `user_roles` | resource | User and role assignments |
| `usage_group_sets` | resource | Usage group sets |
| `session` | event | Login / logout |
| `invitation` | event | Org invitation created / revoked |
| `users` | event | User removed from the org |
| `organization` | event | Organization-level settings: trial end date, app warehouse size, feature enablement, data share provisioning |
## How to poll
Page with `page_token`, and drain every poll until `page_token` is `null`:
1. **First run** — call with no `page_token`. Optionally set `changed_at__gte` to a start date to skip old history.
2. **Drain** — keep re-requesting with the `page_token` from the previous response until the response returns `page_token: null` (you are caught up).
3. **Persist** the last non-null `page_token` you received.
4. **Next poll** — resume from that stored `page_token`. It continues strictly after the last record you ingested, so every new record is delivered exactly once.
> **Do not build your own cursor from `changed_at`.** Bulk operations can stamp thousands of records with the exact same `changed_at`. A client that computes its next request from `max(changed_at)` will re-receive duplicates and, if a single-timestamp cluster is larger than `max_results`, loop forever and never advance past it. Always page with `page_token`.
`sort_order` defaults to `asc` (oldest-first) to preserve the SIEM drain-forward contract above; pass `desc` for newest-first. A `page_token` carries the `sort_order` it was minted with, so resuming with the other order is rejected rather than silently resuming in the wrong direction.
# Get a connection
Source: https://api-docs.select.dev/v2-api-reference/connections/get-a-connection
https://api.select.dev/v2/openapi.json get /connections/{connection_id}
Get a single connection by id.
# List connections
Source: https://api-docs.select.dev/v2-api-reference/connections/list-connections
https://api.select.dev/v2/openapi.json get /connections
List the connections in your organization, oldest first.
No ETag: a page is not a resource, and the connections it holds each carry
their own.
# Test Looker BI access for a connection
Source: https://api-docs.select.dev/v2-api-reference/connections/test-looker-bi-access-for-a-connection
https://api.select.dev/v2/openapi.json post /connections/{connection_id}/actions/test-looker
Test Looker BI access for an existing connection.
Any field the body omits falls back to the connection's currently stored
Looker configuration, so an empty body re-tests what's saved.
# Update a connection
Source: https://api-docs.select.dev/v2-api-reference/connections/update-a-connection
https://api.select.dev/v2/openapi.json patch /connections/{connection_id}
Update a connection's Looker configuration.
Merge-patch: only the fields you send change; omitted fields are left
as-is. `looker_base_url: null` disconnects Looker, clearing all three
Looker fields together.
# Create a default role grant
Source: https://api-docs.select.dev/v2-api-reference/default-roles/create-a-default-role-grant
https://api.select.dev/v2/openapi.json post /default-roles
Grant a role to every member of your organization by default.
Scope it to a resource, or omit the scope to grant it across the whole
organization. There is no minimum — an organization may have none of these.
# Delete a default role grant
Source: https://api-docs.select.dev/v2-api-reference/default-roles/delete-a-default-role-grant
https://api.select.dev/v2/openapi.json delete /default-roles/{role_id}
Revoke a default role grant. Members stop holding it immediately.
# List default role grants
Source: https://api-docs.select.dev/v2-api-reference/default-roles/list-default-role-grants
https://api.select.dev/v2/openapi.json get /default-roles
List the roles every member of your organization holds by default.
# Analyze a query for optimization insights
Source: https://api-docs.select.dev/v2-api-reference/insights/analyze-a-query-for-optimization-insights
https://api.select.dev/v2/openapi.json post /insights/actions/analyze-query
Reports the optimization opportunities SELECT can find in a single query execution, by examining the query alongside the execution profile Snowflake recorded for it. An empty list means the query was examined and nothing was found.
# Generate a code change for an insight
Source: https://api-docs.select.dev/v2-api-reference/insights/generate-a-code-change-for-an-insight
https://api.select.dev/v2/openapi.json post /insights/actions/generate-code-change
Suggests a rewrite of a query that applies one of the optimization opportunities SELECT detected on it. The rewrite is generated by a language model from the query and its execution profile: treat it as a suggestion and review it before running it.
# Get an insight
Source: https://api-docs.select.dev/v2-api-reference/insights/get-an-insight
https://api.select.dev/v2/openapi.json get /insights/{insight_id}
# List insights
Source: https://api-docs.select.dev/v2-api-reference/insights/list-insights
https://api.select.dev/v2/openapi.json get /insights
# Query insights by dimension and measure
Source: https://api-docs.select.dev/v2-api-reference/insights/query-insights-by-dimension-and-measure
https://api.select.dev/v2/openapi.json post /insights/actions/query
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
# Record that the caller viewed an insight
Source: https://api-docs.select.dev/v2-api-reference/insights/record-that-the-caller-viewed-an-insight
https://api.select.dev/v2/openapi.json post /insights/{insight_id}/actions/viewed
Records a view of the insight by the calling user: sets its first- and last-view times and increments its view count at most once per calendar day. Calls authenticated with an API key are accepted without recording a view.
# Update an insight
Source: https://api-docs.select.dev/v2-api-reference/insights/update-an-insight
https://api.select.dev/v2/openapi.json patch /insights/{insight_id}
# Invite a user
Source: https://api-docs.select.dev/v2-api-reference/invitations/invite-a-user
https://api.select.dev/v2/openapi.json post /invitations
Emails an invitation to join the organization. The invitee joins with no roles until they are granted some.
# List invitations
Source: https://api-docs.select.dev/v2-api-reference/invitations/list-invitations
https://api.select.dev/v2/openapi.json get /invitations
Lists the organization's pending invitations, oldest first. An invitation leaves the list once it is accepted or revoked.
# Revoke an invitation
Source: https://api-docs.select.dev/v2-api-reference/invitations/revoke-an-invitation
https://api.select.dev/v2/openapi.json delete /invitations/{invitation_id}
Revokes a pending invitation, so its link no longer lets the invitee join.
# Add a Snowflake account
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/add-a-snowflake-account
https://api.select.dev/v2/openapi.json post /snowflake-accounts
Add a Snowflake account to your organization.
# Delete a Snowflake account
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/delete-a-snowflake-account
https://api.select.dev/v2/openapi.json delete /snowflake-accounts/{snowflake_account_id}
Delete a Snowflake account and clean up the external resources it owned.
# Get a Snowflake account
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/get-a-snowflake-account
https://api.select.dev/v2/openapi.json get /snowflake-accounts/{snowflake_account_id}
Get a single Snowflake account by id.
# Get a Snowflake account's credential configuration
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/get-a-snowflake-accounts-credential-configuration
https://api.select.dev/v2/openapi.json get /snowflake-accounts/{snowflake_account_id}/credentials
Read which authentication method and Snowflake user this account
connects with.
# List Snowflake accounts
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/list-snowflake-accounts
https://api.select.dev/v2/openapi.json get /snowflake-accounts
List the Snowflake accounts in your organization, oldest first.
No ETag: a page is not a resource, and the accounts it holds each carry
their own.
# Test a Snowflake account configuration
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/test-a-snowflake-account-configuration
https://api.select.dev/v2/openapi.json post /snowflake-accounts/actions/test
Validate a proposed Snowflake account configuration without adding it.
# Test an added Snowflake account
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/test-an-added-snowflake-account
https://api.select.dev/v2/openapi.json post /snowflake-accounts/{snowflake_account_id}/actions/test
Re-run validation against an already-added Snowflake account.
# Test Mode BI access for an account
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/test-mode-bi-access-for-an-account
https://api.select.dev/v2/openapi.json post /snowflake-accounts/{snowflake_account_id}/actions/test-mode
Test Mode BI access for a Snowflake account.
Any field left out of the body falls back to the account's currently
stored Mode configuration.
# Update a Snowflake account
Source: https://api-docs.select.dev/v2-api-reference/snowflake-accounts/update-a-snowflake-account
https://api.select.dev/v2/openapi.json patch /snowflake-accounts/{snowflake_account_id}
Update a Snowflake account.
Merge-patch: only the fields you send change; omitted fields are left as-is.
# Create an SSO group
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/create-an-sso-group
https://api.select.dev/v2/openapi.json post /sso-groups
Map a group from your identity provider and grant it its first roles.
Members of the group receive these roles when they log in. At least one role
is required: a group exists only for the roles it carries.
# Delete an SSO group
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/delete-an-sso-group
https://api.select.dev/v2/openapi.json delete /sso-groups/{sso_group_id}
Delete an SSO group and every role it grants.
Members of the group stop receiving those roles at their next login.
# Get an SSO group
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/get-an-sso-group
https://api.select.dev/v2/openapi.json get /sso-groups/{sso_group_id}
Get a single SSO group by id, which is its name.
# Grant a role to an SSO group
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/grant-a-role-to-an-sso-group
https://api.select.dev/v2/openapi.json post /sso-groups/{sso_group_id}/roles
Grant a role to a group, scoped to a resource or to the whole organization.
# List roles granted to an SSO group
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/list-roles-granted-to-an-sso-group
https://api.select.dev/v2/openapi.json get /sso-groups/{sso_group_id}/roles
List the roles granted to a group, each with the scope it applies to.
# List SSO groups
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/list-sso-groups
https://api.select.dev/v2/openapi.json get /sso-groups
List the SSO groups mapped in your organization.
# Rename an SSO group
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/rename-an-sso-group
https://api.select.dev/v2/openapi.json patch /sso-groups/{sso_group_id}
Rename an SSO group, keeping the roles it grants.
Merge-patch: only the fields you send change; omitted fields are left as-is.
The name is the group's id, so a rename moves the group to a new URL — the
response carries the new id, and requests to the old one return 404.
# Revoke a role from an SSO group
Source: https://api-docs.select.dev/v2-api-reference/sso-groups/revoke-a-role-from-an-sso-group
https://api.select.dev/v2/openapi.json delete /sso-groups/{sso_group_id}/roles/{role_id}
Revoke a role from a group.
A group's last role cannot be revoked — delete the group instead.
# Add a Tableau connection
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/add-a-tableau-connection
https://api.select.dev/v2/openapi.json post /tableau-connections
Add a Tableau connection to your organization.
# Delete a Tableau connection
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/delete-a-tableau-connection
https://api.select.dev/v2/openapi.json delete /tableau-connections/{tableau_connection_id}
Delete a Tableau connection and clean up the external resources it owned.
# Get a Tableau connection
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/get-a-tableau-connection
https://api.select.dev/v2/openapi.json get /tableau-connections/{tableau_connection_id}
Get a single Tableau connection by id.
# Get a Tableau connection's credential configuration
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/get-a-tableau-connections-credential-configuration
https://api.select.dev/v2/openapi.json get /tableau-connections/{tableau_connection_id}/credentials
Get which personal access token a connection authenticates as.
# List Tableau connections
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/list-tableau-connections
https://api.select.dev/v2/openapi.json get /tableau-connections
List the Tableau connections in your organization, oldest first.
No ETag: a page is not a resource, and the connections it holds each carry
their own.
# Test a Tableau connection configuration
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/test-a-tableau-connection-configuration
https://api.select.dev/v2/openapi.json post /tableau-connections/actions/test
Validate a proposed Tableau connection configuration without adding it.
# Update a Tableau connection
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/update-a-tableau-connection
https://api.select.dev/v2/openapi.json patch /tableau-connections/{tableau_connection_id}
Update a Tableau connection.
Merge-patch: only the fields you send change; omitted fields are left as-is.
# Add a team member
Source: https://api-docs.select.dev/v2-api-reference/teams/add-a-team-member
https://api.select.dev/v2/openapi.json post /teams/{team_id}/members
Add a user or SSO group to a team.
# Create a team
Source: https://api-docs.select.dev/v2-api-reference/teams/create-a-team
https://api.select.dev/v2/openapi.json post /teams
Create a team in your organization.
# Delete a team
Source: https://api-docs.select.dev/v2-api-reference/teams/delete-a-team
https://api.select.dev/v2/openapi.json delete /teams/{team_id}
Delete a team, along with its memberships and role grants.
# Get a team
Source: https://api-docs.select.dev/v2-api-reference/teams/get-a-team
https://api.select.dev/v2/openapi.json get /teams/{team_id}
Get a single team by id.
# Grant a role to a team
Source: https://api-docs.select.dev/v2-api-reference/teams/grant-a-role-to-a-team
https://api.select.dev/v2/openapi.json post /teams/{team_id}/roles
Grant a role to a team, scoped to a resource or to the whole organization.
Every member of the team inherits the granted role on that scope.
# List roles granted to a team
Source: https://api-docs.select.dev/v2-api-reference/teams/list-roles-granted-to-a-team
https://api.select.dev/v2/openapi.json get /teams/{team_id}/roles
List the roles granted to a team, each with the scope it applies to.
# List team members
Source: https://api-docs.select.dev/v2-api-reference/teams/list-team-members
https://api.select.dev/v2/openapi.json get /teams/{team_id}/members
List a team's explicit members — the users and SSO groups assigned to it.
The all-users team returns an empty list: its membership is every organization
member, derived rather than stored, so there are no explicit members to page.
# List teams
Source: https://api-docs.select.dev/v2-api-reference/teams/list-teams
https://api.select.dev/v2/openapi.json get /teams
List the teams in your organization.
# Remove a team member
Source: https://api-docs.select.dev/v2-api-reference/teams/remove-a-team-member
https://api.select.dev/v2/openapi.json delete /teams/{team_id}/members/{member_id}
Remove a user or SSO group from a team.
# Revoke a role from a team
Source: https://api-docs.select.dev/v2-api-reference/teams/revoke-a-role-from-a-team
https://api.select.dev/v2/openapi.json delete /teams/{team_id}/roles/{role_id}
Revoke a role from a team.
The team's members lose the access this grant gave them.
# Set team memberships for a batch of users
Source: https://api-docs.select.dev/v2-api-reference/teams/set-team-memberships-for-a-batch-of-users
https://api.select.dev/v2/openapi.json post /teams/actions/batch-update-memberships
Set the explicit team memberships for one or more users.
For each listed user, removes all of their current explicit
(individually-assigned) team memberships across the organization, then grants
the specified role on each listed team. Memberships held through an SSO group
are never affected, and a user already in a listed team via SSO is skipped.
This is a full replacement, not an incremental add — any explicit membership
not present in this request is removed.
# Update a team
Source: https://api-docs.select.dev/v2-api-reference/teams/update-a-team
https://api.select.dev/v2/openapi.json patch /teams/{team_id}
Update a team's name or default member role.
Merge-patch: only the fields you send change; omitted fields are left as-is.
# Update a team member
Source: https://api-docs.select.dev/v2-api-reference/teams/update-a-team-member
https://api.select.dev/v2/openapi.json patch /teams/{team_id}/members/{member_id}
Update a team member's role.
Merge-patch: only the fields you send change; omitted fields are left as-is.
# Connect a Jira site with an API token
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/connect-a-jira-site-with-an-api-token
https://api.select.dev/v2/openapi.json post /ticket-integrations
Connect a Jira Cloud site using an Atlassian account's email and API token.
The credentials are checked against the site before anything is saved, and
the site's Atlassian cloud id is looked up and returned as `external_id`;
a site that does not report one is not connected. If the site was
connected before and later disconnected, it is reconnected under its
original id and its ticket links are restored.
# Disconnect a ticket integration
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/disconnect-a-ticket-integration
https://api.select.dev/v2/openapi.json delete /ticket-integrations/{ticket_integration_id}
Disconnect a ticket integration.
SELECT stops receiving updates from the site and deletes its stored
credentials, unless another connected site was authorized by the same OAuth
approval and still uses them. Ticket links made through it are kept, marked disconnected,
and restored if the same site is connected again.
# Get a Jira issue
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/get-a-jira-issue
https://api.select.dev/v2/openapi.json get /ticket-integrations/{ticket_integration_id}/issues/{issue_id}
Get one issue on the integration's Jira site, read live from Jira.
`issue_id` is the issue's key, such as `ENG-123`, or Jira's numeric id for
it.
# Get a ticket integration
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/get-a-ticket-integration
https://api.select.dev/v2/openapi.json get /ticket-integrations/{ticket_integration_id}
Get a single ticket integration by id.
# List Jira issue types for a project
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/list-jira-issue-types-for-a-project
https://api.select.dev/v2/openapi.json get /ticket-integrations/{ticket_integration_id}/issue-types
List the kinds of issue that can be created in a Jira project.
Read live from Jira. `row_count` is Jira's count of the project's issue
types.
# List Jira priorities
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/list-jira-priorities
https://api.select.dev/v2/openapi.json get /ticket-integrations/{ticket_integration_id}/priorities
List the priorities an issue on the integration's Jira site can be given.
Priorities are defined for the whole site rather than per project. Read
live from Jira and returned in full, so `page_token` is always absent.
# List Jira projects
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/list-jira-projects
https://api.select.dev/v2/openapi.json get /ticket-integrations/{ticket_integration_id}/projects
List the projects on the integration's Jira site, read live from Jira.
Only projects the connected account can see are listed. Jira may return
fewer than `max_results` on a page; keep following `page_token` until it is
absent. `row_count` is Jira's count of all such projects.
# List ticket integrations
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/list-ticket-integrations
https://api.select.dev/v2/openapi.json get /ticket-integrations
List the ticketing systems your organization is connected to, oldest first.
Includes integrations still waiting on an OAuth approval, with status
`pending`.
# Search assignable Jira users
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/search-assignable-jira-users
https://api.select.dev/v2/openapi.json post /ticket-integrations/{ticket_integration_id}/users/actions/search
Find the people who can be assigned issues in a Jira project.
Read live from Jira. Only people with an Atlassian account are returned,
so a page may hold fewer than `max_results` people even when more follow;
keep following `page_token` until it is absent. `row_count` is not
reported.
# Search Jira epics in a project
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/search-jira-epics-in-a-project
https://api.select.dev/v2/openapi.json post /ticket-integrations/{ticket_integration_id}/epics/actions/search
Find the epics in a Jira project, most recently updated first.
Read live from Jira. `max_results` is at most 100. `row_count` is not
reported.
# Search Jira issues
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/search-jira-issues
https://api.select.dev/v2/openapi.json post /ticket-integrations/{ticket_integration_id}/issues/actions/search
Find issues on the integration's Jira site by key or summary.
Matches partial issue keys as well as summary words, ranked the way Jira's
own issue search box ranks them. Results are not paginated: at most
`max_results` best matches (15 by default, up to 50) are returned, and
`page_token` is always absent. Narrow the query to find an issue that is
not among them.
# Start connecting a Jira site through OAuth
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/start-connecting-a-jira-site-through-oauth
https://api.select.dev/v2/openapi.json post /ticket-integrations/actions/start-oauth
Begin a browser-based OAuth connect and get the Atlassian consent URL.
Open the returned URL in the browser of the person granting access. The
integration is connected once they approve. To connect without a browser,
use an API token instead.
# Update a ticket integration
Source: https://api-docs.select.dev/v2-api-reference/ticket-integrations/update-a-ticket-integration
https://api.select.dev/v2/openapi.json patch /ticket-integrations/{ticket_integration_id}
Update a ticket integration.
JSON Merge Patch: only the fields you send change, omitted fields are left
as they are, and `null` clears a field. Requires the integration's current
`ETag` in `If-Match`.
# Create a ticket and link it to a resource
Source: https://api-docs.select.dev/v2-api-reference/ticket-links/create-a-ticket-and-link-it-to-a-resource
https://api.select.dev/v2/openapi.json post /ticket-links/actions/create-ticket
# Get a ticket link
Source: https://api-docs.select.dev/v2-api-reference/ticket-links/get-a-ticket-link
https://api.select.dev/v2/openapi.json get /ticket-links/{ticket_link_id}
# Get the links on many resources
Source: https://api-docs.select.dev/v2-api-reference/ticket-links/get-the-links-on-many-resources
https://api.select.dev/v2/openapi.json post /ticket-links/actions/batch-get
# Link a ticket to a resource
Source: https://api-docs.select.dev/v2-api-reference/ticket-links/link-a-ticket-to-a-resource
https://api.select.dev/v2/openapi.json post /ticket-links
# List ticket links
Source: https://api-docs.select.dev/v2-api-reference/ticket-links/list-ticket-links
https://api.select.dev/v2/openapi.json get /ticket-links
# Remove a ticket link
Source: https://api-docs.select.dev/v2-api-reference/ticket-links/remove-a-ticket-link
https://api.select.dev/v2/openapi.json delete /ticket-links/{ticket_link_id}
# Suggest ticket wording for a resource
Source: https://api-docs.select.dev/v2-api-reference/ticket-links/suggest-ticket-wording-for-a-resource
https://api.select.dev/v2/openapi.json post /ticket-links/actions/generate-suggestion
Suggests a title and description for an issue about a SELECT resource, written by a language model from the details SELECT holds about that resource. Nothing is created or linked: treat the wording as a draft and review it before filing.
# Create a usage group
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/create-a-usage-group
https://api.select.dev/v2/openapi.json post /usage-group-sets/{usage_group_set_id}/usage-groups
# Create a usage group set
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/create-a-usage-group-set
https://api.select.dev/v2/openapi.json post /usage-group-sets
# Create a usage group set version
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/create-a-usage-group-set-version
https://api.select.dev/v2/openapi.json post /usage-group-sets/{usage_group_set_id}/versions
Record the set's current usage groups as a new version.
Versions form a linear history in which the newest one holds the live
groups. Usage group writes change that newest version in place and never
add a version on their own. Creating a version copies the live groups into
a new newest version, which freezes the previous version as a restorable
checkpoint and makes the copy the one later writes change. Call this before
a batch of changes to keep the state they start from, or after one to keep
the state they produce. The set's `version` count goes up by one.
Takes no request body. `If-Match` is optional: omit it to record the groups
as they stand when the call runs, or send the set's ETag to fail with 412 if
the set changed since you read it.
# Delete a usage group
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/delete-a-usage-group
https://api.select.dev/v2/openapi.json delete /usage-group-sets/{usage_group_set_id}/usage-groups/{usage_group_id}
# Delete a usage group set
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/delete-a-usage-group-set
https://api.select.dev/v2/openapi.json delete /usage-group-sets/{usage_group_set_id}
# Get a usage group
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/get-a-usage-group
https://api.select.dev/v2/openapi.json get /usage-group-sets/{usage_group_set_id}/usage-groups/{usage_group_id}
# Get a usage group set
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/get-a-usage-group-set
https://api.select.dev/v2/openapi.json get /usage-group-sets/{usage_group_set_id}
# Get a usage group set version
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/get-a-usage-group-set-version
https://api.select.dev/v2/openapi.json get /usage-group-sets/{usage_group_set_id}/versions/{version_id}
# List a usage group set's versions
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/list-a-usage-group-sets-versions
https://api.select.dev/v2/openapi.json get /usage-group-sets/{usage_group_set_id}/versions
Every version of the set, newest first, each with the groups it holds.
The first item is the live version; the rest are frozen checkpoints.
# List usage group sets
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/list-usage-group-sets
https://api.select.dev/v2/openapi.json get /usage-group-sets
# List usage groups in a set
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/list-usage-groups-in-a-set
https://api.select.dev/v2/openapi.json get /usage-group-sets/{usage_group_set_id}/usage-groups
# Replace all usage groups in a set
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/replace-all-usage-groups-in-a-set
https://api.select.dev/v2/openapi.json put /usage-group-sets/{usage_group_set_id}/usage-groups
# Update a usage group
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/update-a-usage-group
https://api.select.dev/v2/openapi.json patch /usage-group-sets/{usage_group_set_id}/usage-groups/{usage_group_id}
# Update a usage group set
Source: https://api-docs.select.dev/v2-api-reference/usage-group-sets/update-a-usage-group-set
https://api.select.dev/v2/openapi.json patch /usage-group-sets/{usage_group_set_id}
# Get a role a user holds
Source: https://api-docs.select.dev/v2-api-reference/users/get-a-role-a-user-holds
https://api.select.dev/v2/openapi.json get /users/{email}/roles/{role_id}
Get a single role the user holds, from any of its three sources.
# Grant a role to a user
Source: https://api-docs.select.dev/v2-api-reference/users/grant-a-role-to-a-user
https://api.select.dev/v2/openapi.json post /users/{email}/roles
Grant a role to a user, scoped to a resource or to the whole organization.
Roles are held against an email address, which need not belong to a member
yet: granting to an address you have invited takes effect when they first
sign in.
# List the roles a user holds
Source: https://api-docs.select.dev/v2-api-reference/users/list-the-roles-a-user-holds
https://api.select.dev/v2/openapi.json get /users/{email}/roles
List every role a user holds, each with the scope it applies to.
Covers all three sources: roles granted to the user directly, roles they
inherit from a team, and the organization's default roles.
# List the teams a user belongs to
Source: https://api-docs.select.dev/v2-api-reference/users/list-the-teams-a-user-belongs-to
https://api.select.dev/v2/openapi.json get /users/{email}/teams
List every team a user belongs to, and how.
This differs deliberately from `GET /v2/users/{email_address}/roles`, which
excludes roles reached through an SSO group: a role list that shifted with
login history would make granted access look unstable. This endpoint
describes membership rather than granted access, so it includes SSO-derived
membership — the same login-derived data `last_login_sso_groups` on the user
resource already publishes, with the same caveat that it reflects the user's
most recent login.
# List users
Source: https://api-docs.select.dev/v2-api-reference/users/list-users
https://api.select.dev/v2/openapi.json get /users
# Remove a user from the organization
Source: https://api-docs.select.dev/v2-api-reference/users/remove-a-user-from-the-organization
https://api.select.dev/v2/openapi.json delete /users/{user_id}
Removes the user from the organization and deletes their SELECT login, along with any roles granted to them. This cannot be undone — the user must be invited again to regain access.
# Revoke a role from a user
Source: https://api-docs.select.dev/v2-api-reference/users/revoke-a-role-from-a-user
https://api.select.dev/v2/openapi.json delete /users/{email}/roles/{role_id}
Revoke a role granted to this user directly.
A default or team-inherited role is revoked at its source, not here.
# Set direct role grants for a batch of users
Source: https://api-docs.select.dev/v2-api-reference/users/set-direct-role-grants-for-a-batch-of-users
https://api.select.dev/v2/openapi.json post /users/actions/batch-update-roles
Set the direct role grants for one or more users, by email.
For each listed email, removes all of its current direct role grants, then
grants the roles in this request. Roles inherited from a team, the
organization's default roles, and grants held through an SSO group are
never affected. This is a full replacement, not an incremental add — any
direct grant not present in this request is removed, and an empty role list
clears a user's direct grants entirely.
# Update a role granted to a user
Source: https://api-docs.select.dev/v2-api-reference/users/update-a-role-granted-to-a-user
https://api.select.dev/v2/openapi.json patch /users/{email}/roles/{role_id}
Change the role level of a grant made to this user directly.
Merge-patch: only the fields you send change; omitted fields are left as-is.
The scope cannot be changed — revoke the grant and make a new one instead.
A default or team-inherited role is changed at its source, not here.
# Quickstart guide
Source: https://api-docs.select.dev/v2/introduction
Get started with the SELECT API v2
## Welcome
The v2 API is SELECT's unified, RESTful API. All v2 endpoints are accessed under the base URL `https://api.select.dev/v2`.
v2 is the current SELECT API. The [v1 API](/api-reference/introduction) is
deprecated and will be removed on December 14, 2026.
## Authentication
Every request needs two headers:
| Header | Description |
| - | - |
| `Authorization` | `Bearer ` — create a key in the [SELECT dashboard](https://select.dev/app) under **Settings → API Keys**. The key must have the scopes required by the endpoint. |
| `x-tenant-id` | Your SELECT organization ID (`org_...`). |
```bash theme={null}
curl https://api.select.dev/v2/audit-logs \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "x-tenant-id: org_YOUR_ORG_ID"
```
### Organization ID
The `x-tenant-id` header is your SELECT organization ID (`org_...`). It can be found in the SELECT app by navigating to settings by clicking the gear in the bottom right of the page and viewing your [profile information](https://select.dev/app/settings/profile).
## What changed from v1
* **Organization is a header, not a path parameter.** v1 routes embedded `organization_id` in the path (`/api/{organization_id}/...`). v2 identifies your organization with the `x-tenant-id` header, so paths are clean resource names (`/v2/audit-logs`).
* **Cursor pagination.** List endpoints return a `page_token`; there is no offset/page paging.
* **RFC 9457 problem responses.** Errors use `application/problem+json` with a stable `code` field.
## Pagination
List endpoints return at most `max_results` records (default 50, max 500) plus a `page_token`:
```json theme={null}
{
"items": [ ... ],
"page_token": "eyJmIjoi...",
"row_count": null
}
```
To read the next page, pass the `page_token` back. Keep going until `page_token` is `null` — that means you have reached the end.
```bash theme={null}
curl "https://api.select.dev/v2/audit-logs?max_results=500&page_token=eyJmIjoi..." \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "x-tenant-id: org_YOUR_ORG_ID"
```
`page_token` is the only reliable way to page. Do not build your own cursor from response fields such as timestamps — records can share identical values, and a hand-rolled cursor can silently skip or stall.
## Responses
Standard HTTP status codes indicate success or failure. Errors return `application/problem+json`:
```json theme={null}
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Invalid API key.",
"code": "unauthorized",
"retryable": false
}
```
Use the `code` field for programmatic handling; it is stable across releases.
# Metrics
Source: https://api-docs.select.dev/v2/metrics-overview
Query cost and usage data with the metrics routes
## Overview
The metrics routes give the cost and usage data that the SELECT app shows, for Snowflake, BigQuery, Databricks and Tableau. Each route queries one semantic model:
```
POST https://api.select.dev/v2/metrics//query
```
All metrics routes use the same request body and the same response. When you know how to query one model, you can query all of them. Only the field names change from model to model. The reference page of each route lists its fields, and gives worked examples.
This page uses the `spend` model for all examples. `spend` is the consolidated cost of all your platforms, for all services. Use it first for all questions about cost. Use a platform route (for example `snowflake-workloads` or `bigquery-projects`) to find which resource in the platform caused the cost.
An API key must have the `usage_data:read` scope to use the metrics routes.
## Your first query
This request gets the daily spend for each platform for the last 30 days:
```bash theme={null}
curl https://api.select.dev/v2/metrics/spend/query \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "x-tenant-id: org_YOUR_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"measures": ["sum_spend"],
"dimensions": ["day", "connection_type"],
"filter_expression": {
"operator": "and",
"filters": [{"field": "day", "operator": "in range", "value": "30D"}]
},
"sort": [{"field": "day", "direction": "asc"}],
"limit": 1000
}'
```
The response has one row for each combination of `day` and `connection_type`:
```json theme={null}
{
"items": [
{"day": "2026-09-01", "connection_type": "Snowflake", "sum_spend": 1520.34},
{"day": "2026-09-01", "connection_type": "Bigquery", "sum_spend": 410.02},
{"day": "2026-09-02", "connection_type": "Snowflake", "sum_spend": 1498.77}
],
"page_token": null,
"row_count": 3,
"sql": null
}
```
## Request body
| Field | Meaning |
| - | - |
| `measures` | The values to calculate, for example `sum_spend`. |
| `dimensions` | The fields to group by. |
| `filter_expression` | Filters on dimensions. SELECT applies them before it calculates the measures. |
| `measure_filters` | Filters on measures. SELECT applies them after it calculates the measures. |
| `sort` | The order of the rows. |
| `limit` | The maximum number of rows. |
| `aggregate` | Set to `false` to get rows with no grouping. See [Listing rows](#listing-rows). |
| `return_sql` | Set to `true` to get the SQL that SELECT ran, in the `sql` field of the response. |
## Measures
A measure is a value that SELECT calculates across a group of rows, for example a sum or an average. The name of a measure usually tells you how SELECT calculates it: `sum_spend` is the sum of spend, and `avg_daily_spend` is the average spend per day.
If a request has measures and no dimensions, the response has one row: the total for all rows that match the filters.
```json theme={null}
{
"measures": ["sum_spend"],
"filter_expression": {
"operator": "and",
"filters": [{"field": "day", "operator": "in range", "value": "MTD"}]
}
}
```
Measures that end in `_annualized` are projections, not spend. SELECT extends the spend of the filtered period to one year. For example, with a 7-day range, `sum_spend_annualized` is the spend of that week × 365 / 7. Do not show a projection as the spend of a period.
## Dimensions
A dimension is a field that you group by. The response has one row for each unique combination of the values of the dimensions, and each row contains the value of each dimension. The measures in a row are calculated from only the data in that group.
`dimensions` is equivalent to a SQL `GROUP BY`. More dimensions give more rows, and each row contains less data:
| `dimensions` | Rows in the response |
| - | - |
| `[]` | 1 row: the total. |
| `["connection_type"]` | 1 row for each platform. |
| `["connection_type", "usage_type"]` | 1 row for each service on each platform. |
| `["day", "connection_type"]` | 1 row for each platform on each day. |
A dimension that is not in `dimensions` does not split the rows. For example, `["connection_type"]` with a 30-day filter gives the total of the 30 days for each platform, not a row for each day.
## Time dimensions
To show a trend, add a time dimension to `dimensions`. The time dimension sets the size of each time bucket:
| Dimension | Value in each row |
| - | - |
| `hour` | The start of the hour, as a timestamp with a UTC offset, for example `2026-09-01T14:00:00.000+0000`. |
| `day` | The date, for example `2026-09-01`. |
| `week` | The date of the Monday that starts the week. |
| `month` | The date of the first day of the month. |
| `quarter` | The date of the first day of the quarter. |
| `day_of_week` | The name of the day, for example `Mon`. Use it to compare days of the week. |
All dates and hours are in UTC.
Some rules apply to time buckets:
* **The first and last buckets can be partial.** For example, a `30D` range with `week` usually starts and stops in the middle of a week. The first and last rows then contain less data than the other rows.
* **Filter on `day`, and group by the larger bucket.** To get monthly spend for the year, filter `day` with `YTD` and add `month` to `dimensions`. Do not filter on `week`, `month` or `quarter`.
* **Hour-level data comes from a different table.** SELECT keeps spend in a daily table and in an hourly table. If your request uses `hour`, or another field that only the hourly table has, SELECT reads the hourly table. Otherwise, SELECT reads the daily table, which is faster. The totals are the same. You do not select the table.
## Filters
`filter_expression` limits the rows that SELECT uses to calculate the measures. It is equivalent to a SQL `WHERE`. It is a tree: each node has an `operator` of `and` or `or`, and a list of `filters`. An item in `filters` can be a filter or another node.
This request gets the spend on Snowflake compute or storage for the last 90 days:
```json theme={null}
{
"measures": ["sum_spend"],
"dimensions": ["usage_type"],
"filter_expression": {
"operator": "and",
"filters": [
{"field": "day", "operator": "in range", "value": "90D"},
{"field": "connection_type", "operator": "=", "value": "Snowflake"},
{
"operator": "or",
"filters": [
{"field": "spend_category", "operator": "=", "value": "Compute"},
{"field": "spend_category", "operator": "=", "value": "Storage"}
]
}
]
},
"limit": 1000
}
```
| Operators | Value |
| - | - |
| `=`, `!=`, `>`, `>=`, `<`, `<=` | `value`: one value. |
| `in`, `not in` | `values`: a list. |
| `is`, `is not` | No value. Compares to null. |
| `ilike`, `startswith` | `value` or `values`. `ilike` matches a part of the text and ignores case. |
| `in range`, `not in range` | `value`: a relative date range. |
| `array_contains` | `values`: a list. The array field must contain one of the values. |
### Date ranges
Filter dates on the `day` field. To use fixed dates, use two filters. Both bounds are inclusive:
```json theme={null}
[
{"field": "day", "operator": ">=", "value": "2026-08-01"},
{"field": "day", "operator": "<=", "value": "2026-08-31"}
]
```
To use a range relative to today, use one `in range` filter:
| Value | Range |
| - | - |
| `30D` | The last 30 days, today included. |
| `3M` | The last 3 months, today included. |
| `WTD`, `MTD`, `QTD`, `YTD` | From the start of the current week, month, quarter or year, to today. |
| `LMTD` | All of the previous calendar month. |
Text values are case-sensitive. A value with incorrect case matches no rows, and SELECT does not return an error. For example, on `spend`, `connection_type` is `Snowflake`, `Bigquery` or `Databricks`. The value `snowflake` matches no rows.
## Measure filters
`measure_filters` removes groups after SELECT calculates the measures. It is equivalent to a SQL `HAVING`. Use it to remove small groups from the response.
This request gets the warehouses that cost more than \$1,000 last month:
```json theme={null}
{
"measures": ["sum_spend"],
"dimensions": ["warehouse_name"],
"filter_expression": {
"operator": "and",
"filters": [
{"field": "day", "operator": "in range", "value": "LMTD"},
{"field": "connection_type", "operator": "=", "value": "Snowflake"}
]
},
"measure_filters": [{"field": "sum_spend", "operator": ">", "value": 1000}],
"sort": [{"field": "sum_spend", "direction": "desc"}],
"limit": 1000
}
```
A filter in `filter_expression` changes the value of each measure. A filter in `measure_filters` does not change a value. It only removes rows.
## Usage groups
A usage group set divides your cost into named groups, for example departments or teams. You define usage group sets in the SELECT app, or with the `/v2/usage-group-sets` routes. A model that has a `usage_group` dimension can group or filter by the groups of your sets.
To group by the groups of one set, give the name of the set in `path`:
```json theme={null}
{
"measures": ["sum_spend"],
"dimensions": [{"field": "usage_group", "path": ["Department"]}],
"filter_expression": {
"operator": "and",
"filters": [{"field": "day", "operator": "in range", "value": "MTD"}]
},
"limit": 1000
}
```
* `path[0]` is the name of the set, not its ID.
* A `usage_group` dimension with no `path` groups by all your sets at the same time.
* To get the cost of one group, use the same form in a filter: `{"field": {"field": "usage_group", "path": ["Department"]}, "operator": "=", "value": "Engineering"}`.
* To test a set before you save it, send its definition in `usage_group_sets`. SELECT then uses that definition in place of your saved sets.
## Sort and limit
`sort` is a list of fields and directions. The first item sorts first. You can sort by a dimension or a measure:
```json theme={null}
"sort": [{"field": "day", "direction": "asc"}, {"field": "sum_spend", "direction": "desc"}]
```
`limit` is the maximum number of rows in the response. The metrics routes do not paginate: `page_token` is always `null`. If a query has more rows than `limit`, SELECT removes the rows after the limit, and does not return an error. Always set a `limit`. To get the top N groups, sort by a measure and set `limit` to N.
## Period over period
Some models have measures that compare a period to the period before it: `_previous_period`, `change_` and `percent_change_`. The previous period has the same number of days, and stops on the day before your range starts.
For these measures, the request must have one `day` range at the top level of `filter_expression`. Use one `in range` filter, or one `>=` filter and one `<=` filter.
```json theme={null}
{
"measures": ["sum_spend", "sum_spend_previous_period", "change_sum_spend", "percent_change_sum_spend"],
"dimensions": ["connection_type"],
"filter_expression": {
"operator": "and",
"filters": [{"field": "day", "operator": "in range", "value": "30D"}]
},
"limit": 1000
}
```
For `QTD` on 2026-09-28, the range is 2026-07-01 to 2026-09-28 (90 days). The previous period is the 90 days from 2026-04-02 to 2026-06-30. It is not the previous calendar quarter.
## Listing rows
To get rows with no grouping, set `aggregate` to `false`, and send only `dimensions`. For example, on `snowflake-queries`, this gives the individual queries. If the request also has `measures` or `measure_filters`, SELECT groups the rows, and does not return an error. Always set a `limit` when you list rows.
## Teams
To query as one of your teams, send the `X-Team-Id` header. The response then contains only the data that the roles of the team give access to. This header may not be functional on all routes, reach out to the SELECT team if needed.
# Create actions in a batch
Source: https://api-docs.select.dev/v2-api-reference/actions/create-actions-in-a-batch
https://api.select.dev/v2/openapi.json post /actions/actions/batch-create
Record many actions at once, in request order, or none of them.
Each entry follows the single-create rules, including joining an action
already open for the Automated Savings feature its insight asks to enable.
# Create an action
Source: https://api-docs.select.dev/v2-api-reference/actions/create-an-action
https://api.select.dev/v2/openapi.json post /actions
Record an action, and the savings the change it describes goes on to make.
An action resolving an "enable Automated Savings" insight joins the action
already open for that feature on the same resource, if there is one, rather
than adding a second one measuring the same change. The response is that
action, carrying the insight.
# Delete an action
Source: https://api-docs.select.dev/v2-api-reference/actions/delete-an-action
https://api.select.dev/v2/openapi.json delete /actions/{action_id}
# Get an action
Source: https://api-docs.select.dev/v2-api-reference/actions/get-an-action
https://api.select.dev/v2/openapi.json get /actions/{action_id}
# List actions
Source: https://api-docs.select.dev/v2-api-reference/actions/list-actions
https://api.select.dev/v2/openapi.json get /actions
# Query actions by dimension and measure
Source: https://api-docs.select.dev/v2-api-reference/actions/query-actions-by-dimension-and-measure
https://api.select.dev/v2/openapi.json post /actions/actions/query
# Update an action
Source: https://api-docs.select.dev/v2-api-reference/actions/update-an-action
https://api.select.dev/v2/openapi.json patch /actions/{action_id}
# Add a BigQuery connection
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/add-a-bigquery-connection
https://api.select.dev/v2/openapi.json post /bigquery-connections
Add a BigQuery connection to your organization.
# Add a BigQuery connection, streamed
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/add-a-bigquery-connection-streamed
https://api.select.dev/v2/openapi.json post /bigquery-connections/actions/add-stream
Add a BigQuery connection to your organization, streaming progress as
server-sent events.
# Delete a BigQuery connection
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/delete-a-bigquery-connection
https://api.select.dev/v2/openapi.json delete /bigquery-connections/{bigquery_connection_id}
Delete a BigQuery connection and clean up the external resources it owned.
# Get a BigQuery connection
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/get-a-bigquery-connection
https://api.select.dev/v2/openapi.json get /bigquery-connections/{bigquery_connection_id}
Get a single BigQuery connection by id.
# List BigQuery connections
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/list-bigquery-connections
https://api.select.dev/v2/openapi.json get /bigquery-connections
List the BigQuery connections in your organization, oldest first.
No ETag: a page is not a resource, and the connections it holds each carry
their own.
# Test a BigQuery connection configuration
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/test-a-bigquery-connection-configuration
https://api.select.dev/v2/openapi.json post /bigquery-connections/actions/test
Validate a proposed BigQuery connection configuration without adding it.
# Test an added BigQuery connection
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/test-an-added-bigquery-connection
https://api.select.dev/v2/openapi.json post /bigquery-connections/{bigquery_connection_id}/actions/test
Re-run validation against an already-added BigQuery connection.
Persists newly-detected enrichment and clears alerts only when every
check passes.
# Test an added BigQuery connection, streamed
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/test-an-added-bigquery-connection-streamed
https://api.select.dev/v2/openapi.json post /bigquery-connections/{bigquery_connection_id}/actions/test-stream
Re-run validation against an already-added BigQuery connection,
streaming progress as server-sent events.
Persists newly-detected enrichment and clears alerts only when every
check passes.
# Update a BigQuery connection
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/update-a-bigquery-connection
https://api.select.dev/v2/openapi.json patch /bigquery-connections/{bigquery_connection_id}
Update a BigQuery connection.
Merge-patch: only the fields you send change; omitted fields are left as-is.
# Update a BigQuery connection, streamed
Source: https://api-docs.select.dev/v2-api-reference/bigquery-connections/update-a-bigquery-connection-streamed
https://api.select.dev/v2/openapi.json post /bigquery-connections/{bigquery_connection_id}/actions/update-stream
Update a BigQuery connection, streaming progress as server-sent events.
Merge-patch: only the fields you send change; omitted fields are left as-is.
# Create a budget
Source: https://api-docs.select.dev/v2-api-reference/budgets/create-a-budget
https://api.select.dev/v2/openapi.json post /budgets
Creates a budget. Its `status` is null until the budget has been measured against spend — evaluate it to fill that in without waiting for the daily refresh.
# Delete a budget
Source: https://api-docs.select.dev/v2-api-reference/budgets/delete-a-budget
https://api.select.dev/v2/openapi.json delete /budgets/{budget_id}
Deletes the budget, and with it every monitor watching the budget. Spend already recorded is unaffected.
# Evaluate a budget's spend now
Source: https://api-docs.select.dev/v2-api-reference/budgets/evaluate-a-budgets-spend-now
https://api.select.dev/v2/openapi.json post /budgets/{budget_id}/actions/evaluate
Measures the budget against the warehouse now and stores the result, rather than waiting for the daily refresh, then returns the summary it wrote. The one budget operation that runs a warehouse query, so it is slower than a read and costs warehouse time — call it when a budget has just been created or changed, not to poll. Returns `409` if the budget changed while it was being measured. Requires `budgets:write`.
# Get a budget
Source: https://api-docs.select.dev/v2-api-reference/budgets/get-a-budget
https://api.select.dev/v2/openapi.json get /budgets/{budget_id}
# Get a budget's spend summary
Source: https://api-docs.select.dev/v2-api-reference/budgets/get-a-budgets-spend-summary
https://api.select.dev/v2/openapi.json get /budgets/{budget_id}/spend-summary
`spend` and `forecast` come from the budget's daily refresh, not from a query run for this request, so a page of summaries costs no warehouse time. Only days that have finished loading count, and a day only finishes once, so the figures step forward daily rather than continuously. Both are null on a budget the refresh has not reached yet — evaluate the budget to fill them in without waiting for the next one.
# List budget spend summaries
Source: https://api-docs.select.dev/v2-api-reference/budgets/list-budget-spend-summaries
https://api.select.dev/v2/openapi.json get /budgets/spend-summaries
`spend` and `forecast` come from the budget's daily refresh, not from a query run for this request, so a page of summaries costs no warehouse time. Only days that have finished loading count, and a day only finishes once, so the figures step forward daily rather than continuously. Both are null on a budget the refresh has not reached yet — evaluate the budget to fill them in without waiting for the next one. Ordered and paginated like the budgets list.
# List budgets
Source: https://api-docs.select.dev/v2-api-reference/budgets/list-budgets
https://api.select.dev/v2/openapi.json get /budgets
# Query budgets by dimension and measure
Source: https://api-docs.select.dev/v2-api-reference/budgets/query-budgets-by-dimension-and-measure
https://api.select.dev/v2/openapi.json post /budgets/actions/query
# Update a budget
Source: https://api-docs.select.dev/v2-api-reference/budgets/update-a-budget
https://api.select.dev/v2/openapi.json patch /budgets/{budget_id}
Applies a merge patch: a field the request omits is left unchanged, and an explicit null clears `team_id` or `filter_expression`. Changing `amount`, `period` or `filter_expression` clears the budget's evaluated `status`, `spend` and `forecast` — they measured the old definition — and lets a monitor watching it alert again on thresholds it has already reported. Evaluate the budget to refresh them without waiting for the next daily run.
# Add a block to a dashboard
Source: https://api-docs.select.dev/v2-api-reference/dashboards/add-a-block-to-a-dashboard
https://api.select.dev/v2/openapi.json post /dashboards/{dashboard_id}/blocks
Adds a block to a dashboard. Supply a position to place the block on the dashboard grid in the same request; omit it to add the block unplaced and set the dashboard's layout separately.
# Create a dashboard
Source: https://api-docs.select.dev/v2-api-reference/dashboards/create-a-dashboard
https://api.select.dev/v2/openapi.json post /dashboards
Creates a dashboard, optionally with its initial blocks.
# Create a dashboard digest
Source: https://api-docs.select.dev/v2-api-reference/dashboards/create-a-dashboard-digest
https://api.select.dev/v2/openapi.json post /dashboards/{dashboard_id}/digests
Schedules a new digest on a dashboard — a recurring capture of the dashboard delivered to one or more destinations.
# Delete a block
Source: https://api-docs.select.dev/v2-api-reference/dashboards/delete-a-block
https://api.select.dev/v2/openapi.json delete /dashboards/{dashboard_id}/blocks/{block_id}
Deletes a block and removes its position from the dashboard's layout.
# Delete a dashboard
Source: https://api-docs.select.dev/v2-api-reference/dashboards/delete-a-dashboard
https://api.select.dev/v2/openapi.json delete /dashboards/{dashboard_id}
Deletes a dashboard and removes related home selections, favorites, and scheduled digests.
# Delete a dashboard digest
Source: https://api-docs.select.dev/v2-api-reference/dashboards/delete-a-dashboard-digest
https://api.select.dev/v2/openapi.json delete /dashboards/{dashboard_id}/digests/{digest_id}
# Duplicate a dashboard
Source: https://api-docs.select.dev/v2-api-reference/dashboards/duplicate-a-dashboard
https://api.select.dev/v2/openapi.json post /dashboards/{dashboard_id}/actions/duplicate
Creates a private copy of the dashboard, owned by the caller, with new block ids and a fresh ETag. The source dashboard is unchanged.
# Duplicate a dashboard digest
Source: https://api-docs.select.dev/v2-api-reference/dashboards/duplicate-a-dashboard-digest
https://api.select.dev/v2/openapi.json post /dashboards/{dashboard_id}/digests/{digest_id}/actions/duplicate
Creates a copy of a digest on the same dashboard, named " (Copy)". Run history is not copied.
# Get a block
Source: https://api-docs.select.dev/v2-api-reference/dashboards/get-a-block
https://api.select.dev/v2/openapi.json get /dashboards/{dashboard_id}/blocks/{block_id}
# Get a dashboard
Source: https://api-docs.select.dev/v2-api-reference/dashboards/get-a-dashboard
https://api.select.dev/v2/openapi.json get /dashboards/{dashboard_id}
# Get a dashboard digest
Source: https://api-docs.select.dev/v2-api-reference/dashboards/get-a-dashboard-digest
https://api.select.dev/v2/openapi.json get /dashboards/{dashboard_id}/digests/{digest_id}
# List a dashboard's blocks
Source: https://api-docs.select.dev/v2-api-reference/dashboards/list-a-dashboards-blocks
https://api.select.dev/v2/openapi.json get /dashboards/{dashboard_id}/blocks
Lists the blocks on a dashboard, oldest first.
# List a dashboard's digests
Source: https://api-docs.select.dev/v2-api-reference/dashboards/list-a-dashboards-digests
https://api.select.dev/v2/openapi.json get /dashboards/{dashboard_id}/digests
Lists the scheduled digests configured on a dashboard, newest first.
# List dashboards
Source: https://api-docs.select.dev/v2-api-reference/dashboards/list-dashboards
https://api.select.dev/v2/openapi.json get /dashboards
Lists dashboards in the selected organization, newest first.
# Send a dashboard
Source: https://api-docs.select.dev/v2-api-reference/dashboards/send-a-dashboard
https://api.select.dev/v2/openapi.json post /dashboards/{dashboard_id}/actions/send
Captures a dashboard and delivers it to one or more destinations, independent of any digest's schedule. Completes asynchronously — a 202 response does not confirm delivery.
# Update a block
Source: https://api-docs.select.dev/v2-api-reference/dashboards/update-a-block
https://api.select.dev/v2/openapi.json patch /dashboards/{dashboard_id}/blocks/{block_id}
Applies a merge patch to a block. Omitted fields remain unchanged. `config` is replaced as a whole rather than merged field by field, so send the complete configuration the block should end up with.
# Update a dashboard
Source: https://api-docs.select.dev/v2-api-reference/dashboards/update-a-dashboard
https://api.select.dev/v2/openapi.json patch /dashboards/{dashboard_id}
Applies a merge patch to a dashboard. Omitted fields remain unchanged; an explicit null clears a nullable field. Blocks are managed separately.
# Update a dashboard digest
Source: https://api-docs.select.dev/v2-api-reference/dashboards/update-a-dashboard-digest
https://api.select.dev/v2/openapi.json patch /dashboards/{dashboard_id}/digests/{digest_id}
Applies a merge patch to a digest. Omitted fields remain unchanged; an explicit null clears a nullable field.
# Add a Databricks connection
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/add-a-databricks-connection
https://api.select.dev/v2/openapi.json post /databricks-connections
Add a Databricks connection to your organization.
# Delete a Databricks connection
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/delete-a-databricks-connection
https://api.select.dev/v2/openapi.json delete /databricks-connections/{databricks_connection_id}
Delete a Databricks connection and clean up the external resources it owned.
# Get a Databricks connection
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/get-a-databricks-connection
https://api.select.dev/v2/openapi.json get /databricks-connections/{databricks_connection_id}
Get a single Databricks connection by id.
# Get a Databricks connection's credential configuration
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/get-a-databricks-connections-credential-configuration
https://api.select.dev/v2/openapi.json get /databricks-connections/{databricks_connection_id}/credentials
Get which service principal a connection authenticates as.
# List Databricks connections
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/list-databricks-connections
https://api.select.dev/v2/openapi.json get /databricks-connections
List the Databricks connections in your organization, oldest first.
No ETag: a page is not a resource, and the connections it holds each carry
their own.
# Test a Databricks connection
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/test-a-databricks-connection
https://api.select.dev/v2/openapi.json post /databricks-connections/{databricks_connection_id}/actions/test
Re-run validation against a stored connection's own configuration.
# Test a Databricks connection configuration
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/test-a-databricks-connection-configuration
https://api.select.dev/v2/openapi.json post /databricks-connections/actions/test
Run every check against a proposed configuration, persisting nothing.
# Update a Databricks connection
Source: https://api-docs.select.dev/v2-api-reference/databricks-connections/update-a-databricks-connection
https://api.select.dev/v2/openapi.json patch /databricks-connections/{databricks_connection_id}
Update a Databricks connection.
Merge-patch: only the fields you send change; omitted fields are left as-is.
# List Databricks workspaces
Source: https://api-docs.select.dev/v2-api-reference/databricks-workspaces/list-databricks-workspaces
https://api.select.dev/v2/openapi.json get /databricks-workspaces
List the Databricks workspaces SELECT has seen activity in.
Ordered by identifier. The response does not include a total row count.
# Query BigQuery capacity commitments
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-capacity-commitments
https://api.select.dev/v2/openapi.json post /metrics/bigquery-commitments/query
One row per capacity commitment, each with its own term, rate and end date. Group by `capacity_commitment_id` for the inventory, or filter by `commitment_scope_id` for what one scope holds.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to list BigQuery capacity commitments: one row per purchase of slots, with its plan, size, state and term dates. This route is a snapshot of the commitments now. It has no `day` field, and it has no cost in a period. For what a commitment scope billed, use `bigquery-commitment-scopes` or `bigquery-commitment-scope-days`. For the slots that reservations used, use `bigquery-reservation-timeline`. The route also keeps terminated commitments (`state` `CANCELLED` or `FAILED`). The SELECT app shows them, but to count or total the slots that are held now, filter on `is_in_effect = true`. `annualized_cost` is `slot_count` at today's list rate for the plan over a year. It is a run-rate, and it is not what the commitment bills.
# Query BigQuery capacity commitments by scope
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-capacity-commitments-by-scope
https://api.select.dev/v2/openapi.json post /metrics/bigquery-commitment-scopes/query
One row per commitment scope: an administration project, region and edition, the boundary BigQuery draws around shared slot capacity. Carries both what the scope holds today and what it was billed over the requested range, which a date filter must bound.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to compare commitment scopes: what capacity each scope holds now, and what it billed in a period. A capacity commitment is a purchase of slots for a fixed term. A reservation is a pool of slots that jobs run on. A scope is one administration project, region and edition: a commitment covers only the reservations in its own scope. For a time series, use `bigquery-commitment-scope-days`. For each purchase, use `bigquery-commitments`. For the slots of one reservation, use `bigquery-reservation-timeline`.
Put a `day` range in the top-level `and` node, as two bounds or as `in range`. Without it, the route returns 422. Do not name `day` as a dimension. The range bounds the billed measures: `total_cost` (the dollar cost), `held_cost`, `autoscale_cost` and the `*_slot_s` slot-seconds. It does not bound the holdings (`committed_slots`, `commitment_count`, `baseline_slots`), which show the current state. `annualized_committed_spend` and `annualized_uncommitted_cost` are yearly run-rates, not spend in the period.
# Query BigQuery capacity spend over time
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-capacity-spend-over-time
https://api.select.dev/v2/openapi.json post /metrics/bigquery-commitment-scope-days/query
One row per commitment scope per day, with capacity cost split into the tiers that priced it. Group by a time dimension for a series, or by scope to total a window.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for BigQuery capacity cost over time: one row per commitment scope per day, from billing. A scope is one administration project, region and edition. `total_cost` is the dollar cost. It is the sum of four tiers: `baseline_cost` (baseline slots that the reservation's own jobs used), `borrowed_idle_cost` (idle committed slots that another reservation in the scope borrowed), `buffer_cost` (held slots that no reservation assigned as baseline), and `autoscale_cost` (pay-as-you-go burst). The `*_slot_s` measures are slot-seconds: divide by 3,600 for slot-hours. This route has no holdings such as `committed_slots`. For those, and for one row per scope over a period, use `bigquery-commitment-scopes`. The route has no `hour`: billing is daily.
# Query BigQuery custom workload queries
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-custom-workload-queries
https://api.select.dev/v2/openapi.json post /metrics/bigquery-custom-workload-queries/query
One row per custom workload run or group of runs, carrying cost and runtime alongside the app and workload id your integration supplied.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the BigQuery cost of workloads that you tag yourself. A job is a custom workload when its labels, or a JSON query comment, carry both `app` and `workload_id`. Each source row is one job. A run groups the jobs that carry the same `run_id` key. A job with no `run_id` is a run of its own. For custom workloads on Snowflake, use `snowflake-custom-workloads`. `sum_spend` is the dollar cost of the jobs. It does not include idle reservation capacity. `sum_spend_annualized` is a run-rate, not spend. `runs` counts runs. `number_jobs` counts jobs. `run_duration_ms` is in milliseconds.
# Query BigQuery dbt invocations
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-dbt-invocations
https://api.select.dev/v2/openapi.json post /metrics/bigquery-dbt-invocations/query
One row per dbt invocation or group of invocations, carrying total spend, duration and node counts for each run.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the cost, duration and status of whole dbt commands on BigQuery, such as `dbt build` or `dbt run`. Each source row is one invocation. The route has no node dimensions: for the cost of one model, use `bigquery-dbt-queries`. `sum_spend` is the dollar cost of the invocation's jobs. `num_invocations` counts invocations. `num_nodes` counts the nodes that issued jobs. `sum_duration_ms` is wall-clock time. `sum_total_duration_ms` adds the durations of the jobs, so it is larger than the wall-clock time when jobs run in parallel. An invocation belongs to the `day` it started on. `execution_status` is `SUCCESS` or `FAIL`. One BigQuery job error makes the invocation `FAIL`. A dbt test that finds failing rows does not.
# Query BigQuery dbt queries
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-dbt-queries
https://api.select.dev/v2/openapi.json post /metrics/bigquery-dbt-queries/query
One row per dbt node run or group of runs, carrying warehouse cost and runtime alongside the dbt project, target and node that issued the jobs.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the cost of dbt models, tests, seeds and snapshots on BigQuery, and for the run history of one node. Each source row is one BigQuery job that a dbt node run issued. For the cost and status of whole `dbt` commands, use `bigquery-dbt-invocations`. `sum_spend` is the dollar cost of the jobs. It does not include idle reservation capacity. `sum_spend_annualized` is a run-rate, not spend. `runs` counts node runs (one node in one invocation). `number_jobs` counts BigQuery jobs: one run can issue many jobs. Durations are in milliseconds (`*_ms`), slot time is in seconds (`*_slot_s`), and bytes are bytes.
To rank models, filter `{"field": "dbt_node_resource_type", "operator": "=", "value": "model"}`. The value is lowercase. Without this filter, tests, seeds and snapshots rank with models. The SELECT app's dbt Resources page applies no default filter, and shows every resource type.
# Query BigQuery jobs
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-jobs
https://api.select.dev/v2/openapi.json post /metrics/bigquery-jobs/query
One row per BigQuery job or group of jobs from enriched job history, carrying cost, slot time, bytes and runtime alongside query metadata.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for questions about single BigQuery jobs: the most expensive jobs, the jobs one user ran, or cost by user. A row of the source is one job. `day` is the date of the job's `start_time`. `sum_spend` is the dollar cost of the jobs. A reservation job costs its slot time at the reservation rate. An on-demand job costs its billed bytes. Unused reservation capacity is not in `sum_spend`. For cost that reconciles to the bill, use `bigquery-projects`. For cost grouped by SQL shape, use `bigquery-query-patterns`. The SELECT app's Job History page lists raw jobs from the last 7 days, newest first.
# Query BigQuery Looker queries
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-looker-queries
https://api.select.dev/v2/openapi.json post /metrics/bigquery-looker-queries/query
One row per Looker-driven query or group of queries, carrying cost and runtime alongside the dashboard, look or explore that caused them.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the BigQuery cost of Looker dashboards, looks and explores. Each source row is one BigQuery job that Looker issued. A run is one Looker interaction, such as one dashboard load, and can issue many jobs. For Looker cost on Snowflake, use `snowflake-looker`. `sum_spend` is the dollar cost of the jobs. It does not include idle reservation capacity. `sum_spend_annualized` is a run-rate, not spend. `runs` counts Looker runs. `number_jobs` counts BigQuery jobs. `run_duration_ms` is in milliseconds.
`looker_workload_name` is the dashboard title, else the look title, else the explore name. `looker_resource_type` is `Dashboard`, `Look`, `Explore`, or `Explore - ` for other explore traffic, such as `Explore - SQL Runner` or `Explore - Pre Cache (Dashboard)`. Grouping by `dashboard_title` alone puts all look and explore cost into one null row.
# Query BigQuery projects
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-projects
https://api.select.dev/v2/openapi.json post /metrics/bigquery-projects/query
One row per billing project and pricing tier, carrying attributed cost and usage quantities for the project's share of capacity and on-demand spend.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for BigQuery compute cost by GCP project that reconciles to the bill. A row of the source is one project, region, reservation and pricing tier for one day. `cost` is the dollar cost. It includes committed capacity that no job used, under the `usage_project_id` value `Unused capacity`. The job-level routes (`bigquery-workloads`, `bigquery-jobs`) leave that capacity out. `cost_type` is the pricing tier: `baseline`, `borrowed_idle`, `autoscale` and `buffer` are reservation (editions) capacity, and `on_demand` is priced on billed bytes. `annual_cost` is a run-rate, not spend. This route has no user or usage group dimensions. Storage cost is not in this route.
# Query BigQuery query patterns
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-query-patterns
https://api.select.dev/v2/openapi.json post /metrics/bigquery-query-patterns/query
One row per normalized query pattern, carrying cost, slot time, bytes and execution counts aggregated across the jobs that share the pattern.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to find the BigQuery SQL shapes that cost the most, run the most or scan the most bytes. A pattern is the job SQL with its literals removed. `query_pattern_id` identifies it. The table holds jobs of every workload type, so dbt, Looker and custom jobs also show as patterns. The SELECT app's Query Patterns page applies `workload_type in ["bigquery_query_pattern"]` by default. Without that filter, the result includes jobs that `bigquery-dbt-queries`, `bigquery-looker-queries` and `bigquery-custom-workload-queries` already report. `sum_spend` is the dollar cost of the jobs. `sum_spend_annualized` is a run-rate, not spend.
# Query BigQuery reservation timeline
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-reservation-timeline
https://api.select.dev/v2/openapi.json post /metrics/bigquery-reservation-timeline/query
One row per reservation and time bucket, carrying reserved and consumed slot capacity alongside concurrency signals for the reservation pool.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to see how a BigQuery reservation's slots were configured and used over time, and how long jobs waited to start. A reservation is a pool of slots that jobs run on. Its baseline is always on. Autoscale adds slots on demand. Idle baseline can be lent to, or borrowed from, other reservations in the same commitment scope. The route has no cost measures: for capacity cost, use `bigquery-commitment-scope-days`. For job cost by reservation, use `bigquery-workloads`. The `*_slot_s` measures are slot-seconds (divide by 3,600 for slot-hours). `baseline_slots`, `max_slots` and the `*_slot_hours_per_hour` measures are slot counts: the average number of slots over the hours observed, the same at every grain. Naming `hour` reads the hourly table. All other requests read the daily table.
# Query BigQuery storage
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-storage
https://api.select.dev/v2/openapi.json post /metrics/bigquery-storage-summary/query
One row per group of BigQuery tables, carrying storage size and cost as they stand now. A request that also asks how recently or how often the tables were read joins that activity in, and then requires a bounded range on `day`.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the BigQuery tables as they are now: the largest and costliest tables, datasets and projects, the tables that nobody reads, and the cost of each billing model. Each source row is one table in the latest storage snapshot. The `*_monthly_cost` and `*_annual_cost` fields are run-rates: the current bytes at the current storage rate, in dollars per month or per year. They are not spend in a period, and a `day` range does not bound them. For storage spend in a period, use `bigquery-storage-spend`.
`total_bytes`, `total_monthly_cost` and the `active_*` and `long_term_*` fields follow the dataset's `storage_billing_model` (`LOGICAL` or `PHYSICAL`). The `*_logical_*` and `*_physical_*` fields give one model for every table, whichever model it uses. The fields `day`, `user_name`, `number_queries`, `number_of_users` and `user_names` join the snapshot to query activity. Then the request must have a top-level bounded range on `day`, or it returns 422. Use `day` only as a filter: the joined rows have no date to group by. The SELECT app's Storage page applies `table_type in ["BASE TABLE"]`. Without it, clones and snapshots count at their full base-table size.
# Query BigQuery storage freshness
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-storage-freshness
https://api.select.dev/v2/openapi.json post /metrics/bigquery-storage-freshness/query
One row per table and snapshot day, carrying how stale the table was and how its row count changed since the prior snapshot.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the history of how stale a BigQuery table was, and how its row count changed, day by day. SELECT reads each table once a day from the storage snapshot. A day without a snapshot has no row. `age` is the seconds from the last modification of the table to the snapshot. For a longer bucket, or for many tables, `age` is the largest value, not a sum. `net_rows_changed` is the change in row count from the previous snapshot. It is null on the first snapshot day of a table, and updates that do not add or remove rows do not change it. This route has no cost fields. For the current `last_modified_at` and cost of each table, use `bigquery-storage-summary`.
# Query BigQuery storage spend
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-storage-spend
https://api.select.dev/v2/openapi.json post /metrics/bigquery-storage-spend/query
One row per table and time bucket, carrying storage billing spend split by logical and physical tiers.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for BigQuery storage spend in a period: the trend, and the total by project, dataset or table. For the current size and the monthly run-rate of each table, use `bigquery-storage-summary`. `sum_spend` is the spend in dollars under each dataset's `storage_billing_model`. `sum_spend_annualized` is a run-rate, not spend. SELECT calculates the spend from daily storage snapshots and the region's storage rates. History starts when SELECT first collected storage for the connection. Clone and snapshot tables are not in this route. The fields `hour` and `start_hour_of_day` read hourly rows: each hour holds 1/24 of the day's spend. The `avg_*` fields average across tables, so for a group of tables they give the size of an average table, not the total.
# Query BigQuery workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-bigquery-workloads
https://api.select.dev/v2/openapi.json post /metrics/bigquery-workloads/query
One row per group of BigQuery jobs, carrying cost, slot time, bytes processed and duration alongside the workload that issued them.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to rank BigQuery workloads (query patterns, dbt, Looker and custom workloads) by cost, and to trend their slot time and bytes. Each job has exactly one `workload_type`: `bigquery_query_pattern`, `bigquery_dbt`, `bigquery_looker` or `bigquery_custom`. A workload is `workload_type` plus `identifying_metadata`. `sum_spend` is the dollar cost of the jobs. A reservation job costs its slot time at the reservation rate. An on-demand job costs its billed bytes. Unused reservation capacity is not in `sum_spend`. For cost that reconciles to the bill, use `bigquery-projects`. For single jobs, use `bigquery-jobs`. `sum_spend_annualized` is a run-rate, not spend.
# Query realized action savings
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-realized-action-savings
https://api.select.dev/v2/openapi.json post /metrics/action-realized-savings/query
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Set `return_sql` to see the SQL the rows came from.
Use this route for the dollars that SELECT actions saved, day by day and action by action. A row is one action on one day. `sum_savings` is the realized savings in dollars. `sum_daily_spend` is the spend that remained on the resource after the savings, and is null for event-driven savings such as automated cluster and warehouse scaling. The savings of a new action are provisional while SELECT calibrates it (`is_calibrating = true`), and can change. The SELECT app's Savings pages exclude calibrating rows with `is_calibrating = false`. Only its provisional-savings toggle includes them. For the spend of a resource, use `spend`.
# Query Snowflake automatic clustering
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-automatic-clustering
https://api.select.dev/v2/openapi.json post /metrics/snowflake-automatic-clustering/query
One row per group of Snowflake automatic-clustering workload spend. This model does not publish its SQL.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for Snowflake automatic clustering spend and reclustering volume per table. A row is one table in one hour. `name` is the table name. `sum_spend` is the dollar cost. `sum_bytes` and `sum_rows` are the bytes and rows that Snowflake reclustered. `latest_clustering_key` is the clustering key of the latest hour in the group. The same spend is in `snowflake-serverless` with `resource_type = "automatic_clustering"`, and in `spend` with `usage_type = "Automatic Clustering"`. Use those routes to compare clustering with the other serverless features. This route has no period-over-period measures. To compare two periods, send one request for each period.
# Query Snowflake custom workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-custom-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-custom-workloads/query
One row per group of Snowflake queries attributed to custom workloads.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of custom workloads. A custom workload is a unit of work that you label yourself: put a JSON object in the query tag or in a query comment. The object must have non-empty `app` and `workload_id` keys. It can also have `run_id`, `environment`, `team`, `tenant_id` and any other keys. SELECT keeps the whole object in `workload_metadata`. A row is one group of the tagged queries. `app` and `custom_workload_id` identify a workload. `run_id` is the `run_id` key, else the query ID. `runs` counts distinct runs that used a warehouse. To group by any other key, use a `path` dimension: `{"field": "workload_metadata", "path": [""]}`. The `workload-metadata-suggestions` route lists the keys in use (`key_type = "custom_workload"`). `sum_spend` is the dollar cost. `sum_spend_annualized` is a run-rate, not spend.
# Query Snowflake dbt invocations
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-dbt-invocations
https://api.select.dev/v2/openapi.json post /metrics/snowflake-dbt-invocations/query
One row per group of dbt invocations and their run-level cost.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the cost, duration and status of whole dbt invocations, for example one `dbt build` or one dbt Cloud job run. A row is one group of invocations. The table has one record for each invocation, dated by the start time of its first query. All the cost of an invocation goes on that day. The cost includes every node in the invocation: models, tests, seeds, snapshots and hooks. This route has no per-model dimension. For cost per model or test, use `snowflake-dbt`. `sum_spend` is the dollar cost of the invocations. `avg_sum_spend` is the average cost of one invocation.
# Query Snowflake dbt workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-dbt-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-dbt/query
One row per group of Snowflake queries attributed to dbt node runs. Nodes are models, tests, snapshots and seeds, so a request that wants models alone must filter on the node's resource type.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost and run time of dbt models, tests, seeds and snapshots. A row is one group of Snowflake queries that dbt nodes sent. Every node type is in the table. For models alone, filter `dbt_node_resource_type = "model"`. The values are lowercase: `model`, `test`, `seed`, `snapshot`. If your organization sets default dbt targets, the SELECT app's dbt pages also filter `dbt_target_name` to those targets. `sum_spend` is the dollar cost. `sum_spend_annualized` is a run-rate, not spend. For the cost of a whole `dbt run` or `dbt build`, use `snowflake-dbt-invocations`. That route has no per-node dimension.
# Query Snowflake dynamic tables
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-dynamic-tables
https://api.select.dev/v2/openapi.json post /metrics/snowflake-dynamic-tables/query
One row per group of Snowflake dynamic-table refresh queries. This model does not publish its SQL.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of dynamic-table refreshes. A row is one group of refresh queries. `database_name`, `schema_name` and `name` identify a dynamic table. `dynamic_table_identifier` is its fully qualified name. `executions` counts refresh queries. `executions_on_warehouse` counts only the refreshes that ran on a warehouse. A refresh with no new upstream data runs only on cloud services. `sum_spend` is the dollar cost. `sum_compute_cost` (warehouse) and `sum_cloud_services_cost` are parts of it. `sum_spend_annualized` is a run-rate, not spend. For all Snowflake workload types together, use `snowflake-workloads` with `resource_type in ["dynamic_table"]`.
# Query Snowflake Fivetran workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-fivetran-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-fivetran/query
One row per group of Snowflake queries attributed to Fivetran.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of Fivetran loads, by destination table, schema or database. A row is one group of Snowflake queries that Fivetran ran. Each query has one destination table: `destination_database_name`, `destination_schema_name` and `destination_table_name`. This route has no sync or run grain: `runs` and `executions` both count queries, and `avg_run_duration_s` is the average elapsed time of one query. `sum_spend` is the dollar cost. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend. For all Snowflake workload types together, use `snowflake-workloads`.
# Query Snowflake Hex workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-hex-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-hex/query
One row per group of Snowflake queries attributed to Hex.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of Hex projects, their run history and their users. A row is one group of Snowflake queries that Hex sent. The name of a workload is `hex__project_name`. `hex__project_id` identifies one project: project names are not unique. `hex__context_nice` tells how the project ran: `Schedule`, `App View` or `Logic View`. The raw `hex__context` values are uppercase (`SCHEDULED_RUN`, `APP_VIEW`, `LOGIC_VIEW`). `runs` counts Hex project runs, not queries. `sum_spend` is the dollar cost. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend. For all Snowflake workload types together, use `snowflake-workloads`.
# Query Snowflake Looker workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-looker-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-looker/query
One row per group of Snowflake queries attributed to Looker.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of Looker dashboards, looks and explores, their run history and their users. A row is one group of Snowflake queries that Looker sent. The name of a workload is `looker_workload_name`: the dashboard title, else the look title, else the explore name. `looker_resource_type` tells which of these a row is: `Dashboard`, `Look`, `Explore`, or `Explore - ` for explore queries from other sources, for example `Explore - SQL Runner`. `dashboard_title` is null for every look and explore query. `runs` counts Looker runs: queries from one user action on one dashboard, look or explore. `sum_spend` is the dollar cost. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend. For all Snowflake workload types together, use `snowflake-workloads`.
# Query Snowflake Mode workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-mode-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-mode/query
One row per group of Snowflake queries attributed to Mode.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of Mode reports, their run history and their users. A row is one group of Snowflake queries that Mode sent. The name of a workload is `mode__report_name`, and `mode__collection_name` is the collection that holds the report. `mode__report_token` identifies one report. Report names repeat across collections. A report with no name in Mode has the name `Unknown`. This route includes only the reports that SELECT reads from the Mode API. Queries from other Mode reports are in `snowflake-query-patterns`. `mode__run_reason` is `Scheduled` or `Manual Run`. `runs` counts Mode report runs, not queries. `sum_spend` is the dollar cost. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend. For all Snowflake workload types together, use `snowflake-workloads`.
# Query Snowflake Periscope workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-periscope-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-periscope/query
One row per group of Snowflake queries attributed to Periscope.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of Periscope dashboards and charts, and of their users. A row is one group of Snowflake queries that Periscope sent. The name of a workload is `periscope__dashboard_id`. Periscope does not send the dashboard title, so this route has no dashboard name. `periscope__chart_name` is the chart in the dashboard. `periscope__query_source_nice` tells why the query ran, for example `Background Chart Refresh`, `User Pageload` or `Shared Dashboard`. The raw `periscope__query_source` values are lowercase with underscores (`background_chart_refresh`). SELECT does not group Periscope queries into runs: `runs` counts queries. `sum_spend` is the dollar cost. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend. For all Snowflake workload types together, use `snowflake-workloads`.
# Query Snowflake pipeline nodes
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-pipeline-nodes
https://api.select.dev/v2/openapi.json post /metrics/snowflake-pipeline-nodes/query
One row per group of nodes in Snowflake workload pipelines. Edges between nodes are not queryable on this endpoint.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the workloads in the pipelines that SELECT flags as unused or overscheduled. A pipeline is a chain of workloads that write and read the same tables. A row is one group of nodes. A node is one workload in one pipeline. `component_id` identifies a pipeline. It is the `component_id` of the matching `unused_pipeline` or `overscheduled_pipeline` insight. `type` is `unused` or `overscheduled`. One workload can be in both, so always filter on `type`. `role` is `writer` or `reader`. Only overscheduled pipelines have readers. This route is a snapshot. It has no date field and does not accept a date filter. `sum_workload_cost` is the dollar cost of the last 14 complete days. It is not annualized. `sum_executions` is null for `unused` nodes.
# Query Snowflake queries
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-queries
https://api.select.dev/v2/openapi.json post /metrics/snowflake-queries/query
One row per group of individual Snowflake queries enriched with workload context. This model does not publish its SQL.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for individual Snowflake queries: the slowest or most expensive queries, the queries that read or wrote a table, and the queries of one user, warehouse or workload. One source row is one query. To list queries, set `aggregate: false` and name no `measures`. The per-query fields are dimensions: `query_cost` is dollars, and `execution_time_s` and `total_elapsed_time_s` are seconds. A request that names a measure aggregates, even with `aggregate: false`. `resource_type` tells which workload sent the query, with the same values as on `snowflake-workloads`.
This route scans the query history, and a wide scan can time out. Always set a short `day` range and a `limit`. The SELECT app's Query History page shows the last 7 days and applies `warehouse_size not in ["Cloud Services"]`. This filter removes the queries that used no warehouse, such as metadata and result-cache queries. For totals over long periods, use `snowflake-query-patterns` or `snowflake-workloads`.
# Query Snowflake query patterns
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-query-patterns
https://api.select.dev/v2/openapi.json post /metrics/snowflake-query-patterns/query
One row per group of Snowflake query-pattern workload activity. Activity is grouped to the hour for a request that asks about hours, and to the day otherwise.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to find the repeated SQL statements (query patterns) that cost the most, run the slowest, fail the most or grow the fastest. A query pattern is one normalized statement, named by `query_pattern_id` and `query_type`. The table holds the queries of every workload type, and `resource_type` tells which. The SELECT app's Query Patterns page applies `resource_type in ["query_pattern"]`. This filter keeps only the queries that no other workload (dbt, tasks, BI tools and so on) claims. Without it, the queries of dbt models, tasks and BI tools rank too.
`sum_spend` is the cost in dollars. `sum_spend_annualized` is a run-rate, not spend in the period. `executions` counts queries. For individual queries, use `snowflake-queries`. To compare query patterns with other workload types, use `snowflake-workloads`. A request that names `hour`, `start_hour_of_day` or `start_hours_of_day` reads the hourly table. `first_run_time` is available only on the daily table.
# Query Snowflake serverless spend
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-serverless-spend
https://api.select.dev/v2/openapi.json post /metrics/snowflake-serverless/query
One row per group of Snowflake serverless spend over a period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for spend on the Snowflake serverless features that attach to an object: Snowpipe, Snowpipe Streaming, automatic clustering and search optimization. A row is one object in one hour. `resource_type` tells the four features apart (`snowpipe`, `snowpipe_streaming`, `automatic_clustering`, `search_optimization`). `nice_resource_type` gives the same labels that the `spend` route uses as `usage_type` values: `Snowpipe`, `Snowpipe Streaming`, `Automatic Clustering` and `Search Optimization`. This route does not include the other serverless services, for example `Serverless Tasks` or `AI Services`. For serverless task spend, use `snowflake-tasks`. For clustering bytes and rows, or Snowpipe files and bytes, use `snowflake-automatic-clustering` or `snowflake-snowpipe`. `sum_spend` is the dollar cost. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend.
# Query Snowflake Sigma workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-sigma-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-sigma/query
One row per group of Snowflake queries attributed to Sigma.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost of Sigma workbooks, dashboards, datasets and ad hoc queries, and of their users. A row is one group of Snowflake queries that Sigma sent. SELECT finds these queries from the Sigma query comment or the Sigma query tag. The name of a workload is `sigma__display_name`: the document name for a query from a Sigma document, else the query kind. The type of a workload is `sigma__display_type`: the document type, else the query kind. `sigma__type` is the document type, for example `Workbook`, `Dashboard`, `Dataset` or `Data Model`. It is null for queries without a document. For these queries, `sigma__kind` tells the source, for example `SQL Runner`, `Adhoc`, `Export` or `Screenshot`. When Sigma does not send a kind, `sigma__kind` is `Scheduler` when the Sigma scheduler sent the query, else `Metadata`. `sigma__name` comes from the document URL, so it is not unique. `sigma__url` identifies one document. SELECT does not group Sigma queries into runs: `runs` counts queries. `sum_spend` is the dollar cost. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend. For all Snowflake workload types together, use `snowflake-workloads`.
# Query Snowflake Snowpipe spend
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-snowpipe-spend
https://api.select.dev/v2/openapi.json post /metrics/snowflake-snowpipe/query
One row per group of Snowflake Snowpipe ingest spend. This model does not publish its SQL.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for Snowpipe spend and load volume per pipe. A row is one pipe in one hour. `sum_spend` is the dollar cost and `sum_credits` is the credits. `sum_files` and `sum_bytes` are the files and bytes that the pipe loaded. `sum_bytes_billed` is the bytes that Snowflake billed. External table auto-refresh is billed as Snowpipe: those rows have `name = "External table refreshes"`. This route does not include Snowpipe Streaming. For Snowpipe Streaming, use `snowflake-serverless` with `resource_type = "snowpipe_streaming"`. This route has no account dimensions, so pipes with the same database, schema and name in different accounts merge into one row. To split by account, use `snowflake-serverless` with `resource_type = "snowpipe"`. This route has no period-over-period measures.
# Query Snowflake storage spend
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-storage-spend
https://api.select.dev/v2/openapi.json post /metrics/snowflake-storage/query
One row per group of Snowflake storage spend. Activity is grouped to the hour for a request that asks about hours, and to the day otherwise.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for Snowflake storage spend in a period: storage cost by database, by account, by storage type, or over time. `sum_spend` is the dollar cost in the date range. For the current size and run-rate of each table, use `snowflake-storage-summary`. That route is a snapshot, and a `day` range does not bound its cost. Stage storage is not in this route. Thus the Storage total of the `spend` route can be higher. `storage_type` values are `Table and Time Travel`, `Failsafe`, `Retained for Clones` and `Failsafe Retained for Clones`. The two clone types have no database, so `database_name` is null on those rows. Snowflake bills storage by the day. An hourly row is an even share of that day.
# Query Snowflake storage summary
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-storage-summary
https://api.select.dev/v2/openapi.json post /metrics/snowflake-storage-summary/query
One row per group of Snowflake tables and their storage footprint, optionally joined to how those tables were read. A snapshot without read activity needs no date range; naming read-activity fields requires a bounded range on `day`, and `sql` is null when the workloads join is used.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the tables as they are now: the largest and costliest tables, the tables that nobody reads, and the time travel, failsafe and clone share of the bytes. Each source row is one table in the latest storage snapshot. A deleted table stays while it holds billable bytes; filter `is_deleted` to `false` to remove it. The `*_monthly_cost` and `*_annual_cost` fields are run-rates: the current billable bytes at the current storage rate. They are not spend in a period, and a `day` range does not bound them. For storage spend in a period, use `snowflake-storage`. The fields `day`, `user_name`, `user_names`, `number_of_users` and all `read_*` and `dml_*` fields join the snapshot to table access activity. Then the request must have a bounded range on `day` at the top level of `filter_expression`, or it returns 422. That range bounds only the access fields. The SELECT app's Storage page sorts by `total_annual_cost`, descending.
# Query Snowflake stored procedures
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-stored-procedures
https://api.select.dev/v2/openapi.json post /metrics/snowflake-stored-procedures/query
One row per group of Snowflake stored-procedure workload queries.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost, run count and run time of stored procedures. A row is one group of queries that ran inside a stored procedure call. A nested call is attributed to the outermost procedure. The table also holds procedure queries that SELECT attributes to another workload. A procedure that a task calls is attributed to the task, and its cost shows in `snowflake-tasks`. The SELECT app's Stored Procedures page filters `resource_type in ["stored_procedure"]`. Without that filter, the totals overlap with the other workload routes. `database_name`, `schema_name` and `name` identify the procedure. `sum_spend` is the dollar cost. `sum_spend_annualized` is a run-rate, not spend.
# Query Snowflake tasks
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-tasks
https://api.select.dev/v2/openapi.json post /metrics/snowflake-tasks/query
One row per group of Snowflake task workload queries.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost, run count and run time of tasks. A row is one group of queries that ran as part of a task run, including queries of the stored procedures that a task calls. The table also holds task queries that SELECT attributes to another workload, for example dbt. The SELECT app's Tasks page filters `resource_type in ["task"]`. Without that filter, the totals overlap with `snowflake-dbt` and the other workload routes. `database_name`, `schema_name` and `name` identify the task, not the objects that its queries read. `sum_spend` is the dollar cost. `sum_spend_annualized` is a run-rate, not spend.
# Query Snowflake warehouse clusters
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-warehouse-clusters
https://api.select.dev/v2/openapi.json post /metrics/snowflake-warehouse-clusters/query
One row per group of Snowflake warehouse cluster utilization and spend. This model does not publish its SQL.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for each cluster of a multi-cluster Snowflake warehouse: the spend, idle spend, utilization and query concurrency of each `cluster_number`. A row is one cluster of one warehouse for one hour. `spend` is dollars: the metering spend of the warehouse, split across its clusters by the time that each cluster ran. For the whole warehouse, use `snowflake-warehouses`. That route also has `avg_running_clusters` and `max_running_clusters`. For queueing and query latency, use `snowflake-warehouse-query-performance`. `cluster_utilization_percent` is 0 to 100: the time the cluster processed queries, divided by the time it ran. `avg_num_running_queries` is the average number of queries that ran at the same time on the cluster while it ran.
# Query Snowflake warehouse query performance
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-warehouse-query-performance
https://api.select.dev/v2/openapi.json post /metrics/snowflake-warehouse-query-performance/query
One row per group of per-query warehouse performance statistics — executions, latency percentiles, bytes scanned and spillage.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the query performance of Snowflake warehouses: query counts, failures, latency, queueing, bytes scanned and spilling. A row is the queries of one warehouse, user and execution status that started in one hour. This route has no dollar measure. For warehouse spend and utilization, use `snowflake-warehouses`. For each cluster, use `snowflake-warehouse-clusters`. For individual queries, use `snowflake-queries`. Times are in seconds and data sizes are in bytes. `avg_*` is the average for each query. The percentiles are approximate. They are not available for `compilation_time_s`, `queued_provisioning_time_s`, `bytes_scanned`, `bytes_scanned_from_cache`, `partitions_total` and `query_acceleration_partitions_scanned`. The SELECT app's warehouse Performance tab applies `ran_on_warehouse = true`. This filter removes the queries that ran only in cloud services, such as result cache hits. Without it, those queries add near-zero times and make the averages lower.
# Query Snowflake warehouses
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-warehouses
https://api.select.dev/v2/openapi.json post /metrics/snowflake-warehouses/query
One row per group of Snowflake warehouse utilization, spend and savings. Activity is grouped to the hour for a request that asks about hours, and to the day otherwise. `sql` in the response is populated for requests that read the hourly table and is null for requests that read the daily table.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the utilization, idle spend and automated savings of each Snowflake warehouse. A row is one warehouse for one day, or for one hour. `spend` is dollars: the metering spend of the warehouse for compute, cloud services after the daily adjustment, and query acceleration, including idle time. The `sum_spend` measure of `snowflake-workloads` is the cost that SELECT gives to each query, so its total is slightly different. The SELECT app's Warehouses page ranks warehouses by cost with `snowflake-workloads`, and gets utilization and savings from this route. For each cluster, use `snowflake-warehouse-clusters`. For query latency, queueing and spilling, use `snowflake-warehouse-query-performance`. `utilization_efficiency_percent` is 0 to 100. The `*_annualized` measures are run-rates, not spend.
# Query Snowflake workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-snowflake-workloads
https://api.select.dev/v2/openapi.json post /metrics/snowflake-workloads/query
One row per group of Snowflake workload activity — the named units of work that run on a warehouse, such as dbt models, query patterns, tasks, stored procedures and BI-tool queries. Measures cover cost, credits, runtime, queueing and row throughput. Activity is grouped to the hour it ran in for a request that asks about hours, and to the day otherwise.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to compare spend across every kind of Snowflake workload in one table: warehouse spend, the top workloads of any type, and spend by workload type. The table holds all attributed Snowflake spend, including storage, serverless features, AI services and idle warehouse time. `sum_spend` is the cost in dollars. `sum_spend_annualized` is a run-rate, not spend in the period. `resource_type` names the workload type. Its values are lowercase keys (`query_pattern`, `dbt`, `task`, `stored_procedure`, `dynamic_table`, `looker`, `mode`, `hex`, `periscope`, `sigma`, `fivetran`, `custom`, `snowpipe`, `snowpipe_streaming`, `automatic_clustering`, `search_optimization`, `storage`, `idle_warehouse`) and Title Case AI names (`Cortex Analyst`, `Cortex Agent`, `Snowflake Intelligence`, and others). The SELECT app's All Workloads page applies `resource_type != "storage"`.
For the fields of one workload type, use its route: `snowflake-dbt`, `snowflake-tasks`, `snowflake-stored-procedures`, `snowflake-dynamic-tables`, `snowflake-looker`, `snowflake-mode`, `snowflake-hex`, `snowflake-sigma`, `snowflake-periscope`, `snowflake-fivetran`, `snowflake-custom-workloads`, `snowflake-serverless` or `snowflake-storage`. For per-query detail, use `snowflake-query-patterns` or `snowflake-queries`. A request that names `hour`, `start_hour`, `start_hour_of_day`, `start_hours_of_day`, `workload_type` or a table-footprint measure (`count_distinct_*`, `*_first_25`) reads the hourly table. All other requests read the daily table.
# Query Tableau data sources
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-tableau-data-sources
https://api.select.dev/v2/openapi.json post /metrics/tableau-data-sources/query
One row per group of Tableau data sources, carrying whether each is certified, whether it materializes an extract, and the workbooks connected to it.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for an inventory of published Tableau data sources: which are certified, which are extracts, and which no workbook uses or views. A row is one data source as it is now. The route has no `day` field and takes no date filter. It carries no activity or cost. `workbooks_connected` lists the workbooks that use the data source, without deleted workbooks. `workbooks_max_last_viewed_date` is the latest view of any of those workbooks. It is null when no connected workbook has a recorded view. View dates come from Tableau Admin Insights, which only Tableau Cloud supplies. For the workbooks themselves, use `tableau-workbooks`. Data sources removed from Tableau stay in the table, and the route has no field to exclude them.
# Query Tableau users
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-tableau-users
https://api.select.dev/v2/openapi.json post /metrics/tableau-users/query
One row per group of Tableau users, carrying the site role each holds and the projects, workbooks and data sources they own. A user is described as they stand now rather than over a period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for an inventory of Tableau users: license mix by site role, owners of content, and users who do not log in. A row is one user as they are now. The route has no `day` field and takes no date filter. It carries no activity or cost. For who viewed what, use `tableau-view-events`. For the warehouse cost that a user's dashboards caused, use `tableau-queries` and group by `tableau__user_luid`. `count_creators`, `count_explorers` and `count_viewers` match a substring of `site_role`, so `SiteAdministratorCreator` counts as a creator and `ExplorerCanPublish` counts as an explorer. Users removed from Tableau stay in the table, and the route has no field to exclude them.
# Query Tableau view events
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-tableau-view-events
https://api.select.dev/v2/openapi.json post /metrics/tableau-view-events/query
One row per group of Tableau view events — one event each time a user opened a view. This is the activity behind the view counts the workbooks model reports, so it is where a trend over time or a breakdown by viewer comes from.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for Tableau view activity over a period of your choice: the most-viewed workbooks, view trends, and who views a workbook. A row is one view: a user opened a view (a sheet or dashboard) in a workbook. The route holds only `Access View` events, so `event_name` has one value. `total_views` counts views and `unique_users` counts distinct viewers. The route carries no cost. For warehouse cost, use `tableau-queries`. For a rolling 30-day view count with workbook names, use `tableau-workbooks`. This route has no workbook name: `workbook_id` is the workbook LUID, which is the `id` on `tableau-workbooks`. Events come from Tableau Admin Insights, which only Tableau Cloud supplies. On Tableau Server, the route returns no rows.
# Query Tableau workbooks
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-tableau-workbooks
https://api.select.dev/v2/openapi.json post /metrics/tableau-workbooks/query
One row per group of Tableau workbooks, carrying view counts and the queries each workbook issued against the connected warehouse.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for an inventory of Tableau workbooks: how many exist, who owns them, and which ones nobody opens. A row is one workbook as it is now. The route has no `day` field and takes no date filter. `view_count_last_30_days`, `viewers_count_last_30_days` and `query_cost_last_30d` are dimensions that always cover the 30 days before today. A request date does not change them. `query_cost_last_30d` is the dollar cost of the Snowflake queries that the workbook issued. For views over a period of your choice, use `tableau-view-events`. For warehouse cost over a period of your choice, use `tableau-queries`. View counts come from Tableau Admin Insights, which only Tableau Cloud supplies. On Tableau Server, the counts are 0 and `last_viewed_date` is null. Deleted workbooks stay in the table with `is_deleted = true`. The SELECT app does not filter them out by default.
# Query the warehouse queries Tableau issued
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-the-warehouse-queries-tableau-issued
https://api.select.dev/v2/openapi.json post /metrics/tableau-queries/query
One row per group of warehouse queries issued by Tableau, carrying the cost, runtime and row throughput of the work alongside the Tableau site, workbook, worksheet and user behind it. This is what attributes warehouse spend to the Tableau content that caused it.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Snowflake cost that Tableau caused: the costliest workbooks, the cost trend of one workbook, and the warehouses and users behind it. This is the only Tableau route with cost over a period of your choice. A row is one Snowflake query that carries a Tableau query tag. The tag gives `tableau__site_luid`, `tableau__workbook_luid`, `tableau__worksheet_luid` and `tableau__user_luid`. The route holds only Snowflake queries. It has no workbook or user names: `tableau__workbook_luid` is the `id` on `tableau-workbooks`, and `tableau__user_luid` is the `id` on `tableau-users`. `sum_spend` is the dollar cost of the queries. It does not include idle warehouse time. `sum_spend_annualized` and `change_sum_spend_annualized` are run-rates, not spend. For view counts, use `tableau-view-events`.
# Resolve a resource to its canonical SRN
Source: https://api-docs.select.dev/v2-api-reference/srn/resolve-a-resource-to-its-canonical-srn
https://api.select.dev/v2/openapi.json post /srn/actions/resolve
# Test a Tableau connection
Source: https://api-docs.select.dev/v2-api-reference/tableau-connections/test-a-tableau-connection
https://api.select.dev/v2/openapi.json post /tableau-connections/{tableau_connection_id}/actions/test
Re-run validation against an already-added Tableau connection.
Clears the connection's connectivity/configuration alerts when the run
passes.
# Delete an alert integration
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/delete-an-alert-integration
https://api.select.dev/v2/openapi.json delete /alert-integrations/{alert_integration_id}
Delete an alert integration and the credentials SELECT holds for it.
An integration that still has destinations cannot be deleted: the request
fails with `409` and code `delete_blocked_by_dependencies`, and nothing
changes. Delete its destinations first. Deleting never removes a
destination, so no monitor, dashboard digest or anomaly alert loses a
destination as a side effect.
# Enable email alerts
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/enable-email-alerts
https://api.select.dev/v2/openapi.json post /alert-integrations/actions/enable-email
Enable sending alerts by email, and get the email alert integration.
An organization has one email integration, which every email alert
destination belongs to. Enabling it again returns the existing one
unchanged, so the call is safe to repeat.
# Enable Microsoft Teams webhook alerts
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/enable-microsoft-teams-webhook-alerts
https://api.select.dev/v2/openapi.json post /alert-integrations/actions/enable-ms-teams-webhook
Enable posting alerts to Microsoft Teams, and get the webhook integration.
An organization has one MS Teams webhook integration, which every MS Teams
alert destination belongs to; each destination brings its own webhook
URL. Enabling it again returns the existing one unchanged, so the call is
safe to repeat.
# Get an alert integration
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/get-an-alert-integration
https://api.select.dev/v2/openapi.json get /alert-integrations/{alert_integration_id}
Get a single alert integration by id.
# List a Slack workspace's channels
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/list-a-slack-workspaces-channels
https://api.select.dev/v2/openapi.json get /alert-integrations/{alert_integration_id}/slack-channels
List the public, unarchived channels of a connected Slack workspace.
Read live from Slack. Slack may return fewer than `max_results` channels
on a page even when more follow; keep following `page_token` until it is
absent. `row_count` is not reported. A workspace whose credentials Slack
refuses is marked `failing` and answered with `409` and code
`integration_credentials_rejected`; reconnect it to continue.
# List alert integrations
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/list-alert-integrations
https://api.select.dev/v2/openapi.json get /alert-integrations
List your organization's alert integrations, oldest first.
Includes integrations whose connection is still being set up, which have
status `pending`.
# Reinstall a Slack integration
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/reinstall-a-slack-integration
https://api.select.dev/v2/openapi.json post /alert-integrations/{alert_integration_id}/actions/reinstall-slack
Re-authorize a Slack integration's workspace and get the Slack consent URL.
Use this when the SELECT app was removed from the workspace or its access
needs renewing. The integration's status becomes `pending` until someone
approves access at the returned URL, and the same integration, with its
destinations, is kept rather than a new one created. The person approving
must choose the workspace the integration is already connected to.
Calling it again returns the same URL and leaves the status as it is, so
the call is safe to repeat.
# Start connecting a Slack workspace through OAuth
Source: https://api-docs.select.dev/v2-api-reference/alert-integrations/start-connecting-a-slack-workspace-through-oauth
https://api.select.dev/v2/openapi.json post /alert-integrations/actions/start-slack-oauth
Begin a browser-based OAuth connect and get the Slack consent URL.
Open the returned URL in the browser of the person granting access. The
workspace they approve is connected as a Slack alert integration.
# Create a destination
Source: https://api-docs.select.dev/v2-api-reference/destinations/create-a-destination
https://api.select.dev/v2/openapi.json post /destinations
Create a destination under one of your organization's alert integrations.
Set `integration_type` to the kind of destination and `integration_id` to
an alert integration of the same type. A new destination has status
`unknown` until it first delivers an alert.
# Create destinations in a batch
Source: https://api-docs.select.dev/v2-api-reference/destinations/create-destinations-in-a-batch
https://api.select.dev/v2/openapi.json post /destinations/actions/batch-create
Create many destinations at once, in request order, or none of them.
Each entry follows the rules for creating a single destination, and
entries may be of different types and use different alert integrations.
As with a single create, nothing stops two entries from naming the same
address or channel; each becomes its own destination. If any entry is
rejected, nothing is created: the error carries the entry's position in
`details`, as `body.items.`. Every new destination has status
`unknown` until it first delivers an alert.
# Delete a destination
Source: https://api-docs.select.dev/v2-api-reference/destinations/delete-a-destination
https://api.select.dev/v2/openapi.json delete /destinations/{destination_id}
Delete a destination.
A destination that a monitor or dashboard digest still sends to cannot be
deleted: the request fails with `409` and code
`delete_blocked_by_dependencies`, and nothing changes. Remove it from
those monitors and digests first.
# Delete destinations in a batch
Source: https://api-docs.select.dev/v2-api-reference/destinations/delete-destinations-in-a-batch
https://api.select.dev/v2/openapi.json post /destinations/actions/batch-delete
Delete many destinations at once, or none of them.
Each entry carries the destination's `id` and its current `etag`, which
plays the part of `If-Match` on a single delete: a destination changed
since you read it fails the whole batch with `412`. A destination that a
monitor or dashboard digest still sends to is refused with `409` and code
`delete_blocked_by_dependencies`, never skipped, so remove it from them
first or leave it out of the batch. Destinations are not deleted in part:
if any entry is rejected, nothing is deleted, and the error carries the
entry's position in `details`, as `body.items.`.
Every entry is checked for existence (`404`), then your permission to
change it (`403`), then its `etag` (`412`), then use by a monitor or digest
(`409`), and the first failing entry of the earliest failing check is the
one reported. The deleted destinations are returned as they were, in
request order.
# Get a destination
Source: https://api-docs.select.dev/v2-api-reference/destinations/get-a-destination
https://api.select.dev/v2/openapi.json get /destinations/{destination_id}
Get a single destination by id.
# List destinations
Source: https://api-docs.select.dev/v2-api-reference/destinations/list-destinations
https://api.select.dev/v2/openapi.json get /destinations
List your organization's destinations, oldest first.
Each item's `integration_type` says which kind of destination it is and
which settings it carries.
# Test a destination
Source: https://api-docs.select.dev/v2-api-reference/destinations/test-a-destination
https://api.select.dev/v2/openapi.json post /destinations/{destination_id}/actions/test
Send a test message to a destination.
Each call sends a message. The response is `200` whether or not the
message was delivered: check `success`, and read `error_message` when it
is false. The destination's
`status` becomes `connected` after a delivered message, or `failing` with
the reason in `error_message` after a failed one, and its `last_used_time`
is updated. Its configuration is not changed, so no `If-Match` is needed.
# Test a destination before saving it
Source: https://api-docs.select.dev/v2-api-reference/destinations/test-a-destination-before-saving-it
https://api.select.dev/v2/openapi.json post /destinations/actions/test
Send a test message to a destination you have not created yet.
The body is the same as for creating a destination. Nothing is saved, so
use this to check a channel, address or webhook URL before creating the
destination. Each call sends a message. The response is `200` whether or
not the message was delivered: check `success`, and read `error_message`
when it is false.
# Update a destination
Source: https://api-docs.select.dev/v2-api-reference/destinations/update-a-destination
https://api.select.dev/v2/openapi.json patch /destinations/{destination_id}
Update a destination.
Merge-patch: only the fields you send change, and omitted fields are left
as they are. `integration_type` is required and must be the destination's
current type, which cannot be changed. No field can be cleared with
`null`.
# Create a favorite folder
Source: https://api-docs.select.dev/v2-api-reference/favorite-folders/create-a-favorite-folder
https://api.select.dev/v2/openapi.json post /favorite-folders
Create a new favorite folder for the caller.
# Delete a favorite folder
Source: https://api-docs.select.dev/v2-api-reference/favorite-folders/delete-a-favorite-folder
https://api.select.dev/v2/openapi.json delete /favorite-folders/{folder_id}
Delete a favorite folder and all favorites it contains.
# Get a favorite folder
Source: https://api-docs.select.dev/v2-api-reference/favorite-folders/get-a-favorite-folder
https://api.select.dev/v2/openapi.json get /favorite-folders/{folder_id}
Fetch a single favorite folder owned by the caller.
# List favorite folders
Source: https://api-docs.select.dev/v2-api-reference/favorite-folders/list-favorite-folders
https://api.select.dev/v2/openapi.json get /favorite-folders
List the caller's favorite folders, oldest first.
Favorites carry `folder_id` so the client can associate them with their folder.
# Rename a favorite folder
Source: https://api-docs.select.dev/v2-api-reference/favorite-folders/rename-a-favorite-folder
https://api.select.dev/v2/openapi.json patch /favorite-folders/{folder_id}
Rename a favorite folder owned by the caller.
# Reorder a favorite folder
Source: https://api-docs.select.dev/v2-api-reference/favorite-folders/reorder-a-favorite-folder
https://api.select.dev/v2/openapi.json post /favorite-folders/{folder_id}/actions/reorder
Move a folder to a new position among the top-level items.
# Create a favorite
Source: https://api-docs.select.dev/v2-api-reference/favorites/create-a-favorite
https://api.select.dev/v2/openapi.json post /favorites
Create a new favorite for the caller.
# Delete a favorite
Source: https://api-docs.select.dev/v2-api-reference/favorites/delete-a-favorite
https://api.select.dev/v2/openapi.json delete /favorites/{favorite_id}
Delete a favorite owned by the caller.
# Get a favorite
Source: https://api-docs.select.dev/v2-api-reference/favorites/get-a-favorite
https://api.select.dev/v2/openapi.json get /favorites/{favorite_id}
Fetch a single favorite owned by the caller.
# List favorites
Source: https://api-docs.select.dev/v2-api-reference/favorites/list-favorites
https://api.select.dev/v2/openapi.json get /favorites
List the caller's favorites, oldest first.
Includes `folder_id`, `order`, and `folder_order` so the client can
reconstruct the tree locally.
# Reorder a favorite
Source: https://api-docs.select.dev/v2-api-reference/favorites/reorder-a-favorite
https://api.select.dev/v2/openapi.json post /favorites/{favorite_id}/actions/reorder
Move a favorite to a new position, optionally into or out of a folder.
# Query consolidated spend
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-consolidated-spend
https://api.select.dev/v2/openapi.json post /metrics/spend/query
One row per group of spend across every connected platform. Measures cover cost by service line, so a caller can attribute spend to a warehouse, a project, a workspace or an account without knowing which platform it came from. Spend is grouped to the hour it was incurred in for a request that asks about hours, and to the day otherwise.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route first for any question about cost. It is the consolidated source of truth for spend on Snowflake, BigQuery and Databricks, and it holds every service line, not only compute. The platform routes (for example `snowflake-workloads`, `bigquery-projects` and `databricks-jobs`) give more detail for one platform, but their totals do not include every service. `sum_spend` is the dollar cost in the period. `sum_spend_annualized` is a run-rate, not spend. `usage_type` is the service that billed the cost (for example `Compute`, `Storage`, `Cloud Services`, `Serverless Tasks`, `AI Services`). `spend_category` is a coarser bucket with exactly four values: `Compute`, `Storage`, `Serverless` and `Other`. On Snowflake, Cloud Services cost is in `Other`, not in `Compute`. `connection_type` is the platform. Its values are `Snowflake`, `Bigquery` and `Databricks`, with this exact case.
# Query data freshness
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-data-freshness
https://api.select.dev/v2/openapi.json post /metrics/data-freshness/query
One row per connected service and connection, carrying the latest time data was ingested from that service. The table holds only the most recent snapshot, so it reports current freshness rather than a history of it, and has no measures to aggregate.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to find how current the data of each connection is. `latest_time` is the start of the most recent hour that has spend for that service on that connection. SELECT loads usage data from each platform with a delay of some hours, so the most recent hours and today are usually incomplete. Before you trust today's numbers from `spend` or another route, compare `latest_time` with the current time. A total for a period that ends after `latest_time` is not final. A service that stops before the others can show a stopped sync. `snapshot_at` is the time SELECT calculated the row. The route has no measures and takes no date filter. `connection_type` is lowercase: `snowflake`, `bigquery` or `databricks`.
# Query Databricks APC metrics
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-apc-metrics
https://api.select.dev/v2/openapi.json post /metrics/databricks-apc-metrics/query
One row per group of Automated Performance Cluster utilization samples, carrying worker and scheduler signals polled from live clusters over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the Spark signals that SELECT Automated Savings reads from Databricks all-purpose clusters (APC). The service polls each cluster approximately every 30 seconds. It records the active and pending tasks, the worker count and the autoscale target. Data exists only for the clusters that have Automated Savings on, and only for the time that it was on. For other clusters, the route returns no rows. This route has no `day` field: filter and group on `minute`. The measures are averages of the polls in each group, not totals. There is no cost measure: for spend and realized savings, use `databricks-clusters`. For CPU and memory, use `databricks-cluster-node-metrics`.
# Query Databricks APC savings
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-apc-savings
https://api.select.dev/v2/openapi.json post /metrics/databricks-apc-savings/query
One row per group of estimated Automated Performance Cluster savings, carrying worker-minute and spend reductions attributed to APC automation over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the estimated savings of SELECT Automated Savings on Databricks all-purpose clusters (APC). These numbers are a simulation, not realized savings. For the savings that the service actually made, use `dollars_saved` on `databricks-clusters`. The simulation replays the observed worker count and worker CPU of each minute. It calculates two savings: downscale (workers above the autoscale minimum while the cluster is idle) and scale cap (workers above a simulated cap while the cluster is busy). Only autoscaling all-purpose clusters (minimum workers less than maximum workers) have rows. A row is one cluster for one hour, and hours with no estimated savings have no row. The `*_spend` measures are dollars, `*_dbus` are DBUs and `*_worker_minutes` are worker-minutes. After Automated Savings is on for a cluster, the observed worker counts already include the effect of the service, so the estimate for those hours has no meaning. This route does not remove those hours. `databricks-clusters` with `sum_estimated_savings_in_period` does.
# Query Databricks cluster node metrics
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-cluster-node-metrics
https://api.select.dev/v2/openapi.json post /metrics/databricks-cluster-node-metrics/query
One row per group of node-level metrics for interactive Databricks clusters, carrying CPU, memory and disk utilization sampled over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the CPU, memory and network use of each node of a Databricks cluster, at minute grain. A row of the source is one node (instance) for one minute. The source holds the nodes of all classic clusters, so filter on `cluster_id`. This route has no cost measure: for the spend and utilization of a cluster, use `databricks-clusters`. For job clusters, `databricks-job-node-metrics` adds the job and task dimensions. The CPU and memory measures are percentages from 0 to 100. The network measures are bytes. The averages include the driver node unless you filter `driver` to `false`. Nodes that ran for less than 10 minutes can be missing from the source.
# Query Databricks clusters
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-clusters
https://api.select.dev/v2/openapi.json post /metrics/databricks-clusters/query
One row per group of Databricks clusters, either as a configuration inventory or as spend and utilization over the requested period, depending on the fields the request names.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the spend, utilization and savings of Databricks all-purpose clusters (the clusters that users create from the UI or the API). It does not include job clusters: for job compute, use `databricks-jobs`. The fields in the request pick the source. A request that names only `cluster_count` and configuration dimensions reads the cluster configuration history. That source has one row for each configuration change of a cluster, so a cluster whose configuration changed can count in more than one group. A request that names any other measure, or a time dimension, reads the cluster summary. The summary starts from the latest configuration of each cluster, so a cluster with no activity in the range gives a row with null measures. `sum_spend`, `idle_spend` and `dollars_saved` are dollars. `usage_dbus` is DBUs. `utilization_efficiency_percent` and the CPU and memory measures are 0 to 100. `dollars_saved` is the realized Automated Savings. The `sum_estimated_savings*` measures are a simulation of what Automated Savings would save, not realized savings. The `*_annualized` measures are run-rates, not spend in the range. For per-node CPU and memory, use `databricks-cluster-node-metrics`.
# Query Databricks dbt invocations
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-dbt-invocations
https://api.select.dev/v2/openapi.json post /metrics/databricks-dbt-invocations/query
One row per group of dbt invocations that ran on Databricks, carrying run-level metadata and aggregate cost for each invocation over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for dbt commands (for example `dbt run` or `dbt build`) that ran on Databricks SQL warehouses. Each table row is one invocation. The route has no dimension for each model. For cost by model, use `databricks-dbt-queries`. `sum_spend` is the cost in dollars. `sum_compute_dbus` is the same usage in DBUs. If one invocation used more than one warehouse SKU, its spend is null, but its DBUs are correct. `execution_status` is `SUCCESS` or `FAIL`. It is `FAIL` when a query of the invocation did not finish. `run_duration_s` is the elapsed time of the invocation in seconds. `sum_spend_annualized` is a run-rate, not spend.
# Query Databricks dbt queries
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-dbt-queries
https://api.select.dev/v2/openapi.json post /metrics/databricks-dbt-queries/query
One row per group of processed dbt queries that ran on Databricks, carrying model metadata and warehouse cost for the work each node performed over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for dbt models, tests, seeds and snapshots that ran on Databricks SQL warehouses, and for their runs. Each table row is one query that dbt sent. For one row for each dbt command, use `databricks-dbt-invocations`. `sum_spend` is the cost in dollars. `sum_compute_dbus` is the same usage in DBUs. `runs` counts node runs. `number_queries` counts queries. The SELECT app's dbt Resources page shows all resource types. To rank only models, filter on `dbt_node_resource_type = "model"`. The values are in lower case: `model`, `test`, `seed`, `snapshot`. `run_duration_s` is the duration of the node run, repeated on each of its queries. Do not add it across rows. `sum_spend_annualized` is a run-rate, not spend.
# Query Databricks JCSS metrics
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-jcss-metrics
https://api.select.dev/v2/openapi.json post /metrics/databricks-jcss-metrics/query
One row per group of Job Cluster Scaling Service samples, carrying worker counts and scheduler pressure signals used to evaluate automated job cluster scaling.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to see what SELECT Automated Savings for Databricks jobs (JCSS) observed and did on a job's clusters. By default, JCSS polls each running job cluster every 30 seconds. It lowers the cluster's autoscale maximum when workers are idle. While work is queued, it holds a low maximum and raises it only when the busy workers cannot keep up. Rows exist only for jobs with Automated Savings enabled. If your organization has no JCSS data, the route returns no rows. A source row is one poll of one job cluster. `minute` is the only time field, and there is no `day` field. Always filter on `minute`, `job_id` and `parent_workspace_id`. The route has no dollar measures. For realized savings in dollars, use `databricks-jobs` with `dollars_saved`. For CPU and memory, use `databricks-job-node-metrics`.
# Query Databricks job instance node metrics
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-job-instance-node-metrics
https://api.select.dev/v2/openapi.json post /metrics/databricks-job-instance-node-metrics/query
One row per group of per-instance node metrics for Databricks job clusters, carrying utilization sampled for each executor over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to see the CPU and memory use of each node (driver and workers) of a job's classic job clusters, minute by minute. It shows which workers stayed idle while others worked. A source row is one node in one minute. For one value per cluster and hour, use `databricks-job-node-metrics`. The route does not return dollars. For job spend, use `databricks-jobs`. The percent measures are 0 to 100. `sample_count` counts node minutes, but it counts a cluster once for each task that uses it. The minute grain gives many rows. Always filter on one job or one cluster, and use a short `day` range. Group by `hour` instead of `minute` for ranges longer than one day.
# Query Databricks job node metrics
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-job-node-metrics
https://api.select.dev/v2/openapi.json post /metrics/databricks-job-node-metrics/query
One row per group of node-level metrics for Databricks job clusters, carrying CPU, memory and disk utilization sampled over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to find oversized job clusters: CPU and memory utilization and node counts for the classic job clusters that Databricks jobs ran on. A source row is one cluster in one hour. The route does not return dollars. For job spend, use `databricks-jobs`. For each node minute by minute, use `databricks-job-instance-node-metrics`. The percent measures are 0 to 100. `utilization_efficiency_percent` is the share of node running time with CPU use above 10%. Serverless compute has no node metrics. Databricks records node metrics only for clusters that ran for more than 10 minutes. When one job cluster serves several tasks, the cluster's rows repeat once for each task, so summed measures (`running_seconds`, `usage_dbus`, network bytes) count too much. Prefer the percent, average and maximum measures.
# Query Databricks job task runs
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-job-task-runs
https://api.select.dev/v2/openapi.json post /metrics/databricks-jobs/query
One row per group of Databricks job task runs at hourly grain, carrying the cost and runtime of the work each task performed over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the cost, run counts, durations and failures of Databricks jobs and their tasks. For the CPU and memory use of job clusters, use `databricks-job-node-metrics`. For all Databricks workload types together, use `databricks-workloads`. A source row is one task run, in one hour, on one compute resource. `sum_spend` is the dollar cost. `sum_task_usage` is the usage in DBUs, not dollars. Tasks that ran on all-purpose compute have no attributed usage, so their spend is 0. Judge those tasks by run counts and durations. The SELECT app applies no default scoping filter on this route.
# Query Databricks model serving
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-model-serving
https://api.select.dev/v2/openapi.json post /metrics/databricks-model-serving/query
One row per group of Databricks model serving endpoint requests, carrying request counts, token throughput and spend for the inference traffic each endpoint served over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the cost, traffic and errors of Databricks Model Serving endpoints, by endpoint, served model, user or request. A row is one request. `sum_spend` is dollars and `sum_request_dbus` is DBUs. Databricks bills an endpoint by the hour, and this route divides each billed endpoint-hour over the requests in that hour: an equal share when `billing_mode = "uptime"`, and a share of the tokens when `billing_mode = "tokens"`. Billed hours with no requests, and batch inference, are not in this route. For the total billed Model Serving spend, use `spend` with `databricks_billing_origin_product = "Model Serving"`. The `sum_*_tokens` measures are token counts. `error_rate_percent` and `percentage_of_total_spend` are 0 to 100.
# Query Databricks queries
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-queries
https://api.select.dev/v2/openapi.json post /metrics/databricks-queries/query
One row per group of individual Databricks queries, carrying runtime, cost and metadata for each statement that ran over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for single Databricks SQL statements from the query history, one table row per statement. For recurring statements, use `databricks-query-patterns`. The table includes the queries that dbt sends. `sum_spend` is the cost in dollars. `sum_compute_dbus` is the same usage in DBUs. Only queries on SQL warehouses get a cost. The SELECT app's Query History page applies `databricks_sql_warehouse_name not in [null]`. The route has no duration dimension for each row. Group by `statement_id` and use the `sum_*_s` measures, which are in seconds. `sum_spend_annualized` is a run-rate, not spend. The route has no previous-period spend measure.
# Query Databricks query patterns
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-query-patterns
https://api.select.dev/v2/openapi.json post /metrics/databricks-query-patterns/query
One row per group of recurring Databricks query patterns, carrying the cost and execution statistics of the work each pattern represents over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for recurring SQL statements on Databricks SQL warehouses, grouped by `query_pattern_id`. For single statements, use `databricks-queries`. For cost across all workload types, use `databricks-workloads`. The table also holds the queries that dbt sends, with `resource_type` `databricks_dbt`. The SELECT app's Query Patterns page applies `resource_type in ["databricks_query_pattern"]`. Without this filter, dbt queries rank with the other patterns. `sum_spend` is the cost in dollars. `sum_compute_dbus` is the same usage in DBUs. Spend is the cost of the queries only. It does not include idle warehouse time. `sum_spend_annualized` is a run-rate, not spend.
# Query Databricks SQL warehouses
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-sql-warehouses
https://api.select.dev/v2/openapi.json post /metrics/databricks-sql-warehouses/query
One row per group of Databricks SQL warehouses, either as a configuration inventory or as spend over the requested period, depending on the fields the request names.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the spend, utilization and configuration of Databricks SQL warehouses. The fields in the request pick the source. A request with only `warehouse_count` and configuration dimensions (such as `warehouse_size`) reads the current inventory, which includes deleted warehouses. A request with an activity measure (such as `sum_spend`) reads the daily summary. A request with `hour`, `hour_of_day`, `hours_of_day` or a `potential_savings_spend_in_period*` measure reads the hourly summary. The summaries include only warehouses that are not deleted: a warehouse with no activity in the range gives a row with null measures, and a deleted warehouse's spend is missing. For total SQL warehouse spend, use `spend` with `databricks_billing_origin_product = "SQL"`. For the queries on a warehouse, use `databricks-queries`. `sum_spend`, `idle_spend`, `dollars_saved` (realized Automated Savings) and `potential_savings_spend_*` (estimated savings) are dollars. `usage_dbus` is DBUs. `utilization_efficiency_percent` is 0 to 100.
# Query Databricks workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-databricks-workloads
https://api.select.dev/v2/openapi.json post /metrics/databricks-workloads/query
One row per group of Databricks workloads — queries, jobs, dbt runs and cluster activity — carrying spend, runtime and throughput for the work that ran over the requested period.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for Databricks cost across all workload types in one table. For detail on one type, use `databricks-query-patterns`, `databricks-dbt-queries` or `databricks-jobs`. `workload_type` is `databricks_query_pattern`, `databricks_dbt`, `databricks_job`, `databricks_submit_run_job`, `databricks_workflow_run_job`, `databricks_cluster` or `databricks_idle_warehouse` (billed SQL warehouse time with no query). `sum_spend` is the cost in dollars. `sum_dbus` is the same usage in DBUs. `sum_all_resource_spend` adds the SQL warehouse spend of jobs, which the query pattern and dbt rows already hold. Do not add it across types. A job on all-purpose compute has no job row: its cost is in the `databricks_cluster` row. Duration, row and byte measures are null for job and cluster rows. `sum_spend_annualized` is a run-rate, not spend.
# Query lineage edges
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-lineage-edges
https://api.select.dev/v2/openapi.json post /metrics/lineage-edges/query
One row per directed edge between lineage workloads and tables on Snowflake or BigQuery. Direction is expressed by filtering the source or the target side rather than by a parameter. The `*_for_filters` dimensions resolve whichever side of an edge carries the value, and spell Snowflake's database and schema and BigQuery's project and dataset as one pair of names.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to walk the Snowflake and BigQuery lineage graph: what reads a table, what builds it, and what feeds a dashboard. A node is an object (`storage`, `view`, `stream` or `stage` on Snowflake, `bigquery_storage` on BigQuery), a workload (for example `dbt`, `query_pattern`, `looker`, `task`, `bigquery_dbt`), or a Tableau `tableau_data_source` or `tableau_workbook` (Snowflake only). An edge goes from source to target. A workload that reads one object and writes another sits on the edge (`edge_*`). A workload that only reads is a target node, and a workload that only writes is a source node. A `*_identifying_metadata_str` value is the node's `key:value` pairs, sorted by key and joined by commas. The graph covers the last 30 complete days and takes no date filter. `sum_spend` is the 30-day dollar cost of the workload queries on the edge. A workload repeats its cost on each of its edges, so do not add `sum_spend` across edges. One request gives one hop. For workload cost use `lineage-workloads`, and for table size use `lineage-tables`. The SELECT app's Lineage page scopes each request to one Snowflake account or one BigQuery `connection_id`, because table names repeat across accounts.
# Query lineage tables
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-lineage-tables
https://api.select.dev/v2/openapi.json post /metrics/lineage-tables/query
One row per table node that participates in lineage on Snowflake or BigQuery, carrying storage bytes and annualized cost estimates. A field the other platform has no equivalent for is null rather than zero, so time travel and failsafe are null on BigQuery and long-term storage is null on Snowflake.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the size and storage run-rate of the table nodes in the lineage graph, on Snowflake and BigQuery. One row is one table. The route has no measures: every field is a dimension, and the body names only `dimensions`. The sizes are the latest snapshot, and the route takes no date filter. Find a table's neighbors with `lineage-edges`. Every `*_annual_cost` field is the current monthly cost times 12: it is a run-rate, not spend. For storage spend in a date range, use `snowflake-storage` or `bigquery-storage-spend`. Byte fields are bytes. `executions` counts the workload runs that wrote the table in the last 30 complete days.
# Query lineage workloads
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-lineage-workloads
https://api.select.dev/v2/openapi.json post /metrics/lineage-workloads/query
One row per workload node — a query, dbt model, job or similar — that participates in lineage on Snowflake or BigQuery. Measures summarize cost and execution over a rolling thirty-day window, so this model carries no date dimension to filter on.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route for the cost, runs and users of the workload nodes in the lineage graph. Find the workloads with `lineage-edges` first, then send their `resource_type` and `identifying_metadata_str` here. The data is Snowflake and BigQuery workloads that ran in the last 30 complete days. The route has no date field and takes no date filter. One workload has many source rows, one for each user and execution. Group by `identifying_metadata` for one row per workload. `annualized_sum_spend` is the 30-day cost times 12: it is a run-rate, not spend. For the dollar cost of a workload in a date range, use `snowflake-workloads` or `bigquery-workloads`.
# Query workload metadata suggestions
Source: https://api-docs.select.dev/v2-api-reference/metrics/query-workload-metadata-suggestions
https://api.select.dev/v2/openapi.json post /metrics/workload-metadata-suggestions/query
One row per workload metadata key observed across the organization, with how often each was seen. Filter on `key_type` to ask about one family of keys — custom workload tags, dbt meta or dbt top-level configuration — and sort by `suggestion_count` to rank them.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to find which metadata keys your queries carry, before you configure custom workloads or dbt metadata as workload dimensions. `suggestion_count` is the number of queries in the last 14 days that carried the key. The window is fixed: the route has no date dimension and takes no date filter. `key_type` has three values: `custom_workload` (the keys in custom workload query tags), `dbt_meta` (the keys in the dbt `meta` config) and `dbt_top_level` (the other top-level keys in the dbt query comment). The source holds one row for each connection, key type and key. `suggestion_count` adds these rows together. `platform` and `connection_type` are lowercase: `snowflake`, `bigquery` or `databricks`. Databricks has no `custom_workload` keys.
# Search resources
Source: https://api-docs.select.dev/v2-api-reference/metrics/search-resources
https://api.select.dev/v2/openapi.json post /metrics/search/query
One row per resource in the catalog across every connected platform — warehouses, tables, jobs, clusters, dbt projects and the rest. Free-text search is expressed as an `ilike` filter on the resource name, which matches anywhere in the name.
Returns one row per combination of the requested dimensions, carrying the requested measures. Each row is keyed by dimension and measure name. `row_count` is the number of rows in `items`: results are not paginated, so an aggregation with more rows than `limit` is cut short at `limit` rather than continued under a `page_token`. Send `X-Team-Id` to evaluate the query as a team you belong to; rows are then limited to what that team's roles reach.
Use this route to find a resource by name, or to count resources, across every connected platform. It is a catalog, not a cost report. It has no date dimension and takes no date filter. `annual_cost` is a dimension, not a measure: it is a run-rate estimate from recent spend (the last 90 days for compute, the current monthly rate for storage). Do not present it as spend in a period. For spend, use `spend`. `num_resources` is the only measure. In this route, `connection_type` is lowercase: `snowflake`, `bigquery`, `databricks` or `tableau`. The SELECT app's search sorts by `annual_cost` descending and returns at most 500 rows.
# Create a monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/create-a-monitor
https://api.select.dev/v2/openapi.json post /monitors
Every query the monitor runs is checked against its query class, so a dimension, measure or filter the class does not have is rejected, naming the field, rather than failing the monitor's scheduled runs. Requires `monitors:write`.
# Delete a monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/delete-a-monitor
https://api.select.dev/v2/openapi.json delete /monitors/{monitor_id}
Deletes the monitor and its run history. The destinations it notified are unaffected. Requires `monitors:write`.
# Dismiss a monitor from the feed
Source: https://api-docs.select.dev/v2-api-reference/monitors/dismiss-a-monitor-from-the-feed
https://api.select.dev/v2/openapi.json post /monitors/{monitor_id}/actions/dismiss
Dismisses the monitor from the monitors feed; `dismissed: false` restores it. On a partitioned monitor, `partition_value` dismisses one partition's item, and a dismissal without it covers the item a failed run shows. A dismissal lasts until what it hides comes back: the partition fires again, the monitor fails again, or, on a monitor that is not partitioned, the monitor fires or fails. Dismissing is not an edit: `update_time` and the ETag are unchanged. Requires `monitors:write`.
# Duplicate a monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/duplicate-a-monitor
https://api.select.dev/v2/openapi.json post /monitors/{monitor_id}/actions/duplicate
Creates an enabled copy of a monitor named " (Copy)", with the same owner, schedule, trigger, message and destinations. A custom SQL section gets its own copy of the SQL, so editing one monitor's SQL leaves the other's unchanged. Run history and feed dismissals are not copied. Requires `monitors:write`.
# Generate a monitor title
Source: https://api-docs.select.dev/v2-api-reference/monitors/generate-a-monitor-title
https://api.select.dev/v2/openapi.json post /monitors/actions/generate-title
Suggests a title for a monitor, or for one of its chart or table sections, from how it is configured; `target` says which. The title is written by a language model, and falls back to one built from `data_source` and the schedule or lookback if none can be generated. Nothing is saved. Requires `monitors:write`.
# Get a monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/get-a-monitor
https://api.select.dev/v2/openapi.json get /monitors/{monitor_id}
Requires `monitors:read`.
# List a monitor's runs
Source: https://api-docs.select.dev/v2-api-reference/monitors/list-a-monitors-runs
https://api.select.dev/v2/openapi.json get /monitors/{monitor_id}/run-history
Lists the monitor's runs, newest first by default. `row_count` counts every run matching the request, not just the page returned. Requires `monitors:read`.
# List a query class's columns
Source: https://api-docs.select.dev/v2-api-reference/monitors/list-a-query-classs-columns
https://api.select.dev/v2/openapi.json get /monitors/query-classes/{query_class}/columns
Lists the columns a table section's `columns` and a partition's `partition_columns` can name by title, with the dimensions and measures each reads. The organization's usage group sets and workload metadata keys add columns of their own, so renaming one changes the list. Requires `monitors:read`.
# List monitor query classes
Source: https://api-docs.select.dev/v2-api-reference/monitors/list-monitor-query-classes
https://api.select.dev/v2/openapi.json get /monitors/query-classes
Lists every query class a monitor query can name in `query_class`, with the dimension and measure names each accepts and the `data_source` values it pairs with. Requires `monitors:read`.
# List monitor runs
Source: https://api-docs.select.dev/v2-api-reference/monitors/list-monitor-runs
https://api.select.dev/v2/openapi.json get /monitors/run-history
Lists the runs of every monitor the caller can read, newest first by default. `row_count` counts every run matching the request, not just the page returned. Requires `monitors:read`.
# List monitors
Source: https://api-docs.select.dev/v2-api-reference/monitors/list-monitors
https://api.select.dev/v2/openapi.json get /monitors
Lists the organization's monitors, newest first by default. `row_count` counts every monitor matching the request, not just the page returned. Requires `monitors:read`.
# Preview an unsaved monitor's message
Source: https://api-docs.select.dev/v2-api-reference/monitors/preview-an-unsaved-monitors-message
https://api.select.dev/v2/openapi.json post /monitors/actions/preview
Renders the message a monitor would send against current data, whether or not its trigger would fire, and sends nothing. The body carries the monitor in the shape create takes, and it is not saved. A message template that fails to render is rejected, naming the template. Requires `monitors:read`.
# Query monitors by dimension and measure
Source: https://api-docs.select.dev/v2-api-reference/monitors/query-monitors-by-dimension-and-measure
https://api.select.dev/v2/openapi.json post /monitors/actions/query
Aggregates the monitors the caller may see. Tally attention with the `triggered_count` and `failing_count` measures, and group by any dimension. Requires `monitors:read`.
# Replace a monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/replace-a-monitor
https://api.select.dev/v2/openapi.json put /monitors/{monitor_id}
Replaces every setting of the monitor with the body, which takes the same shape as create. The monitor's run history and feed dismissals are kept. Every query the monitor runs is checked against its query class, so a dimension, measure or filter the class does not have is rejected, naming the field, rather than failing the monitor's scheduled runs. A query that already failed that check before this request, and is sent back unchanged, is accepted. Requires `monitors:write`.
# Test-send a monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/test-send-a-monitor
https://api.select.dev/v2/openapi.json post /monitors/{monitor_id}/actions/test-send
Renders the monitor's message against current data and sends it to the monitor's destinations now, with its title prefixed `[MONITOR PREVIEW]`, whether or not the trigger would fire. Nothing is recorded in the monitor's run history. A message that cannot be rendered or delivered is rejected with the reason. Requires `monitors:read`.
# Test-send an unsaved monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/test-send-an-unsaved-monitor
https://api.select.dev/v2/openapi.json post /monitors/actions/test-send
Renders the monitor's message against current data and sends it to the monitor's destinations now, with its title prefixed `[MONITOR PREVIEW]`, whether or not the trigger would fire. Nothing is recorded in the monitor's run history. A message that cannot be rendered or delivered is rejected with the reason. For a monitor still being configured: the body carries the monitor in the shape create takes, and it is not saved. Requires `monitors:read`.
# Update a monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/update-a-monitor
https://api.select.dev/v2/openapi.json patch /monitors/{monitor_id}
Applies a merge patch: a field the request omits is left unchanged, and an explicit null clears `cron`, `team_id`, `budget_id`, `snowflake_account_id` or `partition_config`. An object field is replaced whole. The monitor that results is checked as create would check it. Every query the monitor runs is checked against its query class, so a dimension, measure or filter the class does not have is rejected, naming the field, rather than failing the monitor's scheduled runs. A query that already failed that check before this request, and is left unchanged, is accepted. Requires `monitors:write`.
# Validate an unsaved monitor
Source: https://api-docs.select.dev/v2-api-reference/monitors/validate-an-unsaved-monitor
https://api.select.dev/v2/openapi.json post /monitors/actions/validate
Checks a monitor exactly as create would, without saving it or running anything: the body takes the shape create takes. Every query the monitor runs is checked against its query class, so a dimension, measure or filter the class does not have is rejected, naming the field, rather than failing the monitor's scheduled runs. A monitor that fails a check is rejected with the reason. Requires `monitors:write`.
# Batch delete saved views
Source: https://api-docs.select.dev/v2-api-reference/saved-views/batch-delete-saved-views
https://api.select.dev/v2/openapi.json post /saved-views/actions/batch-delete
# Create a saved view
Source: https://api-docs.select.dev/v2-api-reference/saved-views/create-a-saved-view
https://api.select.dev/v2/openapi.json post /saved-views
# Delete a saved view
Source: https://api-docs.select.dev/v2-api-reference/saved-views/delete-a-saved-view
https://api.select.dev/v2/openapi.json delete /saved-views/{saved_view_id}
# Get a saved view
Source: https://api-docs.select.dev/v2-api-reference/saved-views/get-a-saved-view
https://api.select.dev/v2/openapi.json get /saved-views/{saved_view_id}
# List saved views
Source: https://api-docs.select.dev/v2-api-reference/saved-views/list-saved-views
https://api.select.dev/v2/openapi.json get /saved-views
List saved views the caller may see: their own personal views, every
public view, and any team view they hold access to.
# Update a saved view
Source: https://api-docs.select.dev/v2-api-reference/saved-views/update-a-saved-view
https://api.select.dev/v2/openapi.json patch /saved-views/{saved_view_id}