Request
- Method: POST
- Content-Type: application/json
- Header X-Status-Webhook-Timestamp: UNIX seconds
- Header X-Status-Webhook-Signature:sha256=<hex>
Payload
{
  "event": "status.created", // or "status.deleted"
  "did": "did:plc:...",
  "handle": null,
  "status": "🙂",           // created only
  "text": "in a meeting",   // optional
  "uri": "at://...",       // record URI
  "since": "2025-09-10T16:00:00Z", // created only
  "expires": null            // created only
}Verify signature
Compute HMAC-SHA256 over timestamp + "." + rawBody using your secret. Compare to header (without the sha256= prefix) with constant-time equality, and reject if timestamp is too old (e.g., > 5 minutes).
// Node (TypeScript)
import crypto from 'node:crypto';
function verify(req: any, rawBody: Buffer, secret: string): boolean {
  const ts = req.headers['x-status-webhook-timestamp'];
  const sig = String(req.headers['x-status-webhook-signature'] || '').replace(/^sha256=/, '');
  if (!ts || !sig) return false;
  const now = Math.floor(Date.now()/1000);
  if (Math.abs(now - Number(ts)) > 300) return false; // 5m
  const mac = crypto.createHmac('sha256', secret).update(String(ts)).update('.').update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(mac, 'hex'), Buffer.from(sig, 'hex'));
}
// Rust (axum-ish)
use hmac::{Hmac, Mac};
use sha2::Sha256;
fn verify(ts: &str, sig_hdr: &str, body: &[u8], secret: &str) -> bool {
    let sig = sig_hdr.strip_prefix("sha256=").unwrap_or(sig_hdr);
    if let Ok(ts_int) = ts.parse::() {
        if (chrono::Utc::now().timestamp() - ts_int).abs() > 300 { return false; }
    } else { return false; }
    let mut mac = Hmac::::new_from_slice(secret.as_bytes()).unwrap();
    mac.update(ts.as_bytes());
    mac.update(b".");
    mac.update(body);
    let calc = hex::encode(mac.finalize().into_bytes());
    subtle::ConstantTimeEq::ct_eq(calc.as_bytes(), sig.as_bytes()).into()
}
  # Python (Flask example)
import hmac, hashlib, time
from flask import request
def verify(secret: str, raw_body: bytes) -> bool:
    ts = request.headers.get('X-Status-Webhook-Timestamp')
    sig_hdr = request.headers.get('X-Status-Webhook-Signature', '')
    if not ts or not sig_hdr.startswith('sha256='):
        return False
    if abs(int(time.time()) - int(ts)) > 300:
        return False
    expected = hmac.new(secret.encode(), (ts + '.').encode() + raw_body, hashlib.sha256).hexdigest()
    actual = sig_hdr[len('sha256='):]
    return hmac.compare_digest(expected, actual)
// Go (net/http)
package main
import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/hex"
  "net/http"
  "strconv"
  "time"
)
func verify(r *http.Request, body []byte, secret string) bool {
  ts := r.Header.Get("X-Status-Webhook-Timestamp")
  sig := r.Header.Get("X-Status-Webhook-Signature")
  if ts == "" || sig == "" { return false }
  if len(sig) > 7 && sig[:7] == "sha256=" { sig = sig[7:] }
  tsv, err := strconv.ParseInt(ts, 10, 64)
  if err != nil || time.Now().Unix()-tsv > 300 || tsv-time.Now().Unix() > 300 { return false }
  mac := hmac.New(sha256.New, []byte(secret))
  mac.Write([]byte(ts))
  mac.Write([]byte("."))
  mac.Write(body)
  expected := hex.EncodeToString(mac.Sum(nil))
  return hmac.Equal([]byte(expected), []byte(sig))
}