Snowpipe Streaming REST API endpoints¶
Note
Where possible, use the Snowpipe Streaming SDK instead of the REST API to benefit from automatic batching and simpler integration. Use direct REST when an SDK isn’t suitable for your environment.
The Snowpipe Streaming REST API is designed for lightweight workloads and provides a flexible way to integrate with external applications without using a Snowpipe Streaming SDK.
This reference documents both ingestion modes:
- Elastic Channel endpoints for at-least-once ingestion without channel lifecycle or offset-token management.
- Named Channel endpoints for ordered, exactly-once ingestion.
Request headers¶
The following request headers apply to all the endpoints for the Snowpipe Streaming REST API:
| Header | Description |
|---|---|
Authorization | Authentication token |
X-Snowflake-Authorization-Token-Type (optional) | JWT/OAuth |
Content-Encoding (optional) | Specifies the compression format of the payload. Supported: gzip, zstd. |
User-Agent (optional) | Identifies the client application. Recommended format: SnowpipeStreamingSDK/{version} ({platform}) {LANGUAGE}/{language_version} (app={partner-name}). Example: SnowpipeStreamingSDK/1.0.0 (Linux amd64) PYTHON/3.11.0 (app=MyPartnerApp). |
Direct REST clients must group rows into newline-delimited JSON (NDJSON), with one JSON object per line, and handle compression themselves. Both Elastic and Named Channel append requests have a 4 MB payload limit (the payload size sent over the network, after compression if used). Batch rows and use ZSTD or Gzip compression to reduce request overhead; bound batch size and elapsed time before sending.
Get Hostname¶
The Get Hostname returns the hostname used to interact with the Snowpipe Streaming REST API. Each account has a unique hostname.
Note
For private connectivity (AWS PrivateLink, Azure Private Link, or Google Cloud Private Service Connect), call this endpoint through your private account URL, and configure private DNS for the returned ingest hostname before you use it for the scoped-token exchange and streaming operations. For complete steps, see Discover and configure the ingest host in the REST API tutorial.
Response:
Description of response fields:
| Field | Type | Description |
|---|---|---|
| Hostname | String | The hostname of the account. |
Exchange Scoped Token¶
The Exchange Scoped Token returns a security token that can be used to access only the Snowpipe Streaming API-related service. This provides security protection for the customer.
Request:
| Attribute | Required | Component | Description |
|---|---|---|---|
| content_type | Yes | Header | “application/x-www-form-urlencoded” |
| grant_type | Yes | Payload | “urn:ietf:params:oauth:grant-type:jwt-bearer” |
| scope | Yes | Payload | The hostname of the account. |
Response:
Description of response fields:
| Field | Type | Description |
|---|---|---|
| Token | String | The scoped token. |
Elastic Channel endpoints¶
Elastic Channels don’t require a separate open-channel operation. Send a batch of NDJSON rows directly to a table or to the implicit ELASTIC channel of a pipe:
The table endpoint is only for Elastic Channels. On the first request, Snowflake creates or resolves the managed default pipe named <tableName>-STREAMING. Each streaming pipe includes an implicit ELASTIC channel, which the request uses without a separate open-channel operation. Use the pipe endpoint for an Elastic Channel on a custom pipe with in-flight transformations or pre-clustering.
Elastic request attributes¶
| Attribute | Required | Component | Description |
|---|---|---|---|
databaseName | Yes | URI | Database name, case-insensitive. |
schemaName | Yes | URI | Schema name, case-insensitive. |
tableName or pipeName | Yes | URI | The target table for the default pipe, or the custom pipe name. |
rows | Yes | Body | NDJSON rows. The maximum Elastic request payload is 4 MB (the payload size sent over the network, after compression if used). |
requestId | No | Query parameter | A UUID that tracks the request. Use the same value on every retry of the same rowset (batch of rows), and generate a new UUID for each distinct rowset. |
retryCount | No | Query parameter | The retry attempt number, starting at 0. Increment it for each retry. A value greater than 0 signals that duplicate rows are possible; it doesn’t prove that a duplicate occurred. |
Elastic requests must not include offsetToken, startOffsetToken, endOffsetToken, or continuationToken.
Elastic response and delivery semantics¶
A successful HTTP 200 response is the durable acknowledgement: Snowflake has durably buffered the request payload. It doesn’t mean that rows are immediately queryable in the target table. Row-level processing errors are persisted to the error table when error logging is enabled.
Elastic Channels provide at-least-once delivery without an ordering guarantee. Retrying after an ambiguous response can produce duplicate rows. Include a stable event identifier in the row payload and reconcile or deduplicate downstream when duplicates matter.
Elastic append example¶
For a retry of this rowset, reuse REQUEST_ID and increment retryCount. To use a custom pipe, replace the table path with /pipes/$PIPE/channels/ELASTIC/rows.
Named Channel endpoints¶
Named Channels require explicit channel lifecycle, continuation tokens, and source offset tokens. The following operations support ordered, exactly-once ingestion.
The following diagram shows the Named Channel request flow:
Open a Named Channel¶
The Open Channel operation creates or opens a new channel against a pipe or table. If the channel already exists, Snowflake bumps the client sequencer of the channel and returns the last committed offset token.
Request:
| Attribute | Required | Component | Description |
|---|---|---|---|
| databaseName | Yes | URI | Database name, case-insensitive. |
| schemaName | Yes | URI | Schema name, case-insensitive. |
| pipeName | Yes | URI | Pipe name, case-insensitive. |
| channelName | Yes | URI | The name of the channel that you create or re-open, case-insensitive. |
| offset_token | No | Payload | String used to set an offset token when opening a channel. |
| fail_on_uncommitted_rows | No | Payload | Boolean. When true, the server rejects the request with HTTP 409 Conflict (ERR_CHANNEL_HAS_UNCOMMITTED_DATA) if the channel has uncommitted in-flight data. Otherwise, in-flight data is silently discarded and can slow co-located channels on the pipe (default: false). |
| requestId | No | Query parameter | A universally unique identifier (UUID) used to track requests through the system. |
Response:
Description of response fields:
| Field | Type | Description |
|---|---|---|
| next_continuation_token | String | An API-managed token that must be used in the subsequent Append Rows request. The token links a series of calls, ensuring a contiguous, in-order stream of data and maintaining the session state for exactly once delivery. |
| channel_status | Object | A nested object with the following detailed information about the channel:
|
Append rows to a Named Channel¶
The Append Rows operation inserts a batch of rows to the given channel.
Request:
| Attribute | Required | Component | Description |
|---|---|---|---|
| databaseName | Yes | URI | Database name, case-insensitive. |
| schemaName | Yes | URI | Schema name, case-insensitive. |
| pipeName | Yes | URI | Pipe, case-insensitive. |
| channelName | Yes | URI | Channel name, case-insensitive. |
| continuationToken | Yes | Query parameter | Continuation token from Snowflake, encapsulates both client and row sequencers. |
| startOffsetToken | No | Query parameter | Offset token for the first row in the batch. |
| endOffsetToken | No | Query parameter | Offset token for the last row in the batch. |
| rows | Yes | Payload | The actual data payload to be ingested in NDJSON format. The maximum allowed size for this attribute is 4 MB. |
| requestId | No | Query parameter | A UUID used to track requests through the system. |
Note
The JSON text within the NDJSON payload must strictly conform to the RFC 8259 standard. Each JSON text must be followed by a newline character \n (0x0A). You can also insert a carriage return \r (0x0D) before the newline character.
Response:
Description of response fields:
| Field | Type | Description |
|---|---|---|
| next_continuation_token | string | The next continuation token from Snowflake, which encapsulates both client and row sequencers. It should be used for inserting the next batch. |
Drop a Named Channel¶
The Drop Channel operation drops a channel at server side along with its metadata.
Request:
| Attribute | Required | Component | Description |
|---|---|---|---|
| databaseName | Yes | URI | Database name, case-insensitive |
| schemaName | Yes | URI | Schema name, case-insensitive |
| pipeOrTableName | Yes | URI | Pipe or table name, case-insensitive |
| channelName | Yes | URI | Channel name, case-insensitive |
| fail_on_uncommitted_rows | No | Payload | Boolean. When true, the server rejects the request with HTTP 409 Conflict (ERR_CHANNEL_HAS_UNCOMMITTED_DATA) if the channel has uncommitted in-flight data. Otherwise, in-flight data is silently discarded and can slow co-located channels on the pipe (default: false). |
| requestId | No | Query parameter | A UUID used to track requests through the system |
Response:
This operation returns a payload with no specific successful response other than the HTTP status code.
Get Named Channel status in bulk¶
The Bulk Get Channel Status operation returns the status of a channel for a specific client sequencer.
Request:
| Attribute | Required | Component | Description |
|---|---|---|---|
| databaseName | Yes | URI | Database name, case-insensitive |
| schemaName | Yes | URI | Schema name, case-insensitive |
| pipeName | Yes | URI | Pipe name, case-insensitive |
| channel_names | Yes | Payload | An array of String channel names that the customer wants to get status for; the names are case-sensitive. For example, {"channel_names":["channel1", "channel2"]}. |
Response:
Note
If no requested channel is found in the service, the response payload doesn’t have an entry for that channel within the channel_statuses object.
Description of channel_statuses fields for each channel:
| Field | Type | Description |
|---|---|---|
| channel_status_code | String | Indicates the status of the channel. |
| last_committed_offset_token | String | Latest committed offset token. |
| database_name | String | The name of the database that the channel belongs to. |
| schema_name | String | The name of the schema that the channel belongs to. |
| pipe_name | String | The name of the pipe that the channel belongs to. |
| channel_name | String | The name of the channel. |
| rows_inserted | int | A count of all rows inserted into this channel. |
| rows_parsed | int | A count of all rows parsed, but not necessarily inserted into this channel. |
| rows_errors | int | A count of all rows that experienced errors when inserted into this channel and were therefore rejected. |
| last_error_offset_upper_bound | String | The upper bound for an ingestion error. The error will be located at or before this committed offset token. |
| last_error_message | String | A human readable message corresponding to the latest error code for that channel, with sensitive customer data redacted. |
| last_error_timestamp | timestamp_utc | Timestamp at the time when the last error occurred. |
| snowflake_avg_processing_latency_ms | int | Average end-to-end processing time for this channel. |
Error response structure¶
The Snowpipe Streaming REST APIs return a JSON payload for error responses. This structure provides actionable information for both automated error handling and human analysis.
The response payload has the following structure:
Response fields¶
| Field | Type | Description |
|---|---|---|
| Code | String | A stable, programmatic error code. This value can be used for automated error handling and logging. For example, an application’s logic can check for a specific code to trigger a predefined action. |
| Message | String | A human-readable message that describes the error. This message is subject to change and shouldn’t be used for automated parsing. |
Example¶
The following example shows an error response you might receive:
This example shows the response for an attempt to use a continuation token with a stale channel sequencer. The code provides a clear, machine-readable identifier for the error, and the message offers a helpful, descriptive text for a user.
