Skip to main content

What is Webhook Setup?

Setting up a webhook tells Revolv3 where to send event notifications. Once configured, Revolv3 will automatically send HTTP POST requests to your server when events occur (like payments completing, invoices changing status, etc.). Why you need this:
  • Real-time updates: Get notified immediately when events happen
  • Essential for ACH: ACH payments take days—webhooks tell you when they complete
  • Better user experience: Update your UI instantly
  • Efficient: No need to constantly poll the API

Prerequisites

Before creating a webhook, you need:
  1. Public endpoint: Your webhook URL must be publicly accessible (not localhost)
  2. HTTPS: Use HTTPS for security (webhooks contain sensitive data)
  3. Endpoint ready: Your server should be able to receive POST requests
  4. Revolv3 account: Access to the Revolv3 portal

Step 1: Prepare Your Webhook Endpoint

Before configuring in Revolv3, make sure your endpoint is ready to receive webhooks.

Your Endpoint Should:

  • Accept HTTP POST requests
  • Return 200 OK quickly (process asynchronously if needed)
  • Be publicly accessible (not behind a firewall or localhost)
  • Use HTTPS (required for security)
  • Handle the webhook payload (JSON with Body and Entropy fields)

Example Endpoint (Node.js/Express)

app.post('/webhooks/revolv3', (req, res) => {
  // 1. Verify signature (important!)
  const signature = req.headers['x-revolv3-signature'];
  const isValid = verifySignature(req.body, signature, webhookKey, webhookUrl);
  
  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }
  
  // 2. Parse the Body field (it's a JSON string)
  const eventData = JSON.parse(req.body.Body);
  
  // 3. Process the event
  handleWebhookEvent(eventData);
  
  // 4. Respond quickly with 200 OK
  res.status(200).send('OK');
});

Step 2: Create Webhook in Revolv3 Portal

  1. Log in to the Revolv3 Portal:
  2. Navigate to Webhooks:
    • Go to the Webhooks page in the portal
  3. Create a new webhook:
    • Click the button to create a new webhook
  4. Configure the webhook:
    • URL: Enter your webhook endpoint URL (must be HTTPS and publicly accessible)
    • Webhook Type: Select “Object” (the “Event” type is deprecated)
Webhook configuration screen
  1. Copy your Webhook Key:
    • After creating the webhook, you’ll see a Webhook Key
    • Copy this immediately—you’ll need it to verify signatures
    • Store it securely (like your API keys)

Step 3: Test Your Connection

Before saving, test that Revolv3 can reach your endpoint:
  1. Click “Test Connection” in the portal
  2. Revolv3 sends a test webhook to your endpoint
  3. Your endpoint should return 200 OK
  4. If successful: The “Save” button will be enabled
  5. If failed: Check your endpoint, make sure it’s accessible and returns 200 OK
What the test does: Revolv3 sends a WebhookTest event to verify your endpoint is reachable and responds correctly.

Step 4: Save Your Configuration

Once the test connection succeeds:
  1. Click “Save” to save your webhook configuration
  2. Your webhook is now active and will receive events
  3. Monitor your endpoint to ensure webhooks are being received

Understanding Webhook Security: Signature Verification

Revolv3 includes a signature in each webhook request so you can verify it came from Revolv3.

The x-revolv3-signature Header

Each webhook request includes an x-revolv3-signature header containing a hashed signature of the payload. Why it matters: This signature proves the webhook came from Revolv3 and wasn’t tampered with.

How to Verify Signatures

Revolv3 uses HMAC-SHA256 to generate the signature:
  1. Concatenate: {your-webhook-url}${request-body}
    • Note the $ delimiter between URL and body
  2. Create HMAC: Use HMAC-SHA256 with your webhook key
  3. Encode: Base64 encode the result
  4. Compare: This should match the x-revolv3-signature header

Verification Code Examples

C# Example

public static bool IsValidWebhookEventSignature(
    string requestBody,
    string signatureHeader,
    string signatureKey,
    string url)
{
    if (string.IsNullOrEmpty(signatureKey))
        throw new ArgumentNullException(nameof(signatureKey));
    if (string.IsNullOrEmpty(url))
        throw new ArgumentNullException(nameof(url));
    
    // Concatenate url + "$" + requestBody
    byte[] bytes = Encoding.UTF8.GetBytes(url + "$" + requestBody);
    
    // Create HMAC-SHA256 hash
    using var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(signatureKey));
    
    // Compare signatures
    return Convert.ToBase64String(hmacsha256.ComputeHash(bytes)).Equals(signatureHeader);
}

PHP Example

function IsValidWebhookEventSignature(
    string $requestBody,
    string $signatureHeader,
    string $signatureKey,
    string $url
): bool {
    if (empty($signatureKey)) {
        throw new ArgumentNullException('signatureKey');
    }
    if (empty($url)) {
        throw new ArgumentNullException('url');
    }

    // Concatenate url + "$" + requestBody
    $data = $url . '$' . $requestBody;

    // Create HMAC-SHA256 hash
    $hmac = hash_hmac('sha256', $data, $signatureKey, true);

    // Compare signatures
    return base64_encode($hmac) === $signatureHeader;
}

JavaScript/Node.js Example

const crypto = require('crypto');

function isValidWebhookSignature(requestBody, signatureHeader, signatureKey, url) {
  if (!signatureKey || !url) {
    throw new Error('signatureKey and url are required');
  }
  
  // Concatenate url + "$" + requestBody
  const data = url + '$' + requestBody;
  
  // Create HMAC-SHA256 hash
  const hmac = crypto.createHmac('sha256', signatureKey);
  hmac.update(data);
  const hash = hmac.digest('base64');
  
  // Compare signatures (use constant-time comparison for security)
  return crypto.timingSafeEqual(
    Buffer.from(hash),
    Buffer.from(signatureHeader)
  );
}

Important Notes

Webhook Type: Use “Object”

  • Use “Object” type: This is the current format
  • Don’t use “Event” type: It’s deprecated and will be removed

URL Requirements

  • Must be HTTPS: Webhooks require secure connections
  • Must be publicly accessible: Can’t use localhost or private IPs
  • Must return 200 OK: Your endpoint should respond quickly with 200 status

Webhook Key Security

  • Store securely: Treat webhook keys like API keys
  • Never expose: Don’t commit to version control
  • Use environment variables: Store in secrets manager

Testing Your Webhook

Test Connection Button

The “Test Connection” button in the portal:
  1. Sends a WebhookTest event to your endpoint
  2. Waits for a 200 OK response
  3. Enables the Save button if successful

Manual Testing

You can also test manually by:
  1. Making a test payment in sandbox
  2. Checking if your endpoint receives the webhook
  3. Verifying the signature is correct
  4. Ensuring you process the event correctly

Troubleshooting

Test Connection Fails

Possible issues:
  • Endpoint not publicly accessible (localhost won’t work)
  • Endpoint not returning 200 OK
  • Firewall blocking Revolv3’s requests
  • Incorrect URL format
Solutions:
  • Use a service like ngrok for local testing
  • Ensure your endpoint responds with 200 OK
  • Check server logs for incoming requests
  • Verify the URL is correct and uses HTTPS

Webhooks Not Received After Setup

Check:
  • Is your endpoint publicly accessible?
  • Is it returning 200 OK?
  • Are you checking the correct URL?
  • Check Revolv3 portal for webhook delivery status

Signature Verification Fails

Check:
  • Are you using the correct webhook key?
  • Is the URL exactly as configured (including https://)?
  • Are you concatenating URL + ”$” + body correctly?
  • Are you using HMAC-SHA256 and Base64 encoding?

Best Practices

  1. Always verify signatures: Never process webhooks without signature verification
  2. Respond quickly: Return 200 OK immediately, process asynchronously
  3. Handle duplicates: Make your handler idempotent
  4. Log everything: Log all webhooks for debugging and auditing
  5. Test thoroughly: Test in sandbox before production
  6. Monitor delivery: Check webhook delivery status in the portal

Next Steps