Webhooks — receive on-chain events

The demo doesn't host its own webhook receiver, but every Helius account gets unlimited webhooks on the free tier. Here's how to wire one up to your app.

Maintained by Helius · Last updated · View source

What you can subscribe to

  • Enhanced webhooks — parsed events: NFT sales, NFT bids, token swaps, transfers, listings, staking
  • Raw webhooks — every transaction touching one or more addresses
  • Discord webhooks — formatted Discord messages without writing code

Filter by program ID, account address, transaction type, or all of the above. See the full webhook docs for the event taxonomy.

Create a webhook

Via the dashboard or programmatically with the Helius SDK:

import { Helius } from "helius-sdk";

const helius = new Helius(process.env.HELIUS_API_KEY!);

await helius.createWebhook({
  webhookURL: "https://your-app.com/api/webhooks/helius",
  transactionTypes: ["NFT_SALE", "TOKEN_TRANSFER"],
  accountAddresses: ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
  webhookType: "enhanced",
  authHeader: process.env.WEBHOOK_AUTH_SECRET,
});

The authHeader value is sent as an Authorization: header on every delivery — verify it in your receiver to reject spoofed traffic.

Receiver — Next.js API route

// app/api/webhooks/helius/route.ts
import { NextRequest, NextResponse } from "next/server";

export async function POST(request: NextRequest) {
  // 1. Verify the secret you set on createWebhook
  const auth = request.headers.get("authorization");
  if (auth !== process.env.WEBHOOK_AUTH_SECRET) {
    return NextResponse.json({ error: "unauthorized" }, { status: 401 });
  }

  // 2. Handle the event(s) — Helius delivers an array
  const events = (await request.json()) as Array<{
    type: string;
    signature: string;
    timestamp: number;
    events: Record<string, unknown>;
  }>;

  for (const event of events) {
    // Persist, queue, fanout, etc.
    console.log(`[${event.type}] ${event.signature}`);
  }

  return NextResponse.json({ received: events.length });
}

Local testing

Use a tunnel like ngrok or localtunnel to expose your dev server. Set the webhook URL to the tunnel address and trigger events on devnet via the sandbox endpoints.

Retries and at-least-once delivery

Helius retries failed deliveries (non-2xx responses) with exponential backoff. Your receiver should be idempotent — deduplicate on signature to handle replays.

Webhooks vs. Laserstream vs. polling

  • Webhooks — push-based, easy, ~1–5 second latency, no infrastructure to maintain
  • Laserstream — pull-based WebSocket / gRPC, sub-50ms latency, requires running a consumer
  • Polling — only when neither of the above is viable; expensive and high-latency

Pricing

Standard webhooks are free on every Helius tier including the free plan. See /pricing.md.