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:

Request headers

The following request headers apply to all the endpoints for the Snowpipe Streaming REST API:

HeaderDescription
AuthorizationAuthentication 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.

GET /v2/streaming/hostname

Response:

{
  "hostname": "string"
}

Description of response fields:

FieldTypeDescription
HostnameStringThe 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.

POST /oauth/token

Request:

AttributeRequiredComponentDescription
content_typeYesHeader“application/x-www-form-urlencoded”
grant_typeYesPayloadurn:ietf:params:oauth:grant-type:jwt-bearer
scopeYesPayloadThe hostname of the account.

Response:

{
  "token": "string"
}

Description of response fields:

FieldTypeDescription
TokenStringThe 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:

POST /v2/streaming/data/databases/{databaseName}/schemas/{schemaName}/tables/{tableName}/rows
POST /v2/streaming/data/databases/{databaseName}/schemas/{schemaName}/pipes/{pipeName}/channels/ELASTIC/rows

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

AttributeRequiredComponentDescription
databaseNameYesURIDatabase name, case-insensitive.
schemaNameYesURISchema name, case-insensitive.
tableName or pipeNameYesURIThe target table for the default pipe, or the custom pipe name.
rowsYesBodyNDJSON rows. The maximum Elastic request payload is 4 MB (the payload size sent over the network, after compression if used).
requestIdNoQuery parameterA 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.
retryCountNoQuery parameterThe 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.

{
  "message": "OK"
}

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

export REQUEST_ID=$(uuidgen)

curl -sS -X POST \
  -H "Authorization: Bearer $SCOPED_TOKEN" \
  -H "Content-Type: application/x-ndjson" \
  "https://${INGEST_HOST}/v2/streaming/data/databases/$DB/schemas/$SCHEMA/tables/$TABLE/rows?requestId=$REQUEST_ID&retryCount=0" \
  --data-binary @rows.ndjson | jq .

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:

Snowpipe Streaming named-channel REST API 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.

PUT /v2/streaming/databases/{databaseName}/schemas/{schemaName}/pipes/{pipeName}/channels/{channelName}

Request:

AttributeRequiredComponentDescription
databaseNameYesURIDatabase name, case-insensitive.
schemaNameYesURISchema name, case-insensitive.
pipeNameYesURIPipe name, case-insensitive.
channelNameYesURIThe name of the channel that you create or re-open, case-insensitive.
offset_tokenNoPayloadString used to set an offset token when opening a channel.
fail_on_uncommitted_rowsNoPayloadBoolean. 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).
requestIdNoQuery parameterA universally unique identifier (UUID) used to track requests through the system.

Response:

{
  "next_continuation_token": "string",
  "channel_status": {
    "database_name": "string",
    "schema_name": "string",
    "pipe_name": "string",
    "channel_name": "string",
    "channel_status_code": "string",
    "last_committed_offset_token": "string",
    "created_on_ms": "long",
    "rows_inserted": "int",
    "rows_parsed": "int",
    "rows_error_count": "int",
    "last_error_offset_upper_bound": "string",
    "last_error_message": "string",
    "last_error_timestamp": "timestamp_utc",
    "snowflake_avg_processing_latency_ms": "int"
  }
}

Description of response fields:

FieldTypeDescription
next_continuation_tokenStringAn 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_statusObject

A nested object with the following detailed information about the channel:

  • database_name (String): The name of the database where the pipe is located.
  • schema_name (String): The name of the schema where the pipe is located.
  • pipe_name (String): The name of the specific pipe being used.
  • channel_name (String): The name of the streaming channel.
  • channel_status_code (String): A code that indicates the current status of the channel; for example, “ACTIVE”.
  • last_committed_offset_token (String): The token that represents the last successfully committed offset.
  • created_on_ms (Long): The timestamp, in milliseconds, when the channel was created.
  • rows_inserted (Int): The total number of rows successfully inserted.
  • rows_parsed (Int): The total number of rows parsed.
  • rows_error_count (Int): The total number of rows that encountered an error.
  • last_error_offset_upper_bound (String): A token that indicates the upper bound of the offset where the last error occurred.
  • last_error_message (String): The message of the last error that occurred.
  • last_error_timestamp (Long): The timestamp, in milliseconds, of the last error.
  • snowflake_avg_processing_latency_ms (Int): The average processing latency of Snowflake in milliseconds.

Append rows to a Named Channel

The Append Rows operation inserts a batch of rows to the given channel.

POST /v2/streaming/data/databases/{databaseName}/schemas/{schemaName}/pipes/{pipeName}/channels/{channelName}/rows

Request:

AttributeRequiredComponentDescription
databaseNameYesURIDatabase name, case-insensitive.
schemaNameYesURISchema name, case-insensitive.
pipeNameYesURIPipe, case-insensitive.
channelNameYesURIChannel name, case-insensitive.
continuationTokenYesQuery parameterContinuation token from Snowflake, encapsulates both client and row sequencers.
startOffsetTokenNoQuery parameterOffset token for the first row in the batch.
endOffsetTokenNoQuery parameterOffset token for the last row in the batch.
rowsYesPayloadThe actual data payload to be ingested in NDJSON format. The maximum allowed size for this attribute is 4 MB.
requestIdNoQuery parameterA 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:

{
  "next_continuation_token": "string"
}

Description of response fields:

FieldTypeDescription
next_continuation_tokenstringThe 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.

DELETE /v2/streaming/databases/{databaseName}/schemas/{schemaName}/pipes/{pipeName}/channels/{channelName}

Request:

AttributeRequiredComponentDescription
databaseNameYesURIDatabase name, case-insensitive
schemaNameYesURISchema name, case-insensitive
pipeOrTableNameYesURIPipe or table name, case-insensitive
channelNameYesURIChannel name, case-insensitive
fail_on_uncommitted_rowsNoPayloadBoolean. 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).
requestIdNoQuery parameterA 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.

POST /v2/streaming/databases/{databaseName}/schemas/{schemaName}/pipes/{pipeName}:bulk-channel-status

Request:

AttributeRequiredComponentDescription
databaseNameYesURIDatabase name, case-insensitive
schemaNameYesURISchema name, case-insensitive
pipeNameYesURIPipe name, case-insensitive
channel_namesYesPayloadAn 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:

{
  "channel_statuses": {
    "channel1": {
      "channel_status_code": "String",
      "last_committed_offset_token": "String",
      "database_name": "String",
      "schema_name": "String",
      "pipe_name": "String",
      "channel_name": "String",
      "rows_inserted": "int",
      "rows_parsed": "int",
      "rows_errors": "int",
      "last_error_offset_upper_bound": "String",
      "last_error_message": "String",
      "last_error_timestamp": "timestamp_utc",
      "snowflake_avg_processing_latency_ms": "int"
    },
    "channel2": {
      "comment": "same structure as channel1"
    }
    "comment": "potentially other channels"
  }
}

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:

FieldTypeDescription
channel_status_codeStringIndicates the status of the channel.
last_committed_offset_tokenStringLatest committed offset token.
database_nameStringThe name of the database that the channel belongs to.
schema_nameStringThe name of the schema that the channel belongs to.
pipe_nameStringThe name of the pipe that the channel belongs to.
channel_nameStringThe name of the channel.
rows_insertedintA count of all rows inserted into this channel.
rows_parsedintA count of all rows parsed, but not necessarily inserted into this channel.
rows_errorsintA count of all rows that experienced errors when inserted into this channel and were therefore rejected.
last_error_offset_upper_boundStringThe upper bound for an ingestion error. The error will be located at or before this committed offset token.
last_error_messageStringA human readable message corresponding to the latest error code for that channel, with sensitive customer data redacted.
last_error_timestamptimestamp_utcTimestamp at the time when the last error occurred.
snowflake_avg_processing_latency_msintAverage 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:

{
  "code": "...",
  "message": "..."
}

Response fields

FieldTypeDescription
CodeStringA 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.
MessageStringA 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:

{
  "code": "STALE_CONTINUATION_TOKEN_SEQUENCER",
  "message": "Channel sequencer in the continuation token is stale. Please reopen the channel"
}

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.