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.

Webhook Configuration

To receive webhook notifications, you need to configure two things in your merchant settings:

  1. 1. Webhook URL: A publicly accessible HTTPS endpoint on your server
  2. 2. Webhook Signing Key: A secret key used to verify webhook authenticity

Requirements for Webhook Endpoints

  • Must be a publicly accessible HTTPS URL
  • Should respond with a 200 OK status code within 5 seconds
  • Must validate the webhook signature to ensure authenticity
  • Requires a configured webhook signing key for signature verification

Webhook Events

Two-Coin sends webhook notifications when order statuses change. Currently, there is one webhook event type that covers all order status updates.

Event TypeDescription
orderFired when an order status changes (any status transition)

Order Status Types

The webhook payload includes the current order status, which can be one of:

CreatedOrder initially created
PendingWaiting for payment
ProcessingPayment being processed
HoldOrder on hold
CompleteSuccessfully completed
FailedOrder failed
ExpiredOrder expired
RefundedOrder refunded

Webhook Payload

All 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": "ord_123456",
    "from_currency": "USD",
    "to_currency": "BTC",
    "redirect_url": "https://example.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": {}
  }
}

Payload Structure

  • 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.

Verifying Webhooks

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.

Webhook Headers

  • x-webhook-signature: HMAC-SHA256 signature (hex-encoded)
  • x-webhook-timestamp: Unix timestamp (seconds) of webhook generation
  • x-webhook-merchant: Your merchant code

Signature Verification Process

To verify a webhook signature, you need to reconstruct the signed message and compare signatures:

  1. 1. Extract headers: Get signature, timestamp, and merchant code from headers
  2. 2. Build message: Concatenate merchant_code + timestamp + payload
  3. 3. Generate signature: HMAC-SHA256 the message with your webhook signing key
  4. 4. Compare: Verify the hex-encoded signature matches
// Node.js example
const crypto = require('crypto');

function verifyWebhook(req, webhookSigningKey) {
  const signature = req.headers['x-webhook-signature'];
  const timestamp = req.headers['x-webhook-timestamp'];
  const merchantCode = req.headers['x-webhook-merchant'];
  const payload = JSON.stringify(req.body);
  
  // Build the message that was signed
  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

  • • You must configure a webhook signing key in your merchant settings
  • • The signature is hex-encoded (not base64)
  • • Always use timing-safe comparison for signatures
  • • Verify the timestamp to prevent replay attacks

Webhook Retry Logic

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.

Support

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).