GETTING STARTED

Introduction

What this platform does

Contract Webhook API is a managed infrastructure service that connects your applications to on-chain smart contract events via reliable HTTP webhooks. You register a contract address and ABI, specify which events to listen for, and we deliver decoded event payloads to your webhook endpoint — with persistence, retries, and guaranteed delivery.

The problem space

Why on-chain event consumption is fragile

Listening to blockchain events sounds simple until it isn't. RPC providers drop WebSocket connections without warning. Nodes fall behind, return stale data, or rate-limit you at the worst possible moment. Your listener crashes at 3am and misses a week of transfers before anyone notices.

Why listeners, RPCs, and retries fail in practice

Most teams start with ethers.js or web3.js event listeners. They work great in development. Then production happens: the RPC endpoint goes down, the listener process gets OOM-killed, or the database transaction fails mid-processing. Suddenly you're writing retry logic, checkpoint persistence, reconnection handlers, and dead letter queues. You've built half an event-sourcing system when you just wanted to track token transfers.

Why this keeps showing up across teams

Every team building on-chain integrations eventually hits the same wall. Some build custom indexers. Some pay for expensive indexing services that do far more than they need. Some accept data loss as a cost of doing business. None of these are good options for teams that just need reliable event delivery without the infrastructure overhead.

Design philosophy

  • Events are persisted before delivery — We capture and store events before attempting delivery. If your endpoint is down, events queue up safely.
  • Failures are expected, not exceptional — Every delivery attempt is tracked. Retries are automatic. No silent failures.
  • Delivery is at-least-once — You may receive the same event more than once. Design your handlers to be idempotent.
  • Correctness over optimism — We wait for block confirmations before delivery. We don't guess. We verify.

What this platform does NOT do

  • No transactions — We don't send transactions on your behalf
  • No wallets — We don't manage or store private keys
  • No signing — We don't sign anything with your credentials
  • No general-purpose indexing — We deliver events, not historical blockchain state

After this section, no more philosophy. Just mechanics.

GETTING STARTED

Quick Start

The fastest possible success path. If you only read this section and nothing else, you should still succeed.

Step 1: Create an API key

Where: Dashboard → API Keys → Create New Key

Header format:

HTTP Header
Authorization: Bearer YOUR_API_KEY

Step 2: Create a subscription with webhook

POST /api/subscriptions
{
  "chainId": 1,
  "contractAddress": "0x1234...abcd",
  "abi": [...],
  "eventFilters": ["Transfer", "Approval"],  // Optional
  "webhookUrl": "https://yourapp.com/webhook",
  "enableSignature": true  // Optional, enabled by default
}
  • chainId — The blockchain network ID (1 = Ethereum mainnet)
  • contractAddress — The smart contract to monitor
  • abi — Contract ABI (full or event-only)
  • eventFilters — Optional. Specific event names to capture
  • webhookUrl — Your HTTPS endpoint that will receive events

The response will contain your subscription ID and a signing secret (if enabled). Save this secret! It won't be shown again.

Step 3: Receive events

Your webhook will receive POST requests with this payload:

Example Webhook Payload
{
  "id": "evt_xyz789",
  "subscriptionId": "sub_abc123",
  "chainId": 1,
  "blockNumber": 19234567,
  "transactionHash": "0xabc...def",
  "eventName": "Transfer",
  "args": {
    "from": "0x1111...1111",
    "to": "0x2222...2222",
    "value": "1000000000000000000"
  },
  "timestamp": "2026-01-28T08:30:00Z"
}

Respond with a 2xx status code to acknowledge receipt.

REFERENCE

Authentication

API Keys

Creating keys

Navigate to Dashboard → API Keys → Create New Key. Keys are shown once at creation. Store them securely.

Using keys

HTTP Request
curl -X GET https://api.contractwebhook.io/api/subscriptions \
  -H "Authorization: Bearer sk_live_abc123..."

Rotating keys

Create a new key before revoking the old one. Update your application, verify it works, then revoke the old key from the dashboard.

REFERENCE

Subscriptions

Creating a subscription

Required fields

FieldTypeDescription
chainIdnumberNetwork ID (1=Ethereum, 137=Polygon, etc.)
contractAddressstringContract address to monitor
abiarrayContract ABI for event decoding
webhookUrlstringHTTPS endpoint to receive events

Optional fields

FieldTypeDescription
eventFiltersstring[]Event names to capture. Empty = all events
startBlocknumberBlock to start listening from

ABI handling

Supported formats

  • Full contract ABI (standard Solidity compiler output)
  • Event-only ABI (array of event definitions)
  • Human-readable ABI ("event Transfer(address,address,uint256)")

What happens on decode failure

If an event cannot be decoded with the provided ABI, we deliver the raw log data with "decoded": false. Your handler receives the event but must decode it manually.

Event filtering

By event name

Filter specific events
{
  "eventFilters": ["Transfer", "Approval"]
}

Why filters matter

High-activity contracts can emit thousands of events per hour. Filtering reduces noise, lowers latency, and keeps your webhook queue focused on events you actually care about.

REFERENCE

Webhooks

Delivery behavior

At-least-once delivery

Every event is delivered at least once. Network issues, timeouts, or your endpoint returning errors trigger retries. Design handlers to be idempotent using the id field.

No strict ordering guarantees

Events are delivered in approximate order but not strictly sequential. If ordering matters, use blockNumber and logIndex to sort on your end.

Payload format

JSON schema

FieldTypeDescription
idstringUnique event ID (for deduplication)
subscriptionIdstringYour subscription reference
chainIdnumberNetwork the event occurred on
blockNumbernumberBlock containing the event
transactionHashstringTransaction that emitted the event
logIndexnumberPosition within the block's logs
eventNamestringDecoded event name
argsobjectDecoded event arguments
timestampstringISO 8601 delivery timestamp

Example payload

Webhook POST Body
{
  "id": "evt_01HN4X...",
  "subscriptionId": "sub_abc123",
  "chainId": 1,
  "blockNumber": 19234567,
  "transactionHash": "0xabc123...",
  "logIndex": 42,
  "eventName": "Transfer",
  "args": {
    "from": "0x1111...1111",
    "to": "0x2222...2222", 
    "value": "1000000000000000000"
  },
  "timestamp": "2026-01-28T09:30:00.000Z"
}

Signing & verification

How to verify

If you provided a signing secret, each request includes an X-Webhook-Signature header:

Node.js Verification
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Why you should

Without verification, anyone who discovers your webhook URL can send fake events. Always verify in production.

Retries

When retries happen

  • Your endpoint returns a non-2xx status code
  • Connection timeout (30 seconds)
  • Network error (DNS failure, connection refused)

When they stop

After 5 attempts with exponential backoff (1min, 5min, 30min, 2hr, 12hr). Failed events are marked as dead and visible in your dashboard for manual replay.

REFERENCE

Replays

When to replay

  • Webhook downtime — Your endpoint was down and events failed delivery
  • Consumer bugs — Your handler had a bug that caused incorrect processing

How to replay

POST /api/replays
{
  "subscriptionId": "sub_abc123",
  "fromTimestamp": "2026-01-27T00:00:00Z",
  "toTimestamp": "2026-01-28T00:00:00Z"
}
  • Time range — Specify start and end timestamps for the replay window
  • Subscription scope — Replays are scoped to a single subscription

All failed or delivered events within the window will be reset to PENDING status and redelivered.

What replays guarantee

  • Same payloads — You receive the exact same event data as the original delivery
  • New delivery attempts — Each replayed event counts as a fresh delivery with its own retry policy
REFERENCE

Rate Limits

API limits

EndpointLimit
All API endpoints100 requests/minute per API key
Subscription creation10 per minute
Replay requests5 per hour

Webhook throughput expectations

PlanEvents/second
Free10 events/sec
Pro100 events/sec
EnterpriseCustom

Events exceeding your throughput limit are queued, not dropped. Delivery is delayed but guaranteed.

REFERENCE

Errors & Debugging

API errors

Status codes

CodeMeaning
400Invalid request body or parameters
401Missing or invalid API key
403API key lacks permission for this action
404Resource not found
429Rate limit exceeded
500Internal server error

Common causes

  • 400 on subscription creation — Invalid ABI format or unsupported chain ID
  • 401 on all requests — API key not in Authorization: Bearer format
  • 429 suddenly — Tight loop or retry storm. Add exponential backoff.

Delivery failures

What counts as failure

  • Non-2xx response from your endpoint
  • Request timeout (30 seconds)
  • Connection error (DNS, TLS, network)

How to inspect delivery attempts

Dashboard → Subscriptions → [Your Subscription] → Delivery Logs

Each attempt shows: timestamp, HTTP status, response body (first 1KB), and retry count.

REFERENCE

Security Notes

No private keys

We never ask for, store, or have access to your private keys. This service is read-only. We listen to public blockchain events and deliver them to you.

Signed webhooks

Always configure a webhook secret and verify signatures. This prevents attackers from injecting fake events into your system.

Recommended practices

  • Use HTTPS endpoints only (we reject HTTP URLs)
  • Rotate API keys periodically
  • Use separate API keys for different environments (dev, staging, prod)
  • Validate event data before processing (check contract address, chain ID)
  • Implement idempotency using event IDs
REFERENCE

FAQ

Can I receive events from multiple contracts in one subscription?

No. One subscription = one contract. Create multiple subscriptions for multiple contracts.

How fast are events delivered after they're emitted on-chain?

Typically under 500ms after block confirmation. We wait for 2-12 confirmations depending on the chain to avoid delivering events from reorged blocks.

What happens if my webhook is down for a week?

Events queue up. When your endpoint comes back, we deliver them in order with standard retry logic. Use replays for bulk re-processing if needed.

Do you support testnets?

Yes. Goerli, Sepolia, Mumbai, and other major testnets are supported. Same API, same reliability.

Can I filter by specific argument values (e.g., transfers to my address)?

Not yet. Current filtering is by event name only. Topic-based filtering is on the roadmap.

What's the maximum payload size?

Events with decoded arguments exceeding 1MB are truncated. Raw log data is always included for large events.

How do I handle duplicate events?

Use the id field. Store processed event IDs and skip duplicates. This is required for at-least-once delivery semantics.