Tutorial: Get started with Elastic Channels (REST API)¶
Note
We recommend starting with the SDK getting-started guide to benefit from the improved throughput and simpler error handling the SDK provides. Use the REST API for lightweight workloads where the SDK is not suitable.
This tutorial shows how to stream data into Snowflake through the Snowpipe Streaming REST API using an Elastic Channel, cURL, and a JWT. The Elastic Channel REST path is the recommended starting point for new REST integrations because it does not require opening a channel or managing offset and continuation tokens.
For the Named Channel REST path (ordered, exactly-once ingestion), see Tutorial: Get started with Snowpipe Streaming REST API.
Prerequisites¶
-
A Snowflake user configured for key-pair authentication. Register your public key:
For required privileges, see Access control.
-
A Snowflake database, schema, and target table:
-
curl,jq, and SnowSQL installed. -
Your Snowflake account identifier (Format 1:
myorg-account123). For details, see Account identifiers.
Step 1: Generate a JWT and set environment variables¶
Generate a JWT using SnowSQL:
Caution
Store your JWT securely. Avoid exposing it in logs or shell history.
Set environment variables for the tutorial:
Step 2: Discover and configure the ingest host¶
Snowpipe Streaming REST uses two hostnames. The first is the Snowflake account endpoint (CONTROL_HOST). The second is an account-specific ingest endpoint (INGEST_HOST) returned by GET /v2/streaming/hostname.
If you use AWS PrivateLink, Azure Private Link, or Google Cloud Private Service Connect, set CONTROL_HOST to the hostname from privatelink-account-url returned by SYSTEM$GET_PRIVATELINK_CONFIG.
Important
If your Snowflake account name contains underscores, replace all underscores with dashes in the INGEST_HOST before generating the scoped token. Use the converted value (with dashes) for all subsequent API calls. For example, my_account.region.ingest.snowflakecomputing.cn becomes my-account.region.ingest.snowflakecomputing.cn.
Discover the ingest host:
If you use private connectivity, create a private DNS record for INGEST_HOST that routes to your existing Snowflake private endpoint. You don’t need a second Snowflake private endpoint. For details, see the private connectivity troubleshooting section.
Obtain a scoped token for the ingest host:
Step 3: Create sample rows¶
Create a batch of rows in newline-delimited JSON (NDJSON) format. Include a stable event identifier (id) in each row so that you can deduplicate downstream if the request is retried.
id is a stable event identifier for deduplication. REQUEST_ID is a UUID you will use to track the request, and reuse on retries of the same rowset (batch of rows).
Step 4: Append rows to the Elastic Channel¶
Send the rows to the table endpoint, which is available only for Elastic Channels. On the first request, Snowflake creates or resolves the managed default pipe. Every streaming pipe includes an implicit ELASTIC channel; the request uses it without a separate open-channel operation.
A successful HTTP 200 response is the durable acknowledgement: Snowflake has durably buffered the request payload. It does not mean the rows are immediately queryable.
Important
Elastic delivery is at least once. If the request returns an ambiguous response (network timeout, no response, or a server-side 5xx) and you retry, Snowflake may already have accepted the original request. Pass the same requestId on every retry of the same rowset to enable server-side correlation for support. The retryCount query parameter helps Snowflake identify retries: set it to 0 on the first attempt and increment it on each retry. A retryCount greater than 0 signals that duplicates are possible. Add a stable event identifier to your payload and reconcile or deduplicate downstream when duplicates matter.
Alternatively, you can use the pipe endpoint for a custom PIPE:
Note
Direct REST clients own batching and compression, unlike SDK users whose appends are combined internally. For production REST requests, build bounded NDJSON batches and send partial batches after an elapsed-time threshold. Use ZSTD or Gzip compression: add Content-Encoding: zstd or Content-Encoding: gzip only when the payload is compressed in the matching format. Each Elastic request can contain up to 4 MB of payload data (the payload size sent over the network, after compression if used).
Step 5: Verify the data¶
Allow a few seconds for Snowflake to process and materialize the data, then query the target table:
If rows are acknowledged but not visible in the target table, check the error table:
For more information on error tables, see Error logging in Snowpipe Streaming with high-performance architecture.
Step 6: Clean up (optional)¶
Troubleshooting¶
- HTTP 401 (Unauthorized): Verify that your JWT is valid and not expired. Regenerate if needed.
- HTTP 404 (Not Found): Verify that the database, schema, and table names are correct and exist in your Snowflake account.
- HTTP 429 (Too Many Requests): Retry using exponential backoff with random variation in retry delays (jitter). Don’t assume a fixed reserved request rate.
- No rows in target table after acknowledgement: Allow time for materialization, then check the error table.
Private connectivity troubleshooting¶
CONTROL_HOSTdoesn’t resolve: Verify that you usedprivatelink-account-urland that the private DNS zone is linked to the application runtime.Get Hostnamesucceeds butINGEST_HOSTdoesn’t resolve: Add the returned ingest hostname to private DNS and route it through the existing Snowflake private endpoint.- DNS works outside the connector but fails inside it: Test from the connector container or runtime, and restart long-running workers after DNS changes if they cache negative DNS responses.
- TLS hostname mismatch: Keep the returned ingest hostname as the URL hostname. Don’t connect to the raw private endpoint IP address or rewrite the TLS SNI or HTTP
Hostheader.
Next steps¶
- Best practices: Batching, compression, stable event IDs, and graceful shutdown.
- Error handling: Retries, duplicate risk, and request ID correlation.
- REST API reference: Full Elastic endpoint specifications.
- Limitations: Request size, delivery guarantees, and SDK version requirements.