ArenyzeDocs
Automation

Webhooks & events

Instead of polling, let Arenyze call you. Add an HTTPS endpoint in Profile → Developer, choose the events and the players, and receive signed JSON within minutes of the change.

How it works

  1. Watch players. Each endpoint lists the players it follows (THE FINALS name, R6 name + platform, Endfield UID). Leave the list empty to receive the global feeds (THE FINALS renames and bans).
  2. Arenyze checks them — R6 every 5 min, THE FINALS every 10 min, Endfield every 30 min — and compares with the last state.
  3. A change becomes an event and is POSTed to your endpoint, signed. Failed deliveries are retried for 24 hours.

Payload

Every delivery is a POST with a JSON body:

POST bodyJSON
{
  "id": "evt_10423",
  "type": "thefinals.league_changed",
  "game": "thefinals",
  "player": "balise#2431",
  "occurred_at": "2026-11-03T00:16:57.000Z",
  "data": {
    "player": "balise#2431",
    "display": "Balise#2431",
    "url": "https://thefinals.arenyze.com/player/Balise%232431",
    "from": "Diamond 2",
    "to": "Diamond 1",
    "direction": 1,
    "rank": 47,
    "score": 54011
  },
  "text": "Balise#2431 moved from Diamond 2 to Diamond 1."
}
HeaderValue
Arenyze-Signaturet=<unix seconds>,v1=<hex HMAC-SHA256>
Arenyze-EventThe event type.
Arenyze-DeliveryUnique delivery id (use it to de-duplicate).
User-AgentArenyze-Webhooks/1.0

Verifying the signature

Compute HMAC-SHA256 of <t>.<raw body> with the endpoint secret (whsec_…, shown once when you create or rotate it) and compare with v1. Reject timestamps older than 5 minutes.

import crypto from "node:crypto";
import express from "express";

const app = express();
app.post("/arenyze", express.raw({ type: "application/json" }), (req, res) => {
  const sig = req.get("Arenyze-Signature") || "";
  const { t, v1 } = Object.fromEntries(sig.split(",").map(p => p.split("=")));
  const expected = crypto.createHmac("sha256", process.env.ARENYZE_WEBHOOK_SECRET)
    .update(`${t}.${req.body}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  if (!fresh || !v1 || !crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))) {
    return res.status(400).send("bad signature");
  }
  const event = JSON.parse(req.body);
  console.log(event.type, event.text);
  res.sendStatus(204); // answer fast; do the work async
});

Retries & health

  • Any 2xx within 8 seconds is a success. Anything else is retried after 1 min, 5 min, 30 min, 2 h, 6 h and 12 h.
  • 404 and 410 stop the retries at once.
  • After 15 failed deliveries in a row the endpoint is disabled and you get a notification. Enable it again from the panel.
  • The panel shows the last 50 deliveries with status code and timing, and can re-send any of them or a test event (arenyze.test).
  • Targets must be public HTTPS hosts; private and internal addresses are refused.

Event catalogue

r6.rank_changedRainbow Six

The ranked tier changed (e.g. Emerald → Diamond).

dataJSON
{
  "from": {
    "rank": "Emerald I",
    "rp": 3980
  },
  "to": {
    "rank": "Diamond V",
    "rp": 4012,
    "kd": "1.21"
  },
  "delta": 32
}
r6.rp_changedRainbow Six

RP changed — a ranked match was played.

dataJSON
{
  "from": {
    "rank": "Gold II",
    "rp": 2710
  },
  "to": {
    "rank": "Gold II",
    "rp": 2734,
    "kd": "1.05"
  },
  "delta": 24
}
thefinals.rank_changedTHE FINALS

Position or score on the live Ranked board changed.

dataJSON
{
  "from": {
    "rank": 61,
    "score": 53210
  },
  "to": {
    "rank": 47,
    "score": 54011,
    "league": "Diamond 1"
  },
  "rankDelta": 14
}
thefinals.league_changedTHE FINALS

League changed. direction is 1 up, -1 down.

dataJSON
{
  "from": "Diamond 2",
  "to": "Diamond 1",
  "direction": 1,
  "rank": 47,
  "score": 54011
}
thefinals.club_changedTHE FINALS

Joined, left or switched club (null = no club).

dataJSON
{
  "from": "BERGR",
  "to": "VGG"
}
thefinals.renamedTHE FINALS

Embark name changed. Watched players, or every rename with the global feed.

dataJSON
{
  "from": "Balise#9424",
  "to": "Balise#2431",
  "global": true
}
thefinals.ban_detectedTHE FINALS

Removed from the leaderboards. Watched players, or the global feed.

dataJSON
{
  "banType": "removed",
  "banTypeLabel": "Removed from the leaderboard",
  "status": "suspected",
  "lastRank": 6647,
  "lastLeague": "Platinum 2",
  "season": "s12",
  "global": true
}
endfield.level_changedEndfield

Authority level changed.

dataJSON
{
  "from": 52,
  "to": 53
}
endfield.world_level_changedEndfield

World level changed.

dataJSON
{
  "from": 5,
  "to": 6
}
endfield.operators_changedEndfield

Number of operators on the account changed.

dataJSON
{
  "from": 21,
  "to": 22
}