Skip to content

Webhooks ​

ReMeet sends signed POST requests to your server when something happens. Set it up in your developer account: your app → API and webhooks → address (https) and events. On the first save you get a signing secret (shown once).

Events ​

EventWhendata
app.installedA person installed your appuser.id
app.uninstalledA person removed ituser.id
meeting.startedA meeting startedmeeting
meeting.endedIt endedmeeting
participant.joinedSomeone joinedmeeting, participant
participant.leftSomeone leftmeeting, participant
pingYou pressed «Send a test event»message

Meeting events come only for meetings whose host allowed your app meetings.read through Sign in with ReMeet.

The request ​

http
POST /remeet/webhook HTTP/1.1
Content-Type: application/json
User-Agent: ReMeet-Webhooks/1.0
ReMeet-Event: participant.joined
ReMeet-Delivery: 7d3f0c1e-1b0a-4a0f-9d55-2c3b9f4c6a10
ReMeet-Signature: t=1794067200,v1=5f2b…c9

{
  "id": "7d3f0c1e-1b0a-4a0f-9d55-2c3b9f4c6a10",
  "type": "participant.joined",
  "created_at": "2026-11-07T12:00:00+00:00",
  "app": "planning-poker",
  "data": {
    "meeting": { "id": "01m6saztdr6cafg9yzx83db0fs", "title": "Daily", "host_id": "p_3f9c…" },
    "participant": { "id": "p_8a1d…", "name": "Omar" }
  }
}

All ids of people are the ids for your app (p_…), the same as in meetings and in the API.

Check the signature ​

v1 is HMAC-SHA256(secret, "<t>.<raw body>") in hex. Reject requests with a wrong signature or a t older than 5 minutes.

js
import crypto from 'node:crypto';

export function verifyReMeet(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(',').map((part) => part.split('=')));
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;

  return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}
py
import hashlib, hmac, time

def verify_remeet(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(part.split("=", 1) for part in header.split(","))
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return abs(time.time() - int(parts["t"])) < 300 and hmac.compare_digest(expected, parts["v1"])
php
function verifyReMeet(string $rawBody, string $header, string $secret): bool
{
    parse_str(str_replace(',', '&', $header), $parts);
    $expected = hash_hmac('sha256', $parts['t'].'.'.$rawBody, $secret);

    return abs(time() - (int) $parts['t']) < 300 && hash_equals($expected, $parts['v1']);
}

Use the raw body as it came, before parsing JSON.

Answer and retries ​

Answer 2xx within 10 seconds — that counts as delivered. Otherwise ReMeet repeats: after 1 minute, 5 minutes and 30 minutes (4 attempts in all). Redirects are not followed. The same event can arrive twice: deduplicate by ReMeet-Delivery.

The last deliveries and your server's answers are in your developer account under Recent deliveries.

Rules ​

  • The address is public https (internal and private network addresses are refused).
  • Do the work after answering: put the event in a queue and reply 200 at once.

ReMeet Apps SDK v0 · beta. The SDK file v0.js is MIT.