What does the RevenueDot webhook event SUBSCRIBER_ALIAS mean?

The RevenueDot webhook event SUBSCRIBER_ALIAS means a new app user id was linked to an existing customer.

Quick facts#

Event SUBSCRIBER_ALIAS
Where RevenueDot webhook (event.type), RevenueCat's webhook format
Sent to Only webhooks whose event_types filter names subscriber_alias
Fields that are specific to it original_app_user_id
What it means A new app user id joined an existing customer: logIn onto an anonymous customer, logIn that merged an anonymous customer into an existing one, Android's alias call, or a restore that merged two customers.

When it is sent#

  • The app called logIn and the anonymous customer got a real app user id, or two customers were merged.
  • RevenueCat deprecated the event and sends it only to older projects.
  • RevenueDot delivers it only to webhooks whose event_types filter names subscriber_alias, and always keeps it in the customer's event history.

What your server should do#

  1. Add the new id to the customer's list of ids in your own records.
  2. Subscribe to it only if you need to follow id changes.
  3. Prefer reading aliases on any event, which lists every id of the customer.
  4. Deduplicate on event.id: deliveries can repeat, because anything but HTTP 200 is retried after 5, 10, 20, 40 and 80 minutes.

Example#

JavaScript
import { createHmac, timingSafeEqual } from "node:crypto";

// X-RevenueCat-Webhook-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">
function verify(rawBody, header, secret, toleranceSeconds = 300) {
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header ?? "");
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > toleranceSeconds) return false;
  const expected = createHmac("sha256", secret).update(`${m[1]}.${rawBody}`).digest();
  return timingSafeEqual(expected, Buffer.from(m[2], "hex"));
}

// Sign a sample delivery the way RevenueDot does, then handle it.
const secret = "whsec_test_secret";
const rawBody = JSON.stringify({ api_version: "1.0", event: {"id":"66339910-3BFF-49F4-B873-D1283D673DE2","type":"SUBSCRIBER_ALIAS","app_user_id":"user_1","product_id":"pro_monthly","original_app_user_id":"$RCAnonymousID:a"} });
const t = Math.floor(Date.now() / 1000);
const header = `t=${t},v1=${createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex")}`;

const seen = new Set(); // use a database table in production

function handle(rawBody, header) {
  if (!verify(rawBody, header, secret)) return "401 bad signature";
  const { event } = JSON.parse(rawBody);
  if (seen.has(event.id)) return "200 duplicate";
  seen.add(event.id);
  if (event.type !== "SUBSCRIBER_ALIAS") return "200 ignored";
  return "add " + event.app_user_id + " to the customer's ids";
}

console.log(handle(rawBody, header));

Run-checked: npm run check:snippets runs this snippet with Node and compares its output with add user_1 (checked 2026-10-03).

How RevenueDot produces it#

recordSubscriberAlias records it when a customer gets a new alias or two customers merge. OPT_IN_EVENT_TYPES in packages/core keeps it from any webhook that does not name it in its filter.

Source#

Checked: 2026-10-03

Edit this page on GitHub ↗ View as Markdown Last updated