Skip to main content

Webhooks

Receive real-time notifications when events happen in your Brighten organization. 18 event types across 5 categories.

Event Types

Recognitions

EventDescription
recognition.createdA new recognition was sent
recognition.updatedA recognition was edited
recognition.deletedA recognition was removed

Users

EventDescription
user.createdA new user was added to the organization
user.updatedA user profile was updated
user.deletedA user was removed from the organization
user.points.updatedA user's points balance changed

Rewards

EventDescription
reward.createdA new reward was added to the catalog
reward.updatedA reward was modified
reward.redeemedA user redeemed a reward
redemption.fulfilledA reward redemption was fulfilled
redemption.cancelledA reward redemption was cancelled

Teams

EventDescription
team.createdA new team was created
team.updatedA team was modified
team.member.addedA member was added to a team
team.member.removedA member was removed from a team

Budgets

EventDescription
budget.low_balanceA budget is running low
budget.depletedA budget has been fully spent
budget.refilledA budget was refilled

Payload Structure

Every webhook delivery sends a JSON payload with a consistent envelope structure.

Example Payload
{
  "id": "evt_abc123def456",
  "object": "event",
  "type": "recognition.created",
  "created_at": "2026-02-06T14:00:00Z",
  "api_version": "2026-01-01",
  "data": {
    "object": {
      "id": "550e8400-e29b-41d4-a716-446655440003",
      "sender": { "id": "...", "name": "Jane Doe" },
      "recipient": { "id": "...", "name": "John Smith" },
      "message": "Great work on the launch!",
      "points": 50
    }
  },
  "metadata": {
    "organization_id": "org_xyz789",
    "triggered_by": "user_abc123"
  }
}
FieldTypeDescription
idstringUnique event ID
objectstringAlways "event"
typestringThe event type (e.g. recognition.created)
created_atstringISO 8601 timestamp
api_versionstringAPI version this payload conforms to
data.objectobjectThe resource that was affected
data.previousobject?Previous state (update events only)
metadataobjectOrganization ID and triggering user

Signature Verification

Every webhook delivery includes an X-Brighten-Signature header containing an HMAC-SHA256 signature. Always verify this to ensure the payload was sent by Brighten.

How verification works:

  1. Extract the X-Brighten-Signature header
  2. Compute HMAC-SHA256 of the raw request body using your webhook secret
  3. Compare the computed signature with the header value
  4. Reject the request if signatures do not match
TypeScript
import crypto from 'crypto';

function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean {
  const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

// In your webhook handler:
app.post('/webhooks/brighten', (req, res) => {
  const signature = req.headers['x-brighten-signature'];
  const isValid = verifyWebhookSignature(req.rawBody, signature, process.env.BRIGHTEN_WEBHOOK_SECRET);

  if (!isValid) return res.status(401).json({ error: 'Invalid signature' });

  const event = JSON.parse(req.rawBody);
  console.log('Received event:', event.type);
  res.status(200).json({ received: true });
});
Python
import hmac, hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)
WEBHOOK_SECRET = "whsec_your_secret_here"

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.route('/webhooks/brighten', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Brighten-Signature', '')
    if not verify_signature(request.data, signature, WEBHOOK_SECRET):
        return jsonify({"error": "Invalid signature"}), 401
    event = request.get_json()
    print(f"Received event: {event['type']}")
    return jsonify({"received": True}), 200

Retry Behavior

If your endpoint returns a non-2xx status code or times out, Brighten will retry with exponential backoff.

AttemptDelayTotal Elapsed
1st retry1 minute1 minute
2nd retry5 minutes6 minutes
3rd retry30 minutes36 minutes
4th retry2 hours~2.5 hours
5th retry24 hours~26.5 hours

After 5 failed attempts, the webhook will be automatically disabled. Your endpoint must respond within 30 seconds and return a 2xx status code.

Ready to set up webhooks?

Sign up and create your first webhook in minutes.

Get Started