Webhook Integration
This guide explains how to set up and handle webhooks for Xellar's notification service.
Setting Up Your Webhook
Configure Webhook URL
- Navigate to the "Developer" section in your Xellar dashboard
- Select "Webhook" from the menu
- Enter your webhook URL in the "Notification Webhook URL" field
- Click "Save" to store your configuration
Security
Signature Verification
All webhook requests include a signature in the x-xellar-signature
header. You should always verify this signature to ensure the request came from Xellar.
Here's how to verify the signature:
const crypto = require('crypto');
const verifyWebhookSignature = (signature, body) => {
const publicKey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1Db3dCUVlESzJWd0F5RUFsRHUzVWMzenFvTGhhd1dHQnBuMU5XK0E4WFUwY2swSGpqdUFmSDZDekZjPQ0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tDQo="
// Use this public key to verify webhooks from Xellar
const verify = crypto.verify(
null,
Buffer.from(JSON.stringify(body)),
Buffer.from(publicKey, 'base64'),
Buffer.from(signature, 'base64')
);
return verify;
};
// Example usage in Express.js
app.post('/webhook', express.json(), (req, res) => {
const signature = req.headers['x-xellar-signature'];
if (!verifyWebhookSignature(signature, req.body)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook data
console.log('Verified webhook data:', req.body);
res.status(200).send('OK');
});
Webhook Data Format
EVM Networks
Webhook payload for EVM-compatible networks:
interface EVMWebhookData {
id: string;
createdAt: string;
message: string;
data: {
rawData: {
blockchain_type: string,
value: string,
chainId: number,
status: boolean,
transactionHash: string,
transactionIndex: number,
blockHash: string,
blockNumber: number,
from: string,
to: string,
contractAddress?: string,
cumulativeGasUsed: number,
gasUsed: number,
logs: {
address: string,
data: string,
topics: string[],
logIndex: number,
transactionIndex: number,
transactionHash: string,
blockHash: string,
blockNumber: number,
}[],
logsBloom: string,
events?: {
[eventName: string]: {
event: string,
address: string,
returnValues: any,
logIndex: number,
transactionIndex: number,
transactionHash: string,
blockHash: string,
blockNumber: number,
raw?: {
data: string,
topics: any[]
},
},
},
},
filteredData: {
from: string,
to: string,
value: string,
txHash: string,
chainId: number,
blockchain_type: string,
tokenAddress: string,
},
};
}
TRON Network
Webhook payload for TRON network:
interface TronWebhookData {
id: string;
createdAt: string;
message: string;
data: {
rawData: {
status: boolean,
transactionHash: string,
transactionIndex: number,
blockHash: string,
blockNumber: number,
from: string,
to: string,
type: string,
contractAddress?: string,
cumulativeGasUsed: string,
effectiveGasPrice: string,
gasUsed: string,
logs: {
address: string,
data: string,
topics: string[],
logIndex: number,
removed: boolean,
transactionIndex: number,
transactionHash: string,
blockHash: string,
blockNumber: number,
}[],
logsBloom: string,
},
filteredData: {
from: string,
to: string,
value: string,
txHash: string,
chainId: number,
blockchain_type: string,
tokenAddress: string,
tokenSymbol: string,
},
};
}
Example Webhook Responses
Token Transfer (EVM)
{
"id": "webhook_1234567890",
"createdAt": "2024-03-20T10:30:00Z",
"message": "ERC20 token transfer detected",
"data": {
"rawData": {
"blockchain_type": "evm",
"value": "0",
"chainId": 1,
"status": true,
"transactionHash": "0x123...",
"from": "0xabc...",
"to": "0xdef...",
"contractAddress": "0x789...",
"logs": [
{
"address": "0x789...",
"data": "0x000000000000000000000000000000000000000000000000000000174876e800",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000abc...",
"0x000000000000000000000000def..."
],
"logIndex": 0,
"transactionIndex": 5,
"transactionHash": "0x123...",
"blockHash": "0x456...",
"blockNumber": 12345678
}
],
"events": {
"Transfer": {
"event": "Transfer",
"address": "0x789...",
"returnValues": {
"from": "0xabc...",
"to": "0xdef...",
"value": "100000000000"
},
"logIndex": 0,
"transactionIndex": 5,
"transactionHash": "0x123...",
"blockHash": "0x456...",
"blockNumber": 12345678
}
}
},
"filteredData": {
"from": "0xabc...",
"to": "0xdef...",
"value": "100",
"txHash": "0x123...",
"chainId": 1,
"blockchain_type": "ethereum",
"tokenAddress": "0x789..."
}
}
}
Native Transfer (TRON)
{
"id": "webhook_0987654321",
"createdAt": "2024-03-20T10:35:00Z",
"message": "Native TRX transfer detected",
"data": {
"rawData": {
"status": true,
"transactionHash": "123abc...",
"from": "T123...",
"to": "T456...",
"type": "Transfer",
"value": "1000000",
"blockNumber": 987654,
"blockHash": "block123...",
"transactionIndex": 3,
"cumulativeGasUsed": "20000",
"effectiveGasPrice": "420",
"gasUsed": "20000",
"logs": [],
"logsBloom": "0x00..."
},
"filteredData": {
"from": "T123...",
"to": "T456...",
"value": "1.0",
"txHash": "123abc...",
"chainId": 0,
"blockchain_type": "tron",
"tokenAddress": null,
"tokenSymbol": "TRX"
}
}
}
Best Practices
-
Signature Verification
- Always verify the webhook signature
- Store the public key securely
- Reject requests with invalid signatures
-
Error Handling
- Implement proper error handling
- Log invalid requests for debugging
- Set up monitoring for webhook failures
-
Processing
- Process webhooks asynchronously
- Implement idempotency checks
- Store raw webhook data before processing
-
Response
- Respond quickly (within 5 seconds)
- Return 2xx status code for successful receipt
- Handle retries appropriately
Troubleshooting
Common Issues
-
Invalid Signature
- Verify you're using the correct public key
- Check signature header name is correct
- Ensure body is not modified before verification
-
Missing Events
- Verify notification service is enabled
- Check wallet notification status
- Confirm supported network
Need help? Contact our support team or check our documentation for more information.