Skip to main content

Use Case

You want to receive HTTP notifications whenever a specific ERC-20 token is transferred on Base Mainnet. This enables real-time alerting, event-driven workflows, or feeding data into systems that consume webhooks (Slack, PagerDuty, custom backends).

Pipeline Configuration

1

Create a new pipeline

In the GoldRush Platform, navigate to Manage Pipelines and click Create Pipeline. Name it transfer-alerts.
2

Configure the webhook destination

Select Webhook as the destination type and configure your endpoint:
destination:
  type: "webhook"
  url: "https://api.yourapp.com/webhooks/transfers"
  headers:
    Authorization: "Bearer ${WEBHOOK_TOKEN}"
    Content-Type: "application/json"
  batch_size: 1
  timeout_ms: 5000
  retry:
    max_attempts: 5
    backoff_ms: 2000
3

Select your source

Choose Base Mainnet as the chain and Transfers as the data type. This streams every token transfer event.
4

Add a SQL transform to filter

Filter to only USDC transfers on Base (contract 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913):
transforms:
  transfers: >
    SELECT block_height, block_signed_at, tx_hash, contract_address,
           from_address, to_address, amount
    FROM transfers
    WHERE contract_address = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
5

Deploy

Review and deploy. Your webhook endpoint begins receiving POST requests for each matching transfer.

Webhook Payload

Each transfer arrives as a JSON POST request:
{
  "project": "transfer-alerts",
  "stream": "transfers",
  "record": {
    "block_height": 28451023,
    "block_signed_at": "2025-03-18T14:22:05Z",
    "tx_hash": "0xabc123...",
    "contract_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "from_address": "0x1234...",
    "to_address": "0x5678...",
    "amount": "1000000000"
  }
}
The request includes an X-Idempotency-Key header for deduplication on your end.

Handling Idempotency

Every webhook request includes an X-Idempotency-Key header with a deterministic value based on the source record’s position. Store this key and check for duplicates before processing:
app.post('/webhooks/transfers', (req, res) => {
  const idempotencyKey = req.headers['x-idempotency-key'];

  // Check if already processed
  if (await cache.has(idempotencyKey)) {
    return res.status(200).json({ status: 'duplicate' });
  }

  // Process the transfer
  const { record } = req.body;
  await processTransfer(record);

  // Mark as processed
  await cache.set(idempotencyKey, true, { ttl: 86400 });

  res.status(200).json({ status: 'ok' });
});
Always return a 2xx status code promptly. The pipeline retries on 5xx and 429 responses with exponential backoff. A 4xx response (other than 429) causes the batch to be permanently skipped.

Retry Behavior

ResponsePipeline Action
2xxSuccess, move to next record
429Retry with Retry-After header if present, else exponential backoff
5xxRetry with exponential backoff
4xx (not 429)Permanent failure, skip and log

Production Tips

  • batch_size: 1 sends one transfer per HTTP request - simplest to handle. Increase to 5-10 for higher throughput if your endpoint supports batch payloads.
  • timeout_ms: Set this lower than your endpoint’s actual timeout to allow for retry overhead. 5,000 ms is a good default.
  • Filtering: The SQL transform runs before the webhook, so you only pay for HTTP requests on records that match your filter. Add multiple WHERE conditions to narrow further.