Skip to main content

Webhooks API

Receive real-time HTTP callbacks when reputation scores change.

Register Webhook

POST /api/v1/webhooks

Requires API key (X-API-Key header). Free tier cannot use webhooks.

{
"url": "https://your-app.com/webhook/crowdproof",
"walletAddress": "0x1234..."
}

Validation

FieldRules
urlRequired, valid URL, max 2,000 characters
walletAddressOptional, valid Ethereum address (filter events to this address)

Tier Limits

TierMax Webhooks
FreeNot available (403)
Starter3
Growth10
Enterprise50

Response

{
"id": "a1b2c3d4-...",
"url": "https://your-app.com/webhook/crowdproof",
"walletAddressFilter": "0x1234...",
"secret": "whsec_abc123...",
"createdAt": "2026-02-27T12:00:00Z"
}
important

Save the secret — it's only returned once. You'll need it to verify webhook signatures.


List Webhooks

GET /api/v1/webhooks

Requires API key.

Response

{
"count": 2,
"webhooks": [
{
"id": "a1b2c3d4-...",
"url": "https://your-app.com/webhook/crowdproof",
"walletAddressFilter": "0x1234...",
"isActive": true,
"consecutiveFailures": 0,
"lastDeliveryAt": "2026-02-27T12:00:00Z",
"createdAt": "2026-02-27T11:00:00Z"
}
]
}

Get Webhook

GET /api/v1/webhooks/{id}

Requires API key. Returns the full webhook subscription object.


Delete Webhook

DELETE /api/v1/webhooks/{id}

Requires API key. Returns 204 No Content.


Webhook Delivery

When a score changes, CrowdProof sends a POST to your registered URL:

{
"event": "score.updated",
"timestamp": "2026-02-27T12:00:00Z",
"data": {
"walletAddress": "0x1234...",
"category": "DEFI_LENDING",
"oldScore": 680,
"newScore": 720,
"tier": "Good"
}
}

Verifying Signatures

Every delivery includes an X-CrowdProof-Signature header with an HMAC-SHA256 signature:

X-CrowdProof-Signature: sha256=a1b2c3d4e5f6...

Verify it server-side:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expected}` === signature;
}

Auto-Disable

After 10 consecutive delivery failures, the webhook is automatically deactivated (isActive: false). Re-register to reactivate.