> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cord.nyc/llms.txt
> Use this file to discover all available pages before exploring further.

# Cord Data Feeds for Snowflake

> Install and configure the Cord Data Feeds Snowflake Native App to send selected Snowflake tables to Cord.

Cord Data Feeds is a Snowflake Native App for sending selected Snowflake tables to a Cord project. The app runs in the consumer Snowflake account and accesses tables registered as application references. For each push, the app compares the current table fingerprint with the fingerprint stored in Cord and uploads a table snapshot when the fingerprints differ.

## How it works

1. Register each source table as a read-only application reference.
2. The app computes a fingerprint from a consistent table snapshot.
3. If the fingerprint differs from the value stored in Cord, the app serializes the snapshot as compressed Parquet and uploads it.
4. Cord validates the upload and records the run status and row count.

The preview procedures return normalized sample rows and a table fingerprint without using external network access. See [Preview what Cord will receive](#preview-what-cord-will-receive).

## Before you start

You need:

* The **private listing** shared by Cord with your Snowflake account. Provide your Snowflake account identifier to your Cord account team to request access.
* A **feed ID** for each table and a **project feed API key** beginning with `dfk_`. Obtain both from your Cord account team.
* The **ACCOUNTADMIN** role, or assistance from a Snowflake administrator, to install the app and approve external network access.

## Install the app

1. In Snowsight, go to **Data Products → Apps**. The listing shared with your account appears there.
2. Select it, then select **Get**.
3. Name the app `CORD_DATA_FEEDS` when prompted. The commands below use this application name. If you use a different name, replace `CORD_DATA_FEEDS` in each command.

## Set up

### Step 1: Share tables with the app

Register each source table separately. Each registered table maps to one Cord feed. The following example registers two tables.

Grant read access to each table:

```sql theme={null}
CALL CORD_DATA_FEEDS.CONFIG.REGISTER_MULTI_REFERENCE(
  'consumer_tables', 'ADD',
  SYSTEM$REFERENCE('TABLE', 'PROD.SALES.ORDERS', 'PERSISTENT', 'SELECT')
);

CALL CORD_DATA_FEEDS.CONFIG.REGISTER_MULTI_REFERENCE(
  'consumer_tables', 'ADD',
  SYSTEM$REFERENCE('TABLE', 'PROD.SALES.CUSTOMERS', 'PERSISTENT', 'SELECT')
);
```

List the reference aliases assigned by Snowflake:

```sql theme={null}
SHOW REFERENCES IN APPLICATION CORD_DATA_FEEDS;
```

<Warning>
  The result contains one row per registered table. Copy the **alias** value for each table. The alias is a UUID such as `825eef28-b683-4953-9e90-dbdc2565483c`. Use the alias associated with the corresponding table in `CONFIGURE_TABLE`.
</Warning>

Map each table to its Cord feed using the table's feed ID and reference alias:

```sql theme={null}
CALL CORD_DATA_FEEDS.CONFIG.CONFIGURE_TABLE(
  'PROD.SALES.ORDERS',
  'feed_abc123',
  'orders-alias-uuid-here'
);

CALL CORD_DATA_FEEDS.CONFIG.CONFIGURE_TABLE(
  'PROD.SALES.CUSTOMERS',
  'feed_def456',
  'customers-alias-uuid-here'
);
```

To add another table, register its reference, retrieve its alias, and call `CONFIGURE_TABLE`.

### Step 2: Approve network access

Snowflake restricts external network access from Native Apps by default. An ACCOUNTADMIN must create a network rule and external access integration for the Cord API and Google Cloud Storage:

```sql theme={null}
CREATE NETWORK RULE CORD_API_NETWORK_RULE
  MODE = EGRESS TYPE = HOST_PORT
  VALUE_LIST = ('api.cord.nyc:443', 'storage.googleapis.com:443');

CREATE EXTERNAL ACCESS INTEGRATION CORD_API_ACCESS
  ALLOWED_NETWORK_RULES = (CORD_API_NETWORK_RULE)
  ENABLED = TRUE;

GRANT USAGE ON INTEGRATION CORD_API_ACCESS TO APPLICATION CORD_DATA_FEEDS;
```

Configure the app to use the external access integration:

```sql theme={null}
CALL CORD_DATA_FEEDS.CONFIG.SET_EXTERNAL_ACCESS_INTEGRATION('CORD_API_ACCESS');
```

The external access integration applies to the application account and does not need to be recreated for additional tables.

### Step 3: Add the project feed API key

```sql theme={null}
CALL CORD_DATA_FEEDS.CONFIG.SET_API_KEY('dfk_your_key');
```

The application stores one project feed API key for all configured tables. Calling `SET_API_KEY` replaces the current key.

## Preview what Cord will receive

The preview procedures read the source table without accessing an external network.

Return normalized sample rows. The procedure normalizes timestamps to UTC and serializes structured values as JSON:

```sql theme={null}
CALL CORD_DATA_FEEDS.CORE.PREVIEW_NORMALIZED('PROD.SALES.ORDERS', 5);
```

Return the whole-table fingerprint used for change detection:

```sql theme={null}
CALL CORD_DATA_FEEDS.CORE.FINGERPRINT_TABLE('PROD.SALES.ORDERS');
```

## Push

Create a separate run for every configured table:

```sql theme={null}
CALL CORD_DATA_FEEDS.CORE.PUSH_ALL();
```

Or push a single table:

```sql theme={null}
CALL CORD_DATA_FEEDS.CORE.PUSH_TABLE('PROD.SALES.ORDERS', 'live', FALSE);
```

The call waits for the runs to finish and returns one JSON result per table:

* `"disposition": "upload_required"` with `"run_status": "succeeded"` indicates that Cord received, validated, and published the table snapshot.
* `"disposition": "unchanged"` indicates that the current fingerprint matches the value stored in Cord. The app skips the unload and upload operations for that table.

`PUSH_ALL` evaluates each table independently. Use the `run_id` from a result to retrieve its current status:

```sql theme={null}
CALL CORD_DATA_FEEDS.CORE.RUN_STATUS('feed_abc123', 'run-id-from-the-result');
```

## FAQ

<AccordionGroup>
  <Accordion title="What can the app see?">
    The application receives read-only access to tables registered with `REGISTER_MULTI_REFERENCE`. Remove a table configuration with `CALL CORD_DATA_FEEDS.CONFIG.REMOVE_TABLE('PROD.SALES.ORDERS');`.
  </Accordion>

  <Accordion title="What data does the app send?">
    Each push sends a table fingerprint consisting of a hash and row count. When the fingerprint differs from the value stored in Cord, the app uploads the full table snapshot as compressed Parquet over HTTPS. Use `PREVIEW_NORMALIZED` to inspect normalized sample rows.
  </Accordion>

  <Accordion title="What operations run for an unchanged table?">
    The app runs a fingerprint query in the Snowflake warehouse. If the fingerprint matches the value stored in Cord, the app does not unload or upload the table.
  </Accordion>

  <Accordion title="Does the app upload only changed rows?">
    No. When the table fingerprint changes, the app uploads the full table snapshot. Cord compares the snapshot with the existing feed data.
  </Accordion>

  <Accordion title="What happens when upload validation fails?">
    Cord validates schemas, row counts, and checksums before publishing the snapshot. If validation fails, the run returns an error and Cord does not publish the snapshot.
  </Accordion>

  <Accordion title="How do I force a re-upload?">
    Run `CALL CORD_DATA_FEEDS.CORE.PUSH_TABLE('PROD.SALES.ORDERS', 'live', TRUE);`. The final `TRUE` bypasses the fingerprint match and requests an upload.
  </Accordion>

  <Accordion title="How do I rotate my project feed API key?">
    Obtain a new project feed API key from your Cord account team. Run `SET_API_KEY` with the new key, execute a push, and request revocation of the previous key.
  </Accordion>

  <Accordion title="How do I schedule daily pushes?">
    Create a Snowflake task with `CREATE TASK CORD_DAILY_PUSH SCHEDULE = 'USING CRON 0 6 * * * UTC' AS CALL CORD_DATA_FEEDS.CORE.PUSH_ALL();`. Enable the task with `ALTER TASK CORD_DAILY_PUSH RESUME;`.
  </Accordion>

  <Accordion title="How do I remove the application?">
    Run `DROP APPLICATION CORD_DATA_FEEDS;` to remove the application.
  </Accordion>
</AccordionGroup>

## Support

Contact your Cord account team or [support@cord.nyc](mailto:support@cord.nyc).
