Skip to main content

Overview

Audience webhooks notify your server when a player links or disconnects an external account (Steam, Discord, Epic Games, etc.) within a project you manage. Events are delivered as signed HTTP POST requests to an endpoint you configure in Hub.

Configure in Hub

Go to Hub and open Settings > Webhooks > Add Webhook. Select one or both audience events:
EventFired when
audience_account_linkedA player links an external account
audience_account_unlinkedA player disconnects an external account

Payload

Both events use the same envelope shape. The data field contains the player and account details.
{
  "id": "evt_4cea103e-9148-476e-b634-5a31b4dc58de",
  "type": "audience_account_linked",
  "api_version": "2026-05-01",
  "created_at": "2026-05-01T10:30:00.000000000Z",
  "project_id": "353b1f6c-7dde-460c-9e5a-0711949e71f0",
  "data": {
    "player": {
      "id": "auth0|abc123"
    },
    "linked_account": {
      "provider": "steam",
      "provider_account_id": "76561198728595133",
      "username": "playername",
      "linked_at": "2026-05-01T10:29:58Z"
    }
  }
}
For unlink events, type is audience_account_unlinked. All other fields are identical. Supported provider values: steam, discord, epic_games, x, telegram, tiktok, twitch

Verify the Signature

Webhooks are signed by AWS SNS using RSA. Verify signatures using the sns-validator npm package. There is no shared secret or custom header. SNS delivers messages with Content-Type: text/plain. If you use Express, configure a raw text body parser for your webhook route:
app.use('/webhooks/immutable', express.text({ type: '*/*' }));
app.use('/webhooks/immutable', (req, res, next) => {
  if (typeof req.body === 'string') req.body = JSON.parse(req.body);
  next();
});
Then verify the signature and topic ARN:
import MessageValidator from 'sns-validator';

const validator = new MessageValidator();
const TOPIC_ARN = 'arn:aws:sns:us-east-2:362750628221:webhook-outbound-prod';

app.post('/webhooks/immutable', (req, res) => {
  res.status(200).send('OK');

  validator.validate(req.body, (err, message) => {
    if (err) {
      console.error('Invalid SNS signature', err);
      return;
    }

    if (message.TopicArn !== TOPIC_ARN) {
      console.error('Unexpected topic ARN', message.TopicArn);
      return;
    }

    if (message.Type === 'SubscriptionConfirmation') {
      fetch(message.SubscribeURL);
      return;
    }

    const event = JSON.parse(message.Message);
    handleEvent(event);
  });
});
Checking TopicArn confirms the event originated from Immutable’s infrastructure and not a third-party SNS topic.

Retry Policy

SNS retries failed deliveries automatically according to the SNS delivery retry policy. There is no manual retry in Hub. If your endpoint is unavailable for an extended period, events may be permanently dropped.

Best Practices

  • Respond quickly. Return 200 to SNS immediately and process the event asynchronously to avoid delivery timeouts.
  • Deduplicate. Use the id field to detect duplicate deliveries. The same event may arrive more than once.
  • Scope by project. The project_id field identifies which of your projects the player belongs to. A player can appear in multiple projects and trigger events for each.