Streams Beta
Streams deliver onchain events to your app in real-time. Define filters for the activity you care about — transfers, contract calls, deployments, token events — and secondlayer pushes matching events to your endpoint as each block is processed.
Delivery is at-least-once. Handlers should be idempotent.
Streams deliver matching on-chain events (transfers, contract calls, mints, etc.) to your endpoint as each block is processed. Define filters, point at a URL, and secondlayer handles the rest. Delivery is at-least-once.
Ensure setup (skip any step already done, use the project's package manager):
- Skill: run the `skills` npm package to install — e.g. `npx|bunx|pnpm dlx skills add ryanwaits/secondlayer --skill secondlayer -y`
- CLI: `@secondlayer/cli` installed globally
- Auth: `secondlayer auth login`
/secondlayer Help me create a stream. Ask me:
1. What blockchain events do I want to track?
2. Where should deliveries be sent (endpoint URL)?
3. Any filter constraints (contract, sender, amount)?
Create the stream config and register it.Getting started
Create a stream via the SDK. You'll get back a signing secret for verifying deliveries.
import { SecondLayer } from "@secondlayer/sdk"
const client = new SecondLayer({ apiKey: "sk-sl_..." })
const { stream, signingSecret } = await client.streams.create({
name: "my-stream",
endpointUrl: "https://example.com/streams",
filters: [
{ type: "stx_transfer" },
],
})Filters
Each stream takes an array of filters. A block matches if any filter matches. Filters narrow by type and optional fields like contract, sender, recipient, or amount.
filters: [
// STX transfers over 1 STX
{ type: "stx_transfer", minAmount: 1_000_000 },
// Calls to a specific contract function
{
type: "contract_call",
contractId: "SP1234...::marketplace",
functionName: "list-asset",
},
// NFT mints from a specific collection
{
type: "nft_mint",
assetIdentifier: "SP1234...::my-nft::nft-token",
},
// Contract deployments by a specific address
{ type: "contract_deploy", deployer: "SP1234..." },
// Print events matching a topic
{ type: "print_event", contractId: "SP1234...::token", topic: "transfer" },
]Delivery payload
Each delivery posts a JSON payload to your endpoint URL with the matching block, transactions, and events.
{
streamId: "uuid",
streamName: "my-stream",
block: {
height: 150000,
hash: "0x...",
parentHash: "0x...",
burnBlockHeight: 800000,
timestamp: 1710000000,
},
matches: {
transactions: [{
txId: "0x...",
type: "stx_transfer",
sender: "SP1234...",
status: "success",
contractId: null,
functionName: null,
}],
events: [{
txId: "0x...",
eventIndex: 0,
type: "stx_transfer",
data: { ... },
}],
},
isBackfill: false,
deliveredAt: "2026-03-10T00:00:00Z",
}Management
Streams can be enabled, disabled, updated, and deleted. Use partial IDs for convenience — the SDK resolves them automatically.
// List streams
const { streams } = await client.streams.list({ status: "active" })
// Get by ID (supports partial IDs)
const stream = await client.streams.get("a1b2c3")
// Update
await client.streams.update("a1b2c3", {
endpointUrl: "https://new-endpoint.com/streams",
filters: [{ type: "stx_transfer", minAmount: 5_000_000 }],
})
// Enable / disable
await client.streams.enable("a1b2c3")
await client.streams.disable("a1b2c3")
// Bulk pause / resume all streams
await client.streams.pauseAll()
await client.streams.resumeAll()
// Rotate signing secret
const { secret } = await client.streams.rotateSecret("a1b2c3")
// Delete
await client.streams.delete("a1b2c3")Replay
Replay historical blocks through a stream. The delivery payload includes isBackfill: true for replayed deliveries. Maximum 10,000 blocks per replay request.
// Via SDK — replay blocks 150,000 to 151,000
await client.streams.replay("a1b2c3", {
startBlock: 150_000,
endBlock: 151_000,
})
// Replay failed deliveries
await client.streams.replayFailed("a1b2c3")CLI
Manage streams from the command line. The CLI generates config files and registers them with the API.
# Generate a new stream config
sl streams new my-stream
# Register from config file
sl streams register ./my-stream.json
# List / get / delete
sl streams ls
sl streams get a1b2c3
sl streams delete a1b2c3
# View delivery logs
sl streams logs a1b2c3
# Replay a block range
sl streams replay a1b2c3 --start 150000 --end 151000
# Rotate signing secret
sl streams rotate-secret a1b2c3