Webhooks
Webhooks are used to send events from ReferralHero to your server. You can decide which events to send to your server.
To enable webhooks:
go to your campaign dashboard > Edit Campaign > Integrations > Webhooks
Click on the + New Webhook button
In the popup, add your endpoint URL and toggle the events you want to receive
Click on Create Webhook

Webhook Payload Verification
To ensure that your webhook payloads are authentic and have not been tampered with, ReferralHero includes a signature header in every webhook request. You can use this signature to validate requests.
⚠️ Important: Make sure to enable the “Payload Verification” toggle. Once enabled, a secret key will be generated. This key is required to decode and validate the signature header in your application that receives the webhook.

Where to Find Your Webhook Secret Key
You can find your Webhook Secret Key in two places:
Option 1: From Profile Menu
Log in to your ReferralHero dashboard.
Click on your profile button (top-right corner).
In the popup, select Webhook Secret.
You will see your Webhook Secret Key along with an option to regenerate it if needed.

Option 2: From Campaign Settings
Log in to your ReferralHero dashboard.
Click Edit Campaign for the campaign you want.
Go to the Integration tab.
Click on Webhook, and you will see the Webhook Secret Key.

Use this secret key in your server code to verify incoming webhooks.
Steps to Verify a Webhook
Read the raw request body (e.g.,
request.raw_postin Rails).Retrieve the signature from the
X-ReferralHero-Signatureheader.Recompute the HMAC-SHA256 hash of the raw body using your Webhook Secret Key as the secret.
Compare your computed value with the signature header. If they match, the webhook is valid.
Code Examples
require 'openssl'
require 'base64'
class WebhooksController < ActionController::API
skip_before_action :verify_authenticity_token
def receive
raw_payload = request.raw_post
signature = request.headers['X-ReferralHero-Signature']
secret = ENV['REFERRALHERO_API_KEY']
computed_signature = Base64.strict_encode64(
OpenSSL::HMAC.digest('sha256', secret, raw_payload)
)
unless ActiveSupport::SecurityUtils.secure_compare(signature.to_s, computed_signature)
render json: { error: 'Invalid signature' }, status: :unauthorized and return
end
data = JSON.parse(raw_payload)
# handle data...
head :ok
end
end
from flask import Flask, request, abort
import hmac, hashlib, base64, os
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
raw = request.get_data()
signature = request.headers.get('X-ReferralHero-Signature', '')
secret = os.environ['REFERRALHERO_API_KEY'].encode()
digest = hmac.new(secret, raw, hashlib.sha256).digest()
computed = base64.b64encode(digest).decode()
if not hmac.compare_digest(signature, computed):
abort(401)
data = request.get_json()
# handle data...
return '', 200const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.raw({ type: 'application/json' }));
app.post('/webhook', (req, res) => {
const rawBody = req.body; // Buffer
const signature = req.header('X-ReferralHero-Signature') || '';
const secret = process.env.REFERRALHERO_API_KEY;
const computed = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
if (!timingSafeEqual(signature, computed)) {
return res.status(401).send('Invalid signature');
}
const data = JSON.parse(rawBody.toString('utf8'));
// process data...
res.sendStatus(200);
});
function timingSafeEqual(a, b) {
const bufA = Buffer.from(a || '');
const bufB = Buffer.from(b || '');
if (bufA.length !== bufB.length) return false;
return crypto.timingSafeEqual(bufA, bufB);
}
✅ Backward Compatible: If you do not check this header, your existing webhooks will continue to work without any changes. 🔒 Recommended: Implement signature validation to ensure authenticity and security of incoming webhooks.
Events
ReferralHero sends a POST HTTP request with a JSON payload when specific events occur.
There are 6 types of events:
new_registration
Sent when a new person subscribes to your list. If you the confirmation email is disabled, the event is sent as soon as the person is subscribed to the list.
{
response: "new_registration",
list_uuid: "MFXXXX", //The UUID of your list
subscriber_id: "sub_123ABC", // Subscriber's ID
name: "John Doe", //Subscriber's name
first_name: "John",
last_name: "Doe",
email: "[email protected]", //Subscriber's email
extra_field: "+1 2348891123", // Subscriber's extra field's value
extra_field_2: "USA", // Subscriber's second extra field's value
code: "2hg36dvs", //Subscriber's unique referral code
source: "facebook", //Subscriber's source. If the subscriber doesn't have a source the value will be "direct_visit"
referred: true,
referrer: {
subscriber_id: "sub_123CCD",
people_referred: 2,
referral_link: "http://mywebsite.com/LINK_PLAIN",
points: 3,
last_referral_at: 1702017953,
name: "Mark Doe",
first_name: "Mark",
last_name: "Doe",
email: "[email protected]"
extra_field: "+1 2348894454",
extra_field_2: "USA",
option_field: "Los Angeles",
code: "fd336dff",
phone_number: "+1 2348894454",
crypto_wallet_address: "0x0000000000000000000000000000000000000011"
}, //This property can have 3 possible values: an empty string (if the subscriber has not been referred), an object containing data of the referral (if the subscriber has been referred) or "subscriber_deleted" (if the subscriber has been referred but the user has been deleted.)
referral_link: "http://mywebsite.com/LINK_PLAIN",
created_at: 1234567889 // Timestamp of the subscriber's sign up
}subscriber_promoted
Sent when a subscriber is promoted.
{
response: "subscriber_promoted",
list_uuid: "MFXXXX",
subscriber_id: "sub_123ABC",
source: "facebook",
referred: false,
referral: {
subscriber_id: "sub_123CCD",
people_referred: 2,
referral_link: "http://mywebsite.com/LINK_PLAIN",
points: 3,
last_referral_at: 1702017953,
name: "Mark Doe",
first_name: "Mark",
last_name: "Doe",
email: "[email protected]"
extra_field: "+1 2348894454",
extra_field_2: "USA",
option_field: "Los Angeles",
code: "fd336dff",
phone_number: "+1 2348894454",
crypto_wallet_address: "0x0000000000000000000000000000000000000011"
},
people_referred: 3, //Number of people referred
referral_link: "http://mywebsite.com/LINK_PLAIN",
created_at: 1234567889 // Timestamp of the subscriber's promotion
name: "John Doe", //Subscriber's name
first_name: "John",
last_name: "Doe",
email: "[email protected]" //Subscriber's email
extra_field: "+1 2348891123", // Subscriber's extra field's value
extra_field_2: "USA", // Subscriber's second extra field's value
option_field: "Florida", // Subscriber's option field's value
code: "2hg36dvs",
phone_number: "+1 2348891123",
crypto_wallet_address: "0x0000000000000000000000000000000000000000"
}subscriber_updated
Sent when a subscriber field is updated.
{
"response": "subscriber_fields_updated",
"list_uuid": "MF833ac6ee2d", // Unique list identifier
"subscriber_id": "sub_61ad4723e3a9", // Unique ID of the subscriber
"source": "referral", // Source of the subscriber (e.g., referral, direct_visit)
"referred": false, // Whether the subscriber was referred
"referral": null,
"referral_link": "https://campaign.referralhero.com/MF833ac6ee2d/signup?mwr=1296cda7", // Personalized referral URL
"people_referred": 0,
"created_at": 1746795375, // Timestamp of subscriber creation
"last_referral_at": null,
"name": "Jane Doe", // Full name
"first_name": "Jane", // First name
"last_name": "Doe", // Last name
"email": "[email protected]", // Email address
"extra_field": "Company ABC",
"extra_field_2": "Product Manager",
"extra_field_3": "New York",
"extra_field_4": "Referral Campaign A",
"option_field": "Option 1",
"code": "1296cda7",
"phone_number": "+1234567890", // Phone number
"crypto_wallet_address": "0xABCDEF1234567890"
}subscriber_deleted
Sent when a subscriber is deleted.
{
response: "subscriber_deleted",
list_uuid: "MFXXXX",
subscriber_id: "sub_123ABC",
last_referral_at: 1702017953,
name: "John Doe", //Subscriber's name
first_name: "John",
last_name: "Doe",
email: "[email protected]" //Subscriber's email
extra_field: "+1 2348891123", // Subscriber's extra field's value
extra_field_2: "USA", // Subscriber's second extra field's value
option_field: "Florida", // Subscriber's option field's value
code: "2hg36dvs",
phone_number: "+1 2348891123",
crypto_wallet_address: "0x0000000000000000000000000000000000000000"
}reward_unlocked
Sent immediately when a subscriber qualifies for and unlocks a reward.
{
"response": "reward_unlocked",
"list_uuid": "MFABC123",
"subscriber_id": "sub_ABC123",
"bonus_id": 178, // Unique ID of the reward unlocked
"reward_name": "$100 Giftcard", // Name of reward
"reward_value": 100, // Value of the reward if set
"name": "John Smith", // Subscriber's full name
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]", // Subscriber's email
"extra_field": null, // Custom field #1 (optional)
"extra_field_2": null, // Custom field #2 (optional)
"extra_field_3": null, // Custom field #3 (optional)
"extra_field_4": null, // Custom field #4 (optional)
"code": "YYY999", // Unique referral code
"people_referred": 5, // Number of successful referrals
"referral_link": "ReferralHero | Referral Program Software for B2B & B2C Brands ", // Personalized referral URL
"phone_number": "", // Subscriber's phone number
"crypto_wallet_address": "" // Wallet address if used
}reward_sent
Sent when a reward is actually delivered to the subscriber. This happens only after conditions like 'Hold until manually reviewed' or 'Hold for X days' are fulfilled or Reward delivery set to 'Unlock and send reward immediately'.
{
"response": "reward_sent",
"list_uuid": "MFABC123",
"subscriber_id": "sub_ABC123",
"bonus_id": 178, // Unique ID of the reward sent
"reward_name": "$100 Giftcard", // Name of reward
"reward_value": 100, // Value of the reward if set
"name": "John Smith", // Subscriber's full name
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]", // Subscriber's email
"extra_field": null, // Custom field #1 (optional)
"extra_field_2": null, // Custom field #2 (optional)
"extra_field_3": null, // Custom field #3 (optional)
"extra_field_4": null, // Custom field #4 (optional)
"code": "YYY999", // Unique referral code
"people_referred": 5, // Number of successful referrals
"referral_link": "https://referralhero.com/?mwr=YYY999", // Personalized referral URL
"phone_number": "", // Subscriber's phone number
"crypto_wallet_address": "" // Wallet address if used
}Errors
Please send back a blank response with a status code of 200.
All not-200 responses will be considered errors. After 10 consecutive bad responses, the webhook will be disabled.
If a webhook fails, we will try to deliver it 3 times over a period of 5 minutes.
How to test a webhook
To test a webhook just click on the Test button next to the webhook URL you want to test. We will ping your webhook URL with a JSON file containing fake data.
Last updated
Was this helpful?