BEXO / Developers
BUILD WITH BEXO / INTEGRATION GUIDES

Receive signed vendor events

Receive configured operational events without turning an event notification into a second source of entitlement truth.

Reference edition 2026-10-19 • Selected public contract
webhooksHMACeventsERP

Arrange endpoint configuration first

Outbound vendor events require a configured endpoint, subscribed event types and an agreed signing secret. This public reference does not define a self-service webhook registration API. Confirm enablement with BEXO before relying on event delivery.

The committed dispatcher emits verification.allowed and verification.denied for normal POS results. Event availability is configuration-dependent. Do not assume that suggested event names, such as membership.activated, are emitted merely because an integration plan mentions them.

Headers and event envelope

HeaderMeaning
Content-Type: application/jsonJSON event body.
X-Bexo-Event-IdEvent ID; must match the signed body id.
X-Bexo-Event-TypeEvent type; must match the signed body type.
X-Bexo-Signaturesha256= followed by the HMAC-SHA256 hexadecimal digest of the raw request body.
JSON
{
  "id": "11111111-1111-4111-8111-111111111111",
  "type": "verification.denied",
  "occurredAt": "2026-10-19T09:00:00Z",
  "data": {
    "tenantId": "22222222-2222-4222-8222-222222222222",
    "terminalId": "33333333-3333-4333-8333-333333333333",
    "terminalLabel": "Reception",
    "verificationLogId": "44444444-4444-4444-8444-444444444444",
    "decision": "deny",
    "reason": "member_not_found",
    "occurredAt": "2026-10-19T09:00:00Z"
  }
}

This is a synthetic example. Regular verification event data contains operational references and a result; do not expect a complete member profile or a raw card identifier in the event.

Verify exact request bytes

Capture the raw bytes before JSON parsing. Do not reserialize a parsed object for HMAC verification: whitespace and byte ordering matter. Use constant-time comparison and reject malformed signatures before processing the payload.

JavaScript
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyBexoEvent(rawBody, signature, secret) {
  if (!Buffer.isBuffer(rawBody)) throw new Error('Raw bytes required');
  if (!/^sha256=[a-f0-9]{64}$/.test(signature || '')) return false;
  const expected = createHmac('sha256', secret).update(rawBody).digest();
  const received = Buffer.from(signature.slice(7), 'hex');
  return expected.length === received.length &&
    timingSafeEqual(expected, received);
}

Load the secret from your server’s secret store. Do not put it in client code or return it from a diagnostics endpoint. After verifying, parse the signed body and validate the event/tenant against your configured integration.

Acknowledge, deduplicate and reconcile

  1. Reject an invalid signature or an unexpected tenant.
  2. Check that header IDs/types match the signed body.
  3. Durably record the event ID and enqueue permitted work before returning a 2xx response.
  4. Treat an event already durably accepted as a duplicate and acknowledge it without repeating side effects.
  5. Reconcile access/payment facts through the supported API when needed. Do not grant membership from a free-form event name.

The dispatcher uses a 10-second request timeout. Failed attempts record delivery status and retry metadata; this reference does not promise a completed automatic retry schedule, delivery order or delivery SLA. Coordinate recovery/replay with BEXO. A valid signature does not itself prevent replay—event-ID deduplication is required.

Build with a clear contract.

Configuration, approval and deployed behavior determine availability. Validate your own integration before release.

Review the launch checklist ↗

Reference source: b93a4d3 · Examples use synthetic data.