Glozr docs

API reference

Outgoing webhooks

Glozr fires outgoing webhooks when interesting things happen in your workspace. Configure them in /app/integrations/webhooks; every payload is HMAC-signed so you can verify it actually came from Glozr.

Current surface

The v1 webhook surface supports a single event type: lead.captured. Delivery is single-attempt — no automatic retries — and every payload is signed with HMAC-SHA256. Conversation-level events are on the roadmap but not yet available.

Configuration

Each webhook subscription needs:

  • A destination URL. HTTPS is strongly recommended.
  • An event type (currently only lead.captured).
  • An auto-generated signing secret, used to verify every delivery.
  • An active toggle so you can pause deliveries without deleting the subscription.

Request headers

Every dispatch carries two headers:

  • Content-Type: application/json
  • X-Pitchbar-Signature — timestamped HMAC, format t=<unix_ts>,v1=<hex_sig>.

Verifying the signature

The signed string is "{timestamp}.{raw_request_body}", hashed with HMAC-SHA256 using your signing secret.

const crypto = require('crypto');

function verify(rawBody, header, secret) {
  const [tPart, sigPart] = header.split(',');
  const t = Number(tPart.split('=')[1]);
  const sig = sigPart.split('=')[1];

  // Reject anything older than 5 minutes
  if (Math.abs(Date.now() / 1000 - t) > 300) return false;

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

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

Two things to keep in mind: always use a constant-time comparison (Node's timingSafeEqual, PHP's hash_equals, etc.), and reject any delivery whose timestamp is more than 5 minutes off to defeat replay attacks.

Delivery pattern

Webhooks are a single HTTP POST with a 5-second timeout. There is no built-in retry, so build your receiver defensively:

  • Return 2xx as quickly as possible. Acknowledge first, process later.
  • Push the work into your own queue so a slow downstream system doesn't time out the webhook.
  • Deduplicate on occurred_at + lead ID in case Glozr fires the same event twice.
  • For critical data, periodically reconcile with the admin leads endpoint.

Event payload

The lead.captured payload includes:

  • event"lead.captured".
  • occurred_at — ISO-8601 timestamp.
  • lead_id and agent_id.
  • conversation_id — the conversation that produced the lead.
  • fields — captured form fields: name, email, phone, plus any custom fields you configured.

Roadmap

Planned for upcoming releases:

  • Conversation-level events (conversation.started, conversation.escalated).
  • Per-delivery IDs in headers, for safer deduplication.
  • At-least-once retry semantics with exponential backoff and dead-letter delivery for permanent failures.