Skip to main content

Overview

Multi-wallet webhooks let a single subscription monitor up to 100 EVM wallet addresses for ERC-20 transfer activity on Base. Instead of creating one subscription per address, you create one subscription and pass a list of addresses. Events arrive with ~2s average freshness from chain tip.
Multi-wallet webhooks are live in production (API-only). Portal interface support is coming soon.
Multi-wallet webhooks cover ERC-20 token transfers only (to and from). Native ETH transfers are not currently supported.

When to use this

ScenarioUse wallet.activity.multi
Exchange deposit monitoring✅ Watch hundreds of user deposit addresses
Portfolio tracker✅ Track all user wallets under one project
Payment wallet✅ Monitor incoming transfers across a fleet of addresses
Agentic / automation use cases✅ React to transfers on a dynamic set of addresses
Single address monitoringUse wallet.activity.detected instead

Prerequisites

Sign up at portal.cdp.coinbase.com, then navigate to API Keys and select Create API key under the Secret API Keys tab.
  1. Enter an API key nickname (restrictions are optional)
  2. Click Create
  3. Secure your API Key ID and Secret in a safe location
You’ll need an HTTPS URL to receive webhook events. For quick testing, webhook.site gives free temporary URLs instantly.For production, use your own HTTPS endpoint.
Install cdpcurl to make authenticated requests to CDP APIs:
# With Homebrew
brew tap coinbase/cdpcurl && brew install cdpcurl

# Or with Go
go install github.com/coinbase/cdpcurl@latest

1. Construct subscription payload

Create a JSON payload with event type wallet.activity.multi and a wallet_addresses label containing a comma-separated list of EVM addresses.
multi-wallet.json
{
  "description": "Multi-wallet ERC-20 monitor",
  "eventTypes": [
    "wallet.activity.multi"
  ],
  "target": {
    "url": "https://your-webhook-url.com",
    "method": "POST"
  },
  "labels": {
    "wallet_addresses": "0xAddress1,0xAddress2,0xAddress3",
    "network": "base-mainnet"
  },
  "isEnabled": true
}

Configuration fields

FieldDescriptionRequiredNotes
target.urlYour webhook endpoint URLYesMust be a valid HTTPS URL
labels.wallet_addressesComma-separated list of EVM addresses to monitorYesUp to 100 addresses per subscription
labels.networkNetwork nameNobase-mainnet (default) or base-sepolia
eventTypesMust be ["wallet.activity.multi"]Yes
isEnabledEnable/disable webhookNoDefaults to true
target.headersCustom HTTP headersNoObject with header key-value pairs
The 100-address cap is per subscription. You can create multiple subscriptions to monitor more addresses.

2. Create subscription

cdpcurl -X POST \
  -i "YOUR_API_KEY_ID" \
  -s "YOUR_API_KEY_SECRET" \
  "https://api.cdp.coinbase.com/platform/v2/data/webhooks/subscriptions" \
  -d '{
  "description": "Multi-wallet ERC-20 monitor",
  "eventTypes": ["wallet.activity.multi"],
  "target": {
    "url": "https://your-webhook-url.com",
    "method": "POST"
  },
  "labels": {
    "wallet_addresses": "0xAddress1,0xAddress2,0xAddress3",
    "network": "base-mainnet"
  },
  "isEnabled": true
}'
You should see a 201 Created response with a body like:
response.json
{
  "createdAt": "2026-04-15T10:00:00.000000Z",
  "description": "Multi-wallet ERC-20 monitor",
  "eventTypes": [
    "wallet.activity.multi"
  ],
  "isEnabled": true,
  "labels": {
    "project": "<YOUR_CDP_PROJECT_ID>",
    "wallet_addresses": "0xAddress1,0xAddress2,0xAddress3",
    "network": "base-mainnet"
  },
  "metadata": {
    "secret": "<SECRET_FOR_WEBHOOK_VERIFICATION>"
  },
  "subscriptionId": "<YOUR_SUBSCRIPTION_ID>",
  "target": {
    "url": "https://your-webhook-url.com"
  }
}

3. Receive and handle events

When any ERC-20 transfer involves one of your monitored addresses, your endpoint receives a wallet.activity.multi event. The payload includes a direction field indicating whether your address was the sender, receiver, or both.
event-payload.json
{
  "id": "evt_1a2b3c4d5e6f",
  "type": "wallet.activity.multi",
  "createdAt": "2026-04-15T10:01:00.000000Z",
  "data": {
    "subscriptionId": "<YOUR_SUBSCRIPTION_ID>",
    "network": "base-mainnet",
    "matchedAddress": "0xAddress1",
    "direction": "to",
    "transactionHash": "0xabc123...",
    "blockNumber": 40000000,
    "logIndex": 12,
    "contractAddress": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
    "from": "0xAddress2",
    "to": "0xAddress1",
    "value": "5000000"
  }
}
value is the raw token amount with no decimal adjustment. For a 6-decimal token like USDC, 5000000 equals $5.00.

Direction values

ValueMeaning
toOne of your addresses received the transfer
fromOne of your addresses sent the transfer
bothBoth from and to are in your address list

Manage your subscription

To list, update, or delete your subscription, use the same endpoints described in the Webhooks Quickstart. When updating, pass the full revised wallet_addresses list in the labels field.

Limits and rate limiting

  • Address cap: up to 100 addresses per subscription
  • Rate limit: 2 webhook events per second per project. Events that exceed this limit may not be delivered. The rate limit is subject to change.
  • Freshness: ~2s average latency from chain tip to delivery
  • Supported networks: Base mainnet, Base Sepolia
  • Delivery guarantees: at-least-once, with retries and DLQ via the Webhooks 2.0 stack

Verify Signatures

Validate that events are coming from Coinbase

Single-wallet webhooks

Track a single CDP Server Wallet address with wallet.activity.detected

REST API Reference

Full reference for all webhook endpoints and options

Webhooks Overview

Delivery guarantees, use cases, and supported networks