Query + Webhook Demo

From active queries to real-time push — a complete integration example

API Key signed queries, Webhook setup, receiver signature verification, and idempotent event handling — all on one page. Copy the sample code to integrate on-chain transactions, balances, and contract events into your system.

HMAC SigningGo SDKWebhook Verificationstable / pending
Integration Roadmap
Query for active lookups, Webhook for push on match.
4 steps
1

Create API Key

Generate key/secret for HMAC signing

2

Signed Query Calls

Query transactions, balances, internal transfers, and events

3

Configure Webhook URL

Select coin/token/contract event types

4

Verify & Process Events

Verify signature, idempotent storage by eventId

Create API Key
Create an API Key in your profile. Save key and secret — secret is used locally for signing only, never sent as a plain header.
Call Query API
Use HMAC signing to query indexed transactions, balances, internal transfers, and contract events.
Configure Webhook
Set receiver URL and event types, then import wallet, Token, or contract watch targets.
Verify & Store
Receiver validates X-Bot-Signature, then processes idempotently by eventId.
Go SDK & Runnable Examples
Module github.com/calmw/chainpulse; run sdk-go-example/query and webhook_receiver with go run. go.mod replaces to sdk/golang.
Open GitHub
Query API: Address Balances
Pass chainId matching the chain where the address was indexed (demo: 968). HMAC signs the full PATH_WITH_QUERY. Timestamps use YYYY-MM-DD HH:mm:ss; Go SDK needs FlexTime (v1.0.2+ or local replace).

cURL Example

curl -X GET 'https://query.chainpulse.cc/v1/addresses/0x0f4b9fC118DC2428745A10970F680ff06b0d5723/balances?chainId=968&consistency=stable&limit=20' \
  -H 'X-API-Key: ck_live_xxx' \
  -H 'X-API-Timestamp: 1779105954' \
  -H 'X-API-Nonce: 35a6a5094a1784b4dad9d8ff' \
  -H 'X-API-Signature: sha256=<hmac_signature>'

Node.js Signed Request

import crypto from "node:crypto"

const apiKey = process.env.CHAINPULSE_API_KEY!
const apiSecret = process.env.CHAINPULSE_API_SECRET!
const method = "GET"
const path = "/v1/addresses/0x0f4b9fC118DC2428745A10970F680ff06b0d5723/balances?chainId=968&consistency=stable&limit=20"
const timestamp = Math.floor(Date.now() / 1000).toString()
const nonce = crypto.randomBytes(12).toString("hex")

const signingString = [method, path, timestamp, nonce].join("\n")
const signature = "sha256=" + crypto
  .createHmac("sha256", apiSecret)
  .update(signingString)
  .digest("hex")

const response = await fetch("https://query.chainpulse.cc" + path, {
  headers: {
    "X-API-Key": apiKey,
    "X-API-Timestamp": timestamp,
    "X-API-Nonce": nonce,
    "X-API-Signature": signature,
  },
})

console.log(await response.json())

Go SDK Query (sdk-go-example/query)

github.com/calmw/chainpulse / sdk-go-example/query
// sdk-go-example/query — go.mod replace => ../../sdk/golang
package main

import (
  "context"
  "fmt"
  "log"
  "os"

  chainpulse "github.com/calmw/chainpulse"
)

func main() {
  client := chainpulse.NewClient(
    chainpulse.WithQueryBaseURL("https://query.chainpulse.cc"),
    chainpulse.WithAPIKey(os.Getenv("CHAINPULSE_API_KEY"), os.Getenv("CHAINPULSE_API_SECRET")),
  )

  params := chainpulse.QueryParams{
    ChainID:     968,
    Consistency: "stable",
    Limit:       20,
  }

  balances, err := client.ListAddressBalances(context.Background(), "0x0f4b9fC118DC2428745A10970F680ff06b0d5723", params)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Printf("%+v\n", balances)
}

// CHAINPULSE_CHAIN_ID=968 CHAINPULSE_TX_HASH=0xb9308cad0162f61d29b0fe0f892a83fcd62777f4a99a8c5abaf54eda94c2c131 go run .
Runnable Demo
sdk-go-example/query: CHAINPULSE_CHAIN_ID=968 for balances & internal tx; webhook_receiver: ngrok + whsec_ to receive pushes.
Security Boundary
Public Query API is read-only. Webhook verification must use the raw body — re-serialized JSON will fail signature check.
Push Timing
pending is faster but coin excludes internal transfers; use stable for crediting (includes internal_to). pending/stable are mutually exclusive per user.