Inbound data sharing

Learn how to use Observe by Snowflake with your existing data in Snowflake.

📘

Private preview feature (Invite only)

This feature is enabled per tenant by Observe by Snowflake and is not generally available. To participate, contact your Observe by Snowflake representative. You may access and use this preview feature solely for internal evaluation purposes. Previews are provided as-is. Your use of this preview is subject to the Snowflake Preview Terms located at https://www.snowflake.com/en/legal.

Inbound data sharing reads tables you share from your existing Snowflake account and turns each one into an Observe by Snowflake Dataset. Nothing is copied: the data stays in your Snowflake account, and Observe by Snowflake reads it in place. Observe by Snowflake only reads the share; every Snowflake statement in this guide is run by you in your account.

If you're ready to start, you can skip to Configure inbound data sharing. The next few sections help to prepare you for the configuration.

Who should use inbound data sharing?

Existing Snowflake customers, who either have observability data in Snowflake already, or intend to bring it into Snowflake, want to use Observe by Snowflake as the observability product against their observability data that’s already in Snowflake.

Before you start

Verify the following requirements are met.

  • Your tenant is enabled. Make sure Observe by Snowflake has enabled inbound data sharing for your tenant as part of the preview. Until then, every call returns 403 feature_not_enabled.

  • Your Snowflake account is in the same region and cloud as Observe by Snowflake. Cross-region shares are not supported yet. In Snowflake, run SELECT CURRENT_REGION(); and compare it with the region that the setup call returns. The setup call includes the region group, as in PUBLIC.AWS_US_WEST_2; compare the part after the dot; in this case, AWS_US_WEST_2.

  • You know your account name as <ORG>.<ACCOUNT>, not a locator or a URL. Run the following command in Snowflake:

    SELECT CURRENT_ORGANIZATION_NAME() || '.' || CURRENT_ACCOUNT_NAME();
  • You can run Snowflake admin SQL, with a role that can create a share, grant objects to it, and turn on change tracking on the tables you share.

  • Your Observe by Snowflake user has the right permissions. Verify the following permissions in Observe by Snowflake:

    • sharein:view to read shares, offers, table grants and tracked tables.
    • sharein:manage to issue tokens, register, rename and delete shares, and to track, untrack and edit tables.
    • dataset:create to track a table or attach a Dataset.
    • dataset:edit on the table's Dataset to edit, detach or untrack the Dataset, or to delete a share with force=true. Without dataset:edit, you can track a table but won't be able to undo it.
    • dataset:view on the Dataset to query the Dataset.
  • Pick a tool. The REST API and the AI agent tools are available on your tenant. The inbound data sharing commands are in the Observe by Snowflake CLI v1.0.4 and higher. The Terraform resources are in the Observe Terraform provider v0.14.75 and higher.

How it works

The following table summarizes how inbound data sharing works:

StepWhoWhat happens
  1. Get setup info
Observe by SnowflakeObserve by Snowflake returns its Snowflake consumer account and the SQL you run.
  1. Create a share
You, in SnowflakeYou create a share, grant it the tables or views you want Observe by Snowflake to read, turn on change tracking where needed, and add Observe by Snowflake's account to it.
  1. Prove ownership
You, in SnowflakeObserve by Snowflake issues a one-time token and you set it as the share's comment. Only needed for the first share from a Snowflake account.
  1. Register the share
Observe by SnowflakeObserve by Snowflake checks the token and mounts the share. Its status becomes Active. You then clear the comment.
  1. Track tables
Observe by SnowflakeEach tracked table becomes an Observe by Snowflake Dataset.

Observe by Snowflake can read only what you grant to the share. Anything you don't grant, Observe by Snowflake can't see.

The following table shows an example of the values. Every inbound data share uses the same values. Replace them with yours.

ValueExample
Observe tenant123456.observeinc.com
Your Snowflake accountACME_CORP.PROD
ShareOBSERVE_SHARE
Shared tableACME_DB.PUBLIC.EVENTS, timestamp column EVENT_TIMESTAMP
Dataset to createAcme Events, kind Event

Things to know

This section contains useful tips and reminders for setting up inbound data shares.

  • A Snowflake share shows up as a read-only Dataset in Observe by Snowflake. You won't be able to edit this Dataset in any way.
  • Observe by Snowflake can read everything in the share. Share only what yopu want Observe by Snowflake to see. For sensitive data, share a secure view that masks or leaves out the sensitive columns.
  • Your Snowflake protections may not carry over. Masking and row access policies that depend on who is querying won't apply the same way once Observe by Snowflake reads the data, and customer-managed encryption (Tri-Secret Secure) may not extend into Observe by Snowflake. Apply the protection in the view you share.
  • Tokens are one-time secrets. Each token is used once and expires after 24 hours. A new token for the same account replaces the old one. Don't paste tokens into tickets or chat, and clear the share comment after registering.
  • Verifying an account covers the whole account, permanently. After the first share from a Snowflake account is registered, any user on your Observe by Snowflake tenant with sharein:manage can register other shares from that account without a token. Observe by Snowflake can still read only what you grant to a share and add Observe by Snowflake's account to.
  • One share goes to one Observe by Snowflake tenant. To send the same data to two tenants, create two shares.
  • Untracking a table deletes its Observe by Snowflake Dataset. Deleting a share with force does the same for every table in it.
  • Removing a share in Observe by Snowflake doesn't change Snowflake. The share and Observe by Snowflake's access stay in place. To stop sharing, remove Observe by Snowflake's account from the share or drop the share.
  • Revoking access in Snowflake (removing Observe by Snowflake's account, dropping the share or revoking a grant) stops the data, and the share or table shows as Unhealthy in Observe by Snowflake.
  • Cost. There is no ingestion charge, because nothing is copied. You keep paying Snowflake to store the data. In Observe by Snowflake you pay for the background queries that keep the Dataset, and anything built on it, up to date. They're billed as acceleration credits, like any other Dataset, and shown in the Usage Dashboard. See View your compute credit usage in the Usage Dashboard.

Plan your Datasets

Choose the type of Dataset you need:

KindUse it forTime fieldsChange tracking in Snowflake
Table DatasetsRows with no time column, such as reference or lookup dataNoneNot needed: Observe rereads the whole table
Event DatasetsOne point in time per rowA valid-from fieldRequired: Observe reads only the changed rows
Interval DatasetsA start and an end per rowValid-from and valid-to fieldsRequired, as for Event

The time fields must be timestamp columns. If you store time as a number, such as seconds since 1970, pass a schema mapping for that column when you track it, with type timestamp and a conversion of SecondsToTimestamp, MillisecondsToTimestamp, MicrosecondsToTimestamp or NanosecondsToTimestamp.

You can't change the kind after tracking. To change it, untrack the table and track it again.

Check that your data fits the kind

These problems don't show up as errors. Instead, you must recognize the symptoms of the issues, such as the Dataset remaining empty, is slow, or shows the wrong times:

  • Event and Interval datasets pick up new rows only. After the first read, Observe by Snowflake reads only the rows inserted since its last read. A row updated in place is not picked up again, and a deleted row stays in the Dataset. For a source that keeps rewriting rows, such as a rollup that updates the current hour's total, use a Table Dataset, or share the raw table it's built from.
  • History is included. The first read is a snapshot of the whole table, so rows already in the table appear in the Dataset straight away.
  • Time zones. Observe by Snowflake reads a TIMESTAMP_NTZ column as UTC. If you write local time into an NTZ column, it shows up shifted. Use TIMESTAMP_TZ or TIMESTAMP_LTZ, or store UTC.
  • Sort order. For Event and Interval Datasets, cluster or sort the table by its time column. Otherwise queries are slower and cost more.
  • Time Travel. Event and Interval tables need a data retention period above zero (DATA_RETENTION_TIME_IN_DAYS). Transient tables with retention set to 0 won't work.

Notes about your table views

Notes about your table views:

  • Shares accept secure views by default. To share a normal view, the share must be created with SECURE_OBJECTS_ONLY = FALSE, which can't be undone. Prefer a secure view.

  • Keep the view simple for Event and Interval Datasets. Snowflake's change tracking on views supports simple views only; FLATTEN or aggregations make reading the changes fail.

  • Change tracking goes all the way down. For an Event or Interval Dwataset on a view, turn on change tracking on the view and on every table and view it reads, down to the base tables. Those base tables must be reachable through the share.

  • A view that reads from more than one database needs the share to be granted REFERENCE_USAGE on each other database, before you grant the view:

    GRANT REFERENCE_USAGE ON DATABASE <other_db> TO SHARE OBSERVE_SHARE;

Configure inbound data sharing

Perform the following tasks to set up inbound data sharing:

  1. Set up the share in Snowflake.
  2. Register the share and track tables in Observe by Snowflake.
  3. If needed, do some Troubleshooting.

Set up the share in Snowflake

Run the following command in your Snowflake account to set up the share in Snowflake.

CREATE SHARE OBSERVE_SHARE;
GRANT USAGE ON DATABASE ACME_DB TO SHARE OBSERVE_SHARE;
GRANT USAGE ON SCHEMA ACME_DB.PUBLIC TO SHARE OBSERVE_SHARE;
GRANT SELECT ON TABLE ACME_DB.PUBLIC.EVENTS TO SHARE OBSERVE_SHARE;
-- Only for tables that will be Event or Interval datasets:
ALTER TABLE ACME_DB.PUBLIC.EVENTS SET CHANGE_TRACKING = TRUE;
ALTER SHARE OBSERVE_SHARE ADD ACCOUNTS = <observe_consumer_account>;

After ADD ACCOUNTS, it can take about 30 seconds before Observe by Snowflake sees the share. A register in that window fails with 403 ownership_proof_failed. If you see this, just wait and try again.

If this is the first share from your Snowflake account into this Observe by Snowflake tenant, issue a token and set it as the share's comment:

ALTER SHARE OBSERVE_SHARE SET COMMENT = '<token>';

You can set the comment before or after ADD ACCOUNTS; Observe by Snowflake reads it when you register. Once the share is registered, the token is spent. Clear the comment anyway, so the token doesn't stay in your share's metadata:

ALTER SHARE OBSERVE_SHARE UNSET COMMENT;

To check the setup, run SHOW GRANTS TO SHARE OBSERVE_SHARE; and SHOW SHARES LIKE 'OBSERVE_SHARE';. Observe by Snowflake's account appears in the to column.

Some things to be aware of regarding shares:

  • New tables aren't added on their own. Future grants don't apply to shares, so grant every new table or view to the share explicitly, by hand or through your automation. You can also add objects through database roles.
  • A share can't pass on another share. Objects you imported from someone else's share can't be added to your share for Observe by Snowflake.

Register the share and track tables in Observe by Snowflake

You can register the share and track tables in Observe by Snowflake using the REST API, CLI, Terraform, or your own agent via MCP Server.

Pick one tool per share and stay with it. In particular, if a share is managed in Terraform, change it only through Terraform.

REST API

Create an Observe API token, then:

export OBS="https://123456.observeinc.com"
export AUTH="Authorization: Bearer 123456 <api_token>"
# 1. Setup info: Observe's consumer account, region and setup SQL
curl -s -H "$AUTH" "$OBS/v1/shares/inbound/setup"

# 2. Registration token (first share from this Snowflake account only).
#    Set the returned token as the share comment.
curl -s -H "$AUTH" -H "Content-Type: application/json" \
  -X POST "$OBS/v1/shares/inbound/registration-tokens" \
  -d '{"providerAccount": "ACME_CORP.PROD"}'

# 3. Register. Note the returned id. Set label; without it the share is
# labelled SHARE__. Then clear the comment in Snowflake:
# ALTER SHARE OBSERVE_SHARE UNSET COMMENT;
curl -s -H "$AUTH" -H "Content-Type: application/json" \
  -X POST "$OBS/v1/shares/inbound" \
  -d '{"providerAccount": "ACME_CORP.PROD", "shareName": "OBSERVE_SHARE", "label": "Acme"}'

# 4a. See what the share grants, and check a table's columns
curl -s -H "$AUTH" -G "$OBS/v1/shares/inbound/<shareId>/table-grants" --data-urlencode 'filter=!tracked'
curl -s -H "$AUTH" "$OBS/v1/shares/inbound/<shareId>/table-grants/EVENTS/schema?schemaName=PUBLIC"

# 4b. Track the table; this creates the dataset
curl -s -H "$AUTH" -H "Content-Type: application/json" \
  -X POST "$OBS/v1/shares/inbound/<shareId>/tables" \
  -d '{"schemaName": "PUBLIC", "tableName": "EVENTS",
       "datasetLabel": "Acme Events", "datasetKind": "Event",
       "validFromField": "EVENT_TIMESTAMP"}'

# Check status
curl -s -H "$AUTH" "$OBS/v1/shares/inbound/<shareId>"
curl -s -H "$AUTH" "$OBS/v1/shares/inbound/<shareId>/tables"
curl -s -H "$AUTH" "$OBS/v1/shares/inbound/<shareId>/tables/<tableId>"

Right after you track a table, the table list can show health and cdcStatus as Unknown until the first health check. Getting the single table (GET /v1/shares/inbound/{shareId}/tables/{tableId}) checks it live. The API reference lists every call.

Observe by Snowflake CLI

The share-in commands are in the Observe by Snowflake CLI from v1.0.4. They're experimental, so turn them on first:

export OBSERVE_CLI_EXPERIMENTAL=1
observe auth login --url 123456.observeinc.com
# 1. Setup info, with your share name filled in
observe inbound-share setup --share-name OBSERVE_SHARE

# 2. Token (first share from this account only). It prints the exact
#    ALTER SHARE ... SET COMMENT statement to run.
observe inbound-share token create --provider-account ACME_CORP.PROD --share-name OBSERVE_SHARE

# 3. Register. It prints the share ID.
# Then clear the token from the share comment, in Snowflake:
# mALTER SHARE OBSERVE_SHARE UNSET COMMENT;
# Optional: give the share a readable label. Without one, it's SHARE__.
observe inbound-share register --provider-account ACME_CORP.PROD --share-name OBSERVE_SHARE
observe inbound-share update <shareId> --label "Acme"

# 4. See what is in the share, check a table's columns, and track it
observe inbound-share table list --share-id <shareId> --untracked
observe inbound-share table schema --share-id <shareId> --schema PUBLIC --table EVENTS
obsenoterve inbound-share table track --share-id <shareId> \
  --schema PUBLIC --table EVENTS \
  --dataset-label "Acme Events" --kind Event --valid-from EVENT_TIMESTAMP

# Check status
observe inbound-share view <shareId>
observe inbound-share table list --share-id <shareId>

Right after you track a table, the table list can show health and cdcStatus as Unknown until the first health check. observe inbound-share table view checks the single table live.

observe inbound-share --help lists every command, and --help on any command shows its flags. Add --json to any command for scripting. Commands that delete something ask for confirmation; --yes skips the prompt.

Terraform

The resources need Observe by Snowflake Terraform provider v0.14.75 or later. If you also manage Snowflake with Terraform, one apply covers both sides:

data "observe_inbound_share_setup" "setup" {}

# Only needed for the first share from this Snowflake account
resource "observe_inbound_share_registration_token" "acme" {
  provider_account = "ACME_CORP.PROD"
}

resource "snowflake_share" "observe" {
  name     = "OBSERVE_SHARE"
  comment  = observe_inbound_share_registration_token.acme.token
  accounts = [data.observe_inbound_share_setup.setup.consumer_account]
}

resource "observe_inbound_share" "acme" {
  share_name       = snowflake_share.observe.name
  provider_account = observe_inbound_share_registration_token.acme.provider_account
  label            = "Acme"
}

resource "observe_inbound_share_table" "events" {
  share_id         = observe_inbound_share.acme.oid
  schema_name      = "PUBLIC"
  table_name       = "EVENTS"
  dataset_label    = "Acme Events"
  dataset_kind     = "Event"
  valid_from_field = "EVENT_TIMESTAMP"
}

The grants and the change tracking setting on EVENTS still have to exist in Snowflake, through your Snowflake Terraform or the SQL in Set up the share in Snowflake.

  • The token is stored in Terraform state, so treat the state as secret. After the first share is registered, remove the token resource and the comment on snowflake_share, so the next apply clears the comment.
  • Set label. Without it, the share is registered as SHARE__.
  • Import a share registered some other way with terraform import observe_inbound_share.acme <shareId>.
  • Destroying observe_inbound_share fails while it has tracked tables. Destroying a table resource deletes its dataset.

The Terraform Registry pages for the observe_inbound_share resources and data sources list every argument.

Your own AI agent through the Observe by Snowflake MCP server

The share-in tools are part of the Observe by Snowflake MCP server. Connect your MCP client (Claude, Cursor and others) the usual way: your tenant's /settings/mcp page shows the setup for each client. The agent has a tool for each step and shows Observe by Snowflake's setup SQL as is. For example:

"I want to bring the EVENTS table from my Snowflake share OBSERVE_SHARE in account ACME_CORP.PROD into Observe."

The delete and untrack tools are marked as destructive, so most clients ask before running them. Check what the agent proposes before you approve it.

Troubleshooting

Use the following table to help you troubleshoot any issues you may encounter.

SymptomCause and fix
403 feature_not_enabledShare-in isn't on for your tenant yet. Contact your Observe by Snowflake team.
403 ownership_proof_failed on registerThe comment isn't the latest token, the token expired (after 24 hours), the account name is misspelled, or Observe by Snowflake's account isn't on the share yet. Right after ADD ACCOUNTS, wait about 30 seconds and retry. Otherwise fix the cause, with a new token if needed, and register again.
Register returns 409 share_mount_failed or share_not_queryableObserve by Snowflake can see the share but couldn't read it; the message says why. Check the grants and that Observe by Snowflake's account is still on the share, then register again. No new token is needed.
Register returns 409 share_already_mountedObserve by Snowflake's Snowflake account has already mounted this share, and Snowflake mounts a share only once per account. Usually the share is registered in another Observe by Snowflake tenant: a share can go to one tenant only, so create a second share for the second tenant. If the share is listed in your own tenant, delete it there and register again. If neither applies, contact Observe by Snowflake support.
Register returns 409 share_removal_stuckAn earlier removal of this share didn't finish. Contact Observe by Snowflake support.
A table is missing from the table grantsIt isn't granted to the share, or it's in another schema. Run SHOW GRANTS TO SHARE OBSERVE_SHARE;.
Track returns 409 cdc_not_enabledChange tracking isn't enabled for your tenant yet. Contact your Observe by Snowflake team.
The table's cdcStatus is DisabledChange tracking is off on the table. Event and Interval datasets show as Unhealthy; run ALTER TABLE ... SET CHANGE_TRACKING = TRUE (or ALTER VIEW). A Table Dataset is not affected.
The table is Unhealthy because its schema changedA column the Dataset uses was dropped, or changed to a type Observe by Snowflake reads differently. See Schema changes.
A dataset query fails because the shared table is no longer readableThe table was dropped or renamed, or its grant to the share was revoked. Restore it, or untrack the table.
"Not found" for a share or table that existsCapitalization doesn't match. Unquoted Snowflake names are upper case; quoted names must match exactly.

Schema changes

Make note of the following if you need to make schema changes to your tables:

  • Added columns don't break anything, but they don't appear in the existing Dataset.
  • Compatible changes, such as a wider VARCHAR, keep working.
  • A dropped column, or a type change Observe by Snowflake reads differently (a number becoming text, or a TIMESTAMP becoming a DATE), makes the table Unhealthy. The message lists up to five changed columns.

To pick up the new schema, untrack the table and track it again. Untracking deletes the table's Dataset. Tracking reads the table's current columns and creates a new Dataset, so pass the same kind, time fields and schema mapping again. The new Dataset has a new ID, so move anything built on the old Dataset, such as Worksheets, dashboards, Monitors, and derived Datasets, to the new Dataset.

Detaching the Dataset and attaching a new one doesn't pick up new columns. The attached Dataset uses the columns saved when the table was first tracked.

API reference

Base URL: https://<tenant>.observeinc.com. Authenticate with Authorization: Bearer <tenant> <api_token>. Every operation is in beta. Errors return JSON with a type field (for example ownership_proof_failed) and a message.

Setup and ownership proof

CallPurposePermission
GET /v1/shares/inbound/setupObserve by Snowflake's consumer account, region and cloud, the setup SQL, provider checks and a checklist.sharein:view
POST /v1/shares/inbound/registration-tokensIssue a one-time token for a provider account.

Body: providerAccount (required, <ORG>.<ACCOUNT>). Returns the token and when it expires
sharein:manage
GET /v1/shares/inbound-offersShares offered to Observe by Snowflake from accounts this tenant has already verified, that aren't registered yet. Paged with limit, offset. A share already registered in another tenant can still appear here; registering it returns 409 share_already_mounted.sharein:view

Shares

CallPurposePermission
POST /v1/shares/inboundRegister a share.

Body: providerAccount and shareName (required), label (optional, 1 to 255 characters; without it, the label is SHARE__). Returns 201 for a new share, 200 if it was already registered.
sharein:manage
GET /v1/shares/inboundList shares.

Filters: status, healthStatus, providerType; paging limit, offset; orderBy
sharein:view
GET /v1/shares/inbound/{shareId}A share's details, status and health.sharein:view
PATCH /v1/shares/inbound/{shareId}Rename a share.

Body: label
sharein:manage
DELETE /v1/shares/inbound/{shareId}Remove a share. Fails with 409 share_has_tracked_tables while tables are tracked; ?force=true untracks them first and deletes their Datasets. Also returns 204 if the share is already gone.sharein:manage; with force=true, also dataset:edit on each linked Dataset

Table grants (what the share exposes)

CallPurposePermission
GET /v1/shares/inbound/{shareId}/table-grantsEvery table and view the share grants, tracked or not. Each has schemaName, tableName, tableType (Table or View) and trackedTable (a reference to the tracked table, or null). Filter with a CEL expression, such as filter=!tracked for the ones you can still track; paging and orderBy .sharein:view
GET /v1/shares/inbound/{shareId}/table-grants/{tableName}/schema?schemaName=...Preview a granted table's columns (name, type, nullability), tracked or not.sharein:view

Tracked tables and Datasets

CallPurposePermission
POST /v1/shares/inbound/{shareId}/tablesTrack a table and create its Dataset.

Body: schemaName, tableName, datasetLabel, datasetKind (Table, Event or Interval) required; validFromField, validToField, schemaMapping, description optional
sharein:manage, dataset:create
GET /v1/shares/inbound/{shareId}/tablesA share's tracked tables, with health and change-tracking status.sharein:view
GET /v1/shares/inbound/tablesTracked tables across all shares.sharein:view
GET /v1/shares/inbound/{shareId}/tables/{tableId}One tracked table.sharein:view
PATCH /v1/shares/inbound/{shareId}/tables/{tableId}Change the Dataset's label, description, time fields or schema mapping.sharein:manage, dataset:edit
DELETE /v1/shares/inbound/{shareId}/tables/{tableId}Untrack a table. Deletes its Dataset.sharein:manage, dataset:edit
DELETE /v1/shares/inbound/{shareId}/tables/{tableId}/datasetDetach the table's Dataset and delete it. The table stays tracked, and you can attach a new Dataset with POST. The new Dataset uses the columns saved when the table was tracked.sharein:manage, dataset:edit
POST /v1/shares/inbound/{shareId}/tables/{tableId}/datasetAttach a new Dataset to a tracked table that has none. Body: dataset.sharein:manage, dataset:create

GET calls that return tables accept expand=true to include brief records of the referenced share and dataset.

Errors you may see

HTTPtypeMeaning
400bad_request, cannot_parse_requestAn invalid account name, identifier, filter, orderBy or body.
403feature_not_enabledInbound data sharing isn't enabled for the tenant.
403failed_authorizationThe user lacks the necessary permission.
403ownership_proof_failedThe share comment doesn't hold a valid, unexpired token for this account, or the share isn't offered to Observe by Snowflake.
404not_foundThe share or table doesn't exist.
409share_mount_failed, share_not_queryableObserve by Snowflake couldn't mount or read the share; fix the cause and register again.
409share_already_mountedObserve by Snowflake's Snowflake account has already mounted this share, usually for another tenant. See Troubleshooting.
409share_removal_stuckAn earlier removal didn't finish; contact Observe by Snowflake support.
409share_has_tracked_tablesDelete without force while tables are tracked.
409cdc_not_enabledChange tracking isn't enabled for the tenant.
409dataset_already_attachedThe table already has a Dataset.
422missing_fieldA required field is missing.
429Too many requests; retry later.
503service_unavailableInbound data sharing is temporarily unavailable, for example while the service starts. Retry later.



Did this page help you?