Webhooks
Last updated: March 27, 2026
1. Overview
Webhooks deliver real-time notifications when events occur in Arkova. Instead of polling the API, your server receives an HTTPS POST the moment something important happens.
- HTTPS-only delivery (enforced at database level)
- Every delivery is signed with HMAC-SHA256 for authenticity verification
Note
Webhooks are available on all plans. Configure them in Settings → Webhooks.
2. Setup
- Navigate to Settings → Webhooks in the Arkova dashboard
- Click "Add Endpoint"
- Enter your HTTPS endpoint URL
- Select which events to subscribe to
- Copy your webhook signing secret (shown once)
Important
Your endpoint must respond with a
2xx status within 30 seconds. Non-2xx responses trigger retries.3. Event Types
| Event | Trigger | Description |
|---|---|---|
anchor.created | New credential created | Fires when an anchor record is created |
anchor.secured | Network confirmation | Fires when the anchor transaction is confirmed in a block |
anchor.revoked | Credential revoked | Fires when a credential is revoked by the owner |
anchor.verified | Verification lookup | Fires when someone verifies the credential (optional, high volume) |
attestation.created | New attestation | Fires when an attestation claim is created |
attestation.revoked | Attestation revoked | Fires when an attestation is revoked |
4. Payload Format
Every webhook delivery sends a JSON body with the following shape:
json
{
"event": "anchor.secured",
"timestamp": "2026-03-15T14:30:00Z",
"data": {
"public_id": "ARK-2026-00091",
"status": "SECURED",
"bitcoin_block": 204567,
"network_receipt_id": "b8e381df09ca404e...",
"issuer_name": "University of Michigan",
"credential_type": "DIPLOMA"
},
"idempotency_key": "wh_evt_abc123def456"
}Headers included on every delivery:
X-Arkova-Signature— HMAC-SHA256 signature of the payload bodyX-Arkova-Timestamp— ISO 8601 UTC timestampX-Arkova-Event— Event type (e.g.,anchor.secured)
5. Signature Verification
Important
Always verify webhook signatures. Reject unsigned or incorrectly signed payloads.
Node.js / TypeScript
typescript
import crypto from 'crypto';
function verifySignature(
payload: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Python
python
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)6. Retry Policy
| Attempt | Delay | Total Elapsed |
|---|---|---|
| 1 | Immediate | 0 |
| 2 | 1 minute | 1 min |
| 3 | 5 minutes | 6 min |
| 4 | 30 minutes | 36 min |
| 5 | 2 hours | ~2.5 hours |
- After all 5 attempts are exhausted, the event goes to a dead letter queue (retained 30 days)
- Manual replay is available from the dashboard
- Consecutive failures trip a circuit breaker — the endpoint is disabled and probed after a cooldown period
- Rate limit: 100 deliveries/minute per organization
7. Best Practices
- Return
200quickly, then process async — don't do heavy work in the handler - Use the
idempotency_keyto deduplicate — the same event may be delivered more than once - Verify signatures on every request — never trust unverified payloads
- Use a queue (Redis, SQS) for processing — decouple receipt from handling
- Monitor your endpoint's error rate in the Arkova dashboard
- Set up alerting for webhook failures