Back to Help Center

Setting Up Webhooks

Automate your workflow by receiving real-time payment notifications.

Why Use Webhooks?

Webhooks let you automate actions when payments happen:

  • Automatically fulfill orders when payment is received
  • Update your database in real-time
  • Send confirmation emails to customers
  • Trigger downstream workflows

Step-by-Step Setup

1. Create Your Webhook Endpoint

First, create an endpoint on your server to receive webhook events:

// Express.js example
app.post('/webhooks/moneta', (req, res) => {
  const event = req.body;
  
  // Handle the event
  console.log('Received event:', event.type);
  
  // Return 200 to acknowledge receipt
  res.status(200).send('OK');
});

2. Register Your Webhook in Moneta

  1. 1

    Go to Dashboard → Settings → Webhooks

  2. 2

    Click "Add Webhook"

  3. 3

    Enter your endpoint URL

    Must be HTTPS (e.g., https://yoursite.com/webhooks/moneta)

  4. 4

    Select events to receive

    • ☑ payment.completed (most common)
    • ☑ payment.failed
    • ☐ payment.created
    • ☐ payment.expired
  5. 5

    Save and copy your webhook secret

    Store this securely - you'll need it to verify signatures

3. Verify Webhook Signatures

Always verify that webhooks are actually from Moneta:

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  
  return signature === expected;
}

app.post('/webhooks/moneta', (req, res) => {
  const signature = req.headers['x-moneta-signature'];
  
  if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process the verified webhook
  handleWebhook(req.body);
  res.status(200).send('OK');
});

4. Handle Events

function handleWebhook(event) {
  switch (event.type) {
    case 'payment.completed':
      // Payment successful - fulfill the order
      const orderId = event.data.metadata.order_id;
      fulfillOrder(orderId);
      sendConfirmationEmail(event.data.customer_email);
      break;
      
    case 'payment.failed':
      // Payment failed - notify customer
      notifyPaymentFailed(event.data.payment_id);
      break;
      
    case 'payment.expired':
      // Payment link expired
      markOrderExpired(event.data.metadata.order_id);
      break;
  }
}

Testing Your Webhook

Test Mode

Use the "Send Test Event" button in your webhook settings to send a test payload to your endpoint.

For local development, use ngrok to expose your local server to the internet.

Common Issues

Webhook not receiving events

  • • Verify your endpoint URL is correct and accessible
  • • Check that your server returns 200 status
  • • Ensure HTTPS is properly configured

Signature verification failing

  • • Make sure you're using the correct webhook secret
  • • Verify you're hashing the raw request body
  • • Check for encoding issues (UTF-8)

Duplicate events

  • • Store event IDs and check for duplicates
  • • Make your handlers idempotent
  • • Use database transactions for critical operations

Best Practices Checklist

  • Always verify webhook signatures
  • Return 200 status quickly (process async if needed)
  • Handle duplicate events idempotently
  • Log all webhook events for debugging
  • Set up monitoring for webhook failures
  • Keep your webhook secret secure

Need More Help?

Check out our detailed Webhooks Guide for advanced topics like retry policies and event types.