Skip to main content

Webhooks

BossMode webhooks go two directions. Inbound events come from trusted partners — the primary example is AvatarCzar sending confidence updates when a persona’s read on the market changes. Outbound events go from BossMode to whatever URL you configure — Slack, a warehouse, your own service — when directives execute, packs install, revenue is recorded, or the guardian kill engages. Both directions are HMAC-SHA256 signed, timestamp-guarded to reject replays older than 5 minutes, and verified in constant time. Inbound endpoints resolve the sending customer from the payload’s identifier (not from the body’s customerId field) to block cross-tenant forgery. Outbound deliveries are at-least-once with exponential backoff — design handlers to be idempotent.

Inbound webhooks — AvatarCzar confidence updates

BossMode accepts inbound confidence update events from AvatarCzar at:
POST /api/pro/avatarczar/induction

Signature verification

Every inbound request from AvatarCzar is signed with HMAC-SHA256. The implementation is in lib/avatarczar-inbound.ts. The signature is delivered in the x-avatarczar-signature request header in the format:
x-avatarczar-signature: sha256=<hex-digest>
To verify:
import { verifyAvatarCzarInboundSignature } from '@/lib/avatarczar-inbound';

const valid = verifyAvatarCzarInboundSignature({
  secret: process.env.AVATARCZAR_WEBHOOK_SECRET!,
  rawBody: rawBodyString,  // the raw, un-parsed request body string
  signature: request.headers.get('x-avatarczar-signature'),
});

if (!valid) {
  return new Response('Unauthorized', { status: 401 });
}
Verification uses a constant-time comparison (crypto.timingSafeEqual) to prevent timing attacks.

Payload shape

The inbound payload is validated against the avatarCzarConfidenceUpdateSchema from lib/avatarczar-inbound.ts:
FieldTypeDescription
workspaceIdstringThe BossMode workspace receiving the update
customerEntitlementIdstringThe entitlement being updated
avatarczarTargetIdstringThe AvatarCzar target that generated the update
avatarczarEventIdstringIdempotency key — deduplicate on this field
metricenumThe confidence metric being updated (see ALLOWED_METRICS)
deltanumberSigned delta applied to the metric
newConfidencenumber (0–1)The new confidence value after the update
priorConfidencenumber (0–1)Optional — the prior value before this update
sourceBossmodeRefobjectOptional — { table, id } linking back to a BossMode record
firedAtnumberUnix timestamp (ms) when AvatarCzar fired the event

Rate limit

/api/pro/avatarczar/induction — 60 requests per 60 seconds.

Outbound webhooks — operator destinations

Configure outbound webhook destinations to receive BossMode events at your own endpoints.

Configuration endpoint

POST /api/pro/avatarczar/webhooks
Rate limit: 5 requests per 60 seconds.

Registering a destination

curl -sS -X POST https://bossmode.ing/api/pro/avatarczar/webhooks \
  -H "x-bossmode-token: $BOSSMODE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Notify Slack when a directive completes",
    "url": "https://hooks.slack.com/services/T.../B.../..."
  }'
URLs are SSRF-validated before the config saves — private IPs, localhost, 169.254.0.0/16 metadata hosts, and non-HTTPS schemes are rejected.

Event types

EventWhen
directive.createdA new boss directive is persisted
directive.executedA directive completes (success or fail)
pack.installedA pack fanout completes
pack.revokedA pack license is refunded or disputed
revenue.recordedA new revenue event is logged
approval.requestedAn operator approval is queued
kill.activatedGuardian kill is engaged

Request format

POST https://your-endpoint.example.com/bossmode-webhook
X-BossMode-Signature: t=1712345678,v1=<hmac-sha256-hex>
X-BossMode-Event: directive.executed
X-BossMode-RequestId: req_...
Content-Type: application/json

{
  "event": "directive.executed",
  "timestamp": 1712345678123,
  "workspaceId": "...",
  "payload": { ... }
}

Verifying

import crypto from 'node:crypto';

function verifyBossModeSignature(rawBody: string, header: string, secret: string): boolean {
  const [tPart, v1Part] = header.split(',');
  const timestamp = Number.parseInt(tPart.split('=')[1], 10);
  const signature = v1Part.split('=')[1];

  // Reject events older than 5 minutes
  if (Math.abs(Date.now() - timestamp * 1000) > 5 * 60 * 1000) return false;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex');

  return crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(signature, 'hex'));
}

Retry policy

  • At-least-once delivery. Design handlers to be idempotent.
  • Up to 5 attempts with exponential backoff (1s → 10s → 60s → 10m → 1h).
  • Response 2xx = delivered. Any other status = retry. Response 410 Gone = permanent failure; retries stop.

Security

Outbound webhooks from BossMode are signed with HMAC-SHA256, using the same signing approach as AvatarCzar inbound events. Verify the X-BossMode-Signature header on your receiving endpoint.