Snowflake
Connect your Snowflake organization to StackSpend via the ORGANIZATION_USAGE billing views.
What StackSpend tracks
StackSpend queries SNOWFLAKE.ORGANIZATION_USAGE.USAGE_IN_CURRENCY_DAILY to pull your billed spend in your account currency — compute, storage, data transfer, and serverless services — broken down by service type, with credits and adjustments included. Data is refreshed daily, with up to 90 days of history available on first sync.
You connect at the account level: a single connection captures spend across all databases and warehouses in the account automatically — you don’t connect per database or per warehouse, and you don’t pick which to include.
| Latency | Historical | Setup time |
|---|---|---|
| Daily | 90 days | ~10 min |
Prerequisites
- A Snowflake organization (paid) account. Standalone trial / learning accounts do not expose
ORGANIZATION_USAGEbilling data, so a live sync cannot complete on them. - Access to both the ORGADMIN role (to read the org billing views) and the ACCOUNTADMIN role (to create the service user). These are often the same person but are separate roles.
- A warehouse StackSpend can use to run the daily billing queries (e.g.
COMPUTE_WH).
USE ROLE line that doesn’t run leaves you on the wrong role and the next query fails with “Object does not exist, or operation cannot be performed.” Run each statement below individually (or select all and choose Run All), and let each finish before the next.SNOWFLAKE.ORGANIZATION_USAGE.USAGE_IN_CURRENCY_DAILY. Access to that schema requires the ORGADMIN role — a plain ACCOUNTADMIN cannot see it. The grants below hand read-only billing access to a dedicated role via the ORGANIZATION_BILLING_VIEWER database role, nothing more.If your account enforces a network policy, Snowflake will reject the connection before any query runs — the error reads “Incoming request with IP … is not allowed to access Snowflake.” Add StackSpend’s fixed outbound IP addresses to your allowlist (add all of them — traffic can egress from any one):
152.55.176.240162.220.232.252152.55.177.181
The quickest, least-invasive way is a policy scoped to just the service user:
USE ROLE ACCOUNTADMIN;
CREATE NETWORK POLICY IF NOT EXISTS stackspend_service_access
ALLOWED_IP_LIST = ('152.55.176.240', '162.220.232.252', '152.55.177.181')
COMMENT = 'StackSpend billing sync egress IPs';
-- Apply it to the service user only (does not change your account-wide policy)
ALTER USER stackspend_service_user SET NETWORK_POLICY = stackspend_service_access;If your Snowflake account is reachable only over Azure Private Link (public access disabled), an IP allowlist can’t help — there’s no public endpoint to reach. Contact support@stackspend.com for a push-based ingest setup.
Find your account identifier
In Snowsight, open Projects → Worksheets, create a worksheet, and run:
SELECT LOWER(CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME())
AS account_identifier;Copy the result — this is the Account Identifier you’ll enter in StackSpend (e.g. my-org-my-account). Older accounts may instead use the accountlocator.region form (e.g. xy12345.us-east-1).
Switch to ORGADMIN and verify billing access
First switch to the ORGADMIN role. Run this on its own and confirm it succeeds:
USE ROLE ORGADMIN;If that errors with “Role ‘ORGADMIN’ does not exist or not authorized,” your login hasn’t been granted ORGADMIN — ask whoever set up the Snowflake organization to grant it (GRANT ROLE ORGADMIN TO USER <your_user>;) or to run Steps 2–4 for you.
Then confirm the role is active and the billing view is reachable:
SELECT CURRENT_ROLE();SHOW VIEWS LIKE 'USAGE_IN_CURRENCY_DAILY'
IN SCHEMA SNOWFLAKE.ORGANIZATION_USAGE;CURRENT_ROLE() should return ORGADMIN, and the second query should return one row. If it still errors after you’re confirmed on ORGADMIN, this account doesn’t expose org billing data (see prerequisites).
Finally, list your warehouses and note one to use:
SHOW WAREHOUSES;Pick any one warehouse (a small X-Small is ideal). It’s only the engine that runs the billing queries — it does not limit what’s read, so it doesn’t matter which you choose.
Create the service user and grant access (admin)
Switch to ACCOUNTADMIN to create the user and role. Run each statement individually, in order — if you run them as one block, later lines fail with “User … does not exist.”
YOUR_WAREHOUSE below with the exact warehouse from Step 2 (e.g. LBDEVCOMMON_WH) — it must be a warehouse that exists, and it must match the Warehouse you enter in StackSpend in Step 5. If the role isn’t granted USAGE on that exact warehouse, every query fails and Test Connection reports it can’t reach the billing views.USE ROLE ACCOUNTADMIN;CREATE USER IF NOT EXISTS stackspend_service_user
DEFAULT_WAREHOUSE = YOUR_WAREHOUSE
COMMENT = 'Read-only billing user for StackSpend';CREATE ROLE IF NOT EXISTS stackspend_billing_reader;GRANT USAGE ON WAREHOUSE YOUR_WAREHOUSE TO ROLE stackspend_billing_reader;GRANT ROLE stackspend_billing_reader TO USER stackspend_service_user;ALTER USER stackspend_service_user SET DEFAULT_ROLE = stackspend_billing_reader;Confirm the user was created:
SHOW USERS LIKE 'STACKSPEND_SERVICE_USER';Now grant the billing views to the role. This usually works as ACCOUNTADMIN; if it’s denied, run USE ROLE ORGADMIN; first, then re-run the grant:
GRANT DATABASE ROLE SNOWFLAKE.ORGANIZATION_BILLING_VIEWER
TO ROLE stackspend_billing_reader;Generate a key pair and register it (recommended)
Key-pair authentication is recommended for long-lived machine access. In your terminal, move into a known folder first so you can find the files afterwards (we use ~/Downloads here), then generate an unencrypted PKCS#8 private key and its public key:
cd ~/Downloads
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt
openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pubBoth files are now in ~/Downloads. Snowflake wants the public key as a single line with no header/footer — print exactly that and copy the output:
grep -v "PUBLIC KEY" ~/Downloads/rsa_key.pub | tr -d '\n'Back in Snowsight (as ACCOUNTADMIN), register it on the service user — paste the single-line key between the quotes:
ALTER USER stackspend_service_user
SET RSA_PUBLIC_KEY = '<paste single-line public key>';Confirm it took — look for a non-null RSA_PUBLIC_KEY_FP fingerprint:
DESC USER stackspend_service_user;JWT token is invalid / decoder error:- Snowflake (
RSA_PUBLIC_KEY, above): the public key without theBEGIN/END PUBLIC KEYlines — body only. - StackSpend (Step 5, Private Key field): the full
rsa_key.p8including theBEGIN/END PRIVATE KEYlines.
openssl run.~/Downloads/rsa_key.p8 is the private key you’ll paste into StackSpend in Step 5. Keep it secret, never commit it to source control, and delete it from Downloads once it’s saved in StackSpend.Add to StackSpend
In StackSpend, go to Providers → Snowflake and enter:
| Field | Value |
|---|---|
| Account Identifier | From Step 1 |
| Username | stackspend_service_user |
| Warehouse | Your warehouse from Step 2 (required) |
| Role (optional) | stackspend_billing_reader |
| Authentication Method | Key-pair (recommended) or Username and password |
| Private Key (PEM) | Paste the full contents of ~/Downloads/rsa_key.p8, including the BEGIN/END PRIVATE KEY lines (key-pair only) |
| Private Key Passphrase (optional) | Only if your key is encrypted |
Click Test Connection to confirm billing access, then Save to begin the first sync.
Verify
The first sync fetches up to 90 days of billed currency history from USAGE_IN_CURRENCY_DAILY. Data appears in StackSpend within minutes of the sync completing.
Frequently asked questions
What Snowflake credentials does StackSpend need?
StackSpend needs a read-only Snowflake service user with key-pair authentication and access to the organization billing views. The user is granted the ORGANIZATION_BILLING_VIEWER database role, which lets it read per-warehouse credits converted to your account currency and nothing more.
Is the Snowflake connection read-only?
Yes, the service user only reads the ORGANIZATION_USAGE billing views and never writes to your Snowflake account. The grants hand it read-only billing access via the ORGANIZATION_BILLING_VIEWER role, nothing more.
How long does Snowflake setup take?
Setup takes about 10 minutes: find your account identifier, verify ORGADMIN billing access, create the service user and grants, register a key pair, and add it to StackSpend. The first sync then loads up to 90 days of billed currency history.
Why does the connection fail before any data appears?
If your account enforces a network policy, Snowflake rejects the connection before any query runs with an "IP is not allowed" error — add StackSpend's fixed egress IPs to your allowlist. Access to the billing views also requires the ORGADMIN role, since a plain ACCOUNTADMIN cannot see the ORGANIZATION_USAGE schema.