pending briefly after all requirements are submitted, and ongoing monitoring can change a customer’s state at any time. See Capabilities and Requirements for the underlying lifecycle.
Setup
Prerequisites
A Secret API Key
A Secret API Key
Sign up at portal.cdp.coinbase.com, then navigate to API Keys and select Create API key under the Secret API Keys tab.
- Enter an API key nickname (restrictions are optional)
- Click Create
- Secure your API Key ID and Secret in a safe location
A webhook URL
A webhook URL
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.
CDP CLI
CDP CLI
The CDP CLI handles authentication and exposes webhook subscription endpoints as typed commands (
cdp data webhooks subscriptions create, list, update, delete). For raw HTTP, use cdp api.Event types
Subscribe to the customer event types relevant to your integration:| Event type | Description |
|---|---|
customers.capability.changed | One or more capability statuses changed for a customer. A single event can report several capabilities at once. |
customers.customer.deleted | The customer record was deleted. This transition is terminal. |
Create a webhook subscription
Configuration notes:target.urlshould be your HTTPS webhook endpoint that will receive the events.- You can set a
headersobject intargetif your URL requires specific headers. Pass it inline with'target.headers:={"custom-header":"value"}'. - Include every customer event type you want to receive so you do not miss a state change.
Manage subscriptions
Use thesubscriptionId from the response to view, update, or delete the subscription.
List all subscriptions
update is a full replace. Pass every field, including ones you aren’t changing:
Webhook signature verification
Use the standard CDP webhook verification flow. The same code works for all webhook event domains. See Verify signatures for the full step-by-step implementation.Event payloads
Coinbase POSTs a JSON body containing only the event-specific fields. There is no outer envelope (eventId, eventType, timestamp, or data wrapper) in the request body.
Routing and idempotency metadata arrive in HTTP headers instead:
| Header | Description |
|---|---|
X-Event-Id | Unique identifier for this delivery. Use it for idempotency. The same event may be delivered more than once. |
X-Event-Type | The event type string (for example, customers.capability.changed). |
X-Hook0-Signature | Signature for verifying the request. See Verify signatures. |
Example request
customers.capability.changed
Emitted when the status of one or more capabilities changes. Each change is a distinct entry in the capabilities array.
customers.customer.deleted
Emitted when the customer record is deleted. This transition is terminal.
Best practices
To ensure reliable webhook delivery:- Test endpoints locally before enabling subscriptions in production.
- Handle concurrent requests. Ensure your target URL can process multiple events simultaneously.
- Process events asynchronously. Return a
200response quickly and process the event in the background. - Use
X-Event-Idfor idempotency. The same event may be delivered more than once. - Monitor webhook receiver health. Track delivery success rates to your target URL.
- Set up subscription monitoring. Use a scheduled job (for example, cron or a systemd timer) to periodically call the List Subscriptions API and verify critical subscriptions have
isEnabled: true.
Subscriptions may be automatically disabled if your endpoint experiences sustained delivery failures (e.g., high failure rates, endpoint unavailability, or throughput issues). If this happens, fix the underlying endpoint issue and use the Update Subscription API to re-enable.