Set Up Webhooks

Configure webhooks to receive real-time notifications when objects change state.

What You'll Build

Webhooks let your server receive real-time HTTP callbacks when events occur in Dual, like object transfers, property changes, or new mints. In this tutorial you'll register a webhook endpoint, configure event filters, and handle incoming payloads.

Step 1, Create Your Endpoint

Set up an HTTPS endpoint on your server that accepts POST requests. Every webhook handler should verify the HMAC-SHA256 signature before processing, this ensures the request genuinely came from Dual.

javascript
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = process.env.DUAL_WEBHOOK_SECRET;
function verifySignature(body, timestamp, signature) {
const message = \`\${timestamp}.\${body}\`;
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(message)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
app.post('/webhooks/dual', (req, res) => {
const sig = req.headers['x-dual-signature'];
const ts = req.headers['x-dual-timestamp'];
if (!sig || !ts || !verifySignature(JSON.stringify(req.body), ts, sig)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = req.body;
console.log('Event:', event.event_type);
console.log('Object:', event.object_id);
console.log('Data:', event.payload);
res.status(200).json({ received: true });
});
app.listen(3000, () => console.log('Webhook server on :3000'));

Security: Your webhook secret is in your org settings under Developer → Webhook Secret. Never hardcode it, use environment variables.

Step 2, Register the Webhook

Tell Dual to send events to your endpoint:

bash
curl -X POST https://api-testnet.dual.network/webhooks \\
-H "Authorization: Bearer $DUAL_TOKEN" \\
-H "Content-Type: application/json" \\
-d '{
"webhook": {
"url": "https://your-server.com/webhooks/dual",
"events": ["object.transferred", "object.updated"],
"active": true
}
}'

Step 3, Test with a Transfer

Transfer an object to trigger a webhook delivery:

bash
curl -X POST https://api-testnet.dual.network/ebus/actions \\
-H "Authorization: Bearer $DUAL_TOKEN" \\
-H "Content-Type: application/json" \\
-d '{
"action_name": "Transfer",
"object_id": "your-object-id",
"new_owner": "recipient-wallet"
}'

Within seconds your endpoint should receive a POST with a payload like:

json
{
"event_type": "object.transferred",
"object_id": "abc-123",
"timestamp": "2026-03-13T10:30:00Z",
"payload": {
"previous_owner": "wallet-a",
"new_owner": "wallet-b"
}
}

Step 4, Manage Your Webhooks

List all registered webhooks:

bash
curl https://api-testnet.dual.network/webhooks \\
-H "Authorization: Bearer $DUAL_TOKEN"

Delete a webhook by ID:

bash
curl -X DELETE https://api-testnet.dual.network/webhooks/{webhookId} \\
-H "Authorization: Bearer $DUAL_TOKEN"

Retry Policy: Dual retries failed webhook deliveries with exponential backoff (1s, 5s, 30s, 5m). After 5 consecutive failures, the webhook is automatically deactivated. Re-enable it via PATCH /webhooks/{id}.

What's Next?

Ready to add monetization? Head to Integrate Payments.