The Streams REST API provides programmatic access to create, manage, and monitor your Streams. All operations available in the dashboard can be performed via API.
Authentication
To send your first request using the REST API, you need to obtain an API key from the Quicknode dashboard. All API requests require authentication via this key passed in the x-api-key header.
Get your API key:
Open API Keys in Dashboard
Creating an API Key
If you don't have an API key yet, follow these steps:
- Open the API Keys page in the Quicknode Dashboard
- Click Add API Key in the top-right corner
- In the modal, select the applications you need access to (enable Streams at minimum)
- Choose a Role (Admin for full access)
- Optionally add a Label to identify the key (e.g., "Production - Streams")
- Click Create and copy your API key
Using Your API Key
Once you have your API key, you can send your first request to the Streams API. Include the key in the x-api-key header with every request:
curl -X GET "https://api.quicknode.com/streams/rest/v1/streams" \
-H "x-api-key: YOUR_API_KEY"
Keep your API key secret. Do not commit it to version control or expose it in client-side code.
Base URL
All API requests should be made to the following base URL. Append the endpoint path to this URL when making requests.
https://api.quicknode.com/streams/rest/v1
For example, to list all streams, send a request to https://api.quicknode.com/streams/rest/v1/streams.
Endpoints
The following endpoints are available for managing your streams:
| Method | Endpoint | Description |
|---|---|---|
| POST | /streams | Create a new stream |
| GET | /streams | List all streams |
| GET | /streams/{id} | Get stream by ID |
| PATCH | /streams/{id} | Update a stream |
| DELETE | /streams/{id} | Delete a stream |
| DELETE | /streams | Delete all streams |
| POST | /streams/{id}/pause | Pause a stream |
| POST | /streams/{id}/activate | Activate a stream |
| GET | /streams/enabled_count | Get count of active streams |
| POST | /streams/test_filter | Test a filter function |
Example: Creating a Stream
This example demonstrates how to create a new stream that delivers Ethereum block data to a webhook endpoint. Every request to the Streams API requires the x-api-key header for authentication and Content-Type: application/json for request bodies.
Request
curl -X POST "https://api.quicknode.com/streams/rest/v1/streams" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "ethereum-blocks",
"network": "ethereum-mainnet",
"dataset": "block",
"region": "usa_east",
"dataset_batch_size": 1,
"elastic_batch_enabled": true,
"destination": "webhook",
"destination_attributes": {
"url": "https://your-endpoint.example.com/webhook",
"compression": "none",
"max_retry": 3,
"retry_interval_sec": 1,
"post_timeout_sec": 10,
"mtls": true
},
"status": "active"
}'
See Create Stream for all parameters including filter functions, backfill ranges, and additional destinations.
Batch Size and Elastic Batch
dataset_batch_size sets how many blocks a Stream processes in one filter execution and delivers in one payload. elastic_batch_enabled controls what happens when fewer blocks than that are available at the chain tip.
- Batch size groups blocks so your filter runs once across the set instead of once per block. On networks producing several blocks per second, a group of blocks is the natural unit of work, and batching is what lets a Stream keep up with the chain. This matters most for filters doing heavier computation.
- Elastic Batch means a larger batch size never waits for the batch to fill. If the Stream is configured for five blocks and only two are available at the tip, those two are processed and delivered immediately. You get the efficiency of batching and delivery at tip speed at the same time.
Networks with sub-second block times
Block production is accelerating across the industry, with networks moving to shorter block times and larger blocks. Streams that follow the chain tip (no end_range, or end_range: -1) on networks with block times under one second must use a dataset_batch_size of at least 5, or your plan's maximum batch size if that is lower. Requests below the minimum are rejected with a 422 response. Backfill Streams with a fixed end_range are not affected.
We recommend enabling Elastic Batch on these Streams so blocks still reach your endpoint as soon as they are produced and your filter has executed. Existing Streams keep their current configuration. To move one to the recommended settings, use Update Stream to raise dataset_batch_size and set elastic_batch_enabled to true.
Using Filters via API
Filters let you transform and customize stream data before delivery. When using the API, pass your filter function as a base64-encoded string in the filter_function parameter.
Filter Function Requirements
- Must be named
main - Receives a single parameter with
.data(blockchain data) and.metadata(stream info) - Return an object/array/string to deliver data, or
nullto skip delivery
Example: Adding a Filter
// 1. Define your filter function
const filter = `
function main(stream) {
const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
const transfers = [];
for (const blockLogs of stream.data) {
for (const receiptLogs of blockLogs) {
for (const log of receiptLogs) {
if (log.topics && log.topics[0] === TRANSFER_TOPIC && log.topics.length === 3) {
transfers.push({
token: log.address,
from: '0x' + log.topics[1].slice(26),
to: '0x' + log.topics[2].slice(26),
value: log.data
});
}
}
}
}
return transfers.length > 0 ? transfers : null;
}
`;
// 2. Base64 encode the filter
const encodedFilter = Buffer.from(filter).toString('base64');
// 3. Include in your create/update request
const streamConfig = {
name: "erc20-transfers",
network: "ethereum-mainnet",
dataset: "logs",
filter_function: encodedFilter,
// ... other config
};
You can test your filter before deploying using the Test Filter endpoint. For more filter examples and patterns, see Filter Functions.
Response
All responses are returned as JSON. On success, the API returns the created stream object with a unique id and timestamps.
{
"id": "stream_abc123",
"name": "ethereum-blocks",
"network": "ethereum-mainnet",
"dataset": "block",
"region": "usa_east",
"dataset_batch_size": 1,
"elastic_batch_enabled": true,
"destination": "webhook",
"destination_attributes": {
"url": "https://your-endpoint.example.com/webhook",
"compression": "none",
"max_retry": 3,
"retry_interval_sec": 1,
"post_timeout_sec": 10,
"mtls": true,
"security_token": "generated_token_here"
},
"status": "active",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
Error Response
If a request fails, the API returns an error object with a message and status code.
{
"error": "Invalid API key",
"status": 401
}
HTTP Status Codes
The API returns standard HTTP status codes to indicate the success or failure of a request.
| Status Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid or missing API key |
| 404 | Not Found - Stream does not exist |
| 422 | Unprocessable Entity - Validation error |
| 500 | Internal Server Error |
Supported Networks
Streams supports 60+ blockchain networks including Ethereum, Solana, Bitcoin, Arbitrum, Base, Polygon, and more. See Supported Chains for the complete list with available data schemas.
OpenAPI Specification
The complete OpenAPI specification is available for generating client libraries or importing into API tools:
https://api.quicknode.com/streams/rest/openapi.json
Related Resources
- Quickstart Guide - Create your first stream
- Filter Functions - Transform data before delivery
- Destinations - Supported delivery targets
- Data Sources - Available datasets by chain