Custom Webhooks

Build your own integrations using RevKeen webhooks

Custom webhooks allow you to build your own integrations with RevKeen. Receive real-time notifications about events and trigger actions in your systems.

When to Use Custom Webhooks

Custom webhooks are ideal for:

  • CRM integration - Update customer records in Salesforce, HubSpot, etc.
  • Fulfillment - Trigger order fulfillment in your warehouse system
  • Access control - Grant/revoke access in your application
  • Analytics - Send events to your analytics platform
  • Accounting - Sync transactions to QuickBooks, Xero
  • Custom notifications - Build custom alert systems

Setting Up a Custom Webhook

  1. Go to Settings → Webhooks
  2. Click Add Endpoint
  3. Enter your endpoint URL (must be HTTPS)
  4. Select events to receive
  5. Copy the signing secret for verification
  6. Save the endpoint

Building Your Endpoint

Your webhook endpoint needs to:

  1. Accept POST requests
  2. Verify the signature
  3. Process the event
  4. Return 200 status quickly

Example Implementation

import express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json());

const WEBHOOK_SECRET = process.env.REVKEEN_WEBHOOK_SECRET;

function verifySignature(payload: string, signature: string): boolean {
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

app.post('/webhooks/revkeen', (req, res) => {
  // Verify signature
  const signature = req.headers['x-revkeen-signature'] as string;
  if (!verifySignature(JSON.stringify(req.body), signature)) {
    return res.status(401).send('Invalid signature');
  }

  // Get the event
  const event = req.body;

  // Process based on event type
  switch (event.type) {
    case 'payment.succeeded':
      handlePaymentSucceeded(event.data);
      break;
    case 'subscription.created':
      handleSubscriptionCreated(event.data);
      break;
    case 'subscription.canceled':
      handleSubscriptionCanceled(event.data);
      break;
    // Add more event handlers
  }

  // Return 200 quickly
  res.status(200).send('OK');
});

function handlePaymentSucceeded(data: any) {
  console.log('Payment received:', data.amount);
  // Update your database, send to analytics, etc.
}

function handleSubscriptionCreated(data: any) {
  console.log('New subscription:', data.id);
  // Grant access, update CRM, etc.
}

function handleSubscriptionCanceled(data: any) {
  console.log('Subscription canceled:', data.id);
  // Revoke access, send win-back email, etc.
}

Event Payload Structure

All webhooks follow this structure:

{
  "id": "evt_abc123",
  "type": "payment.succeeded",
  "created_at": "2025-01-15T10:30:00Z",
  "data": {
    "id": "pay_xyz789",
    "amount": 9900,
    "currency": "USD",
    "customer": {
      "id": "cus_def456",
      "email": "customer@example.com",
      "name": "John Doe"
    },
    "invoice_id": "inv_ghi012"
  },
  "entities": {
    "customer_id": "cus_def456",
    "invoice_id": "inv_ghi012"
  }
}

Best Practices

PracticeWhy
Always verify signaturesPrevents spoofed requests
Return 200 quicklyProcess async to avoid timeouts
Handle duplicatesSame event may be sent twice
Use idempotencySafe to process same event twice
Log eventsHelps with debugging
Queue long tasksDon't block the webhook response

Testing Your Webhook

  1. Deploy your endpoint to a publicly accessible URL
  2. Add it to RevKeen webhook settings
  3. Click Send Test Event
  4. Select an event type
  5. Check your logs for the received event
For local development, use a tool like ngrok to expose your local server with a public URL.

Common Integration Patterns

Granting Access

When subscription is created, grant access to your product:

  • Listen for subscription.created
  • Create user account if needed
  • Set subscription tier/permissions
  • Send welcome email

Revoking Access

When subscription ends, revoke access:

  • Listen for subscription.canceled
  • Check if subscription has ended (vs scheduled to end)
  • Downgrade to free tier or disable access
  • Optionally send win-back campaign

Related