Webhooks allow your application to receive real-time notifications about events related to orders and transactions. This page explains how to configure, receive, and validate webhooks from the Two-Coin system.
To receive webhook notifications, you need to configure two things in your merchant settings:
Two-Coin sends webhook notifications when order statuses change. Currently, there is one webhook event type that covers all order status updates.
| Event Type | Description |
|---|---|
order | Fired when an order status changes (any status transition) |
The webhook payload includes the current order status, which can be one of:
createdOrder initially createdpendingWaiting for paymentprocessingPayment being processedholdOrder on holdcompleteSuccessfully completedfailedOrder failedexpiredOrder expiredrefundedOrder refundedAll webhook notifications are sent as HTTP POST requests with a JSON payload. The payload is wrapped in a typed structure that identifies the webhook type.
{
"type": "order_update",
"body": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"from_currency": 35,
"to_currency": 15,
"redirect_url": "https://provider.com/redirect",
"external_user_id": "user123",
"external_order_id": "order456",
"from_amount": "100.00",
"to_amount": "0.003",
"payment_method": "card",
"country_code": "US",
"state_code": "CA",
"wallet_address": "bc1q...",
"status": "complete",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:05:00Z",
"ip": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"extras": {}
}
}type: The webhook event type (currently "order_update")body: The actual webhook data, which varies by type. For order updates, contains the complete order information.For security reasons, you should always verify that webhook requests are coming from Two-Coin. Each webhook request includes signature headers that you can use for verification.
x-webhook-signature: HMAC-SHA256 signature (hex-encoded)x-webhook-timestamp: ISO 8601 formatted timestamp of webhook generation (e.g., "2024-01-15 14:30:00 UTC")x-webhook-merchant: Your merchant codeTo verify a webhook signature, you need to reconstruct the signed message and compare signatures:
merchant_code + unix_timestamp_seconds + payload_json// Node.js example
const crypto = require('crypto');
function verifyWebhook(req, webhookSigningKey) {
const signature = req.headers['x-webhook-signature'];
const timestampStr = req.headers['x-webhook-timestamp'];
const merchantCode = req.headers['x-webhook-merchant'];
const payload = JSON.stringify(req.body);
// Parse the ISO 8601 timestamp and convert to Unix seconds
const timestamp = Math.floor(new Date(timestampStr).getTime() / 1000);
// Build the message that was signed: merchant_code + unix_seconds + payload
const message = merchantCode + timestamp + payload;
// Generate expected signature
const expectedSignature = crypto
.createHmac('sha256', webhookSigningKey)
.update(message)
.digest('hex');
// Compare signatures securely
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
// Processing the webhook
app.post('/webhook', (req, res) => {
if (!verifyWebhook(req, WEBHOOK_SIGNING_KEY)) {
return res.status(401).send('Invalid signature');
}
// Extract webhook type and body
const { type, body } = req.body;
switch (type) {
case 'order_update':
// Process order update
console.log('Order updated:', body.id, 'Status:', body.status);
break;
// Add more webhook types as they become available
}
res.status(200).send('OK');
});Important Notes
In case your webhook endpoint is temporarily unavailable, Two-Coin will retry the webhook delivery with an exponential backoff. The number of retry attempts is configurable (default: 5 attempts). Failed webhooks are processed by a background task that handles delivery retries automatically.
If you encounter any issues or have questions not addressed in this documentation, please contact our support team on Telegram at https://t.me/cs_2coin (@cs_2coin).