InsightHireHelp Center

Outbound webhooks

Configure HTTPS webhooks for partner platforms to receive signed InsightHire events.

Outbound webhooks let partner systems (GlazierHire, PivotalMetrics, custom integrations) receive real-time notifications when candidates apply, complete journeys, or scores update. Org admins manage endpoints from Settings → Integrations in the Partner webhooks section.

Settings path

ActionLocation
Create / edit webhooks/dashboard/settings/integrations (Partner webhooks)
Dedicated webhooks page/dashboard/integrations/webhooks
Delivery logsSame UI — recent deliveries panel

Requires Org Admin role (orgAdminOrgProcedure).

Creating a webhook

Use the Settings UI or webhooks.create:

FieldRules
Name1–120 characters
URLHTTPS required (http://localhost allowed for development)
Secret8–256 characters; used for HMAC signing
EventsOne or more from event catalog
EnabledDefault true
DescriptionOptional, max 500 chars

InsightHire generates a signing secret (recommended: 64-char hex from 32 random bytes). Store the secret at creation — only a masked version is shown afterward.

Event catalog

Available events (webhooks.eventCatalog):

EventLabel
application.createdApplication created (candidate applied)
application.status_updatedApplication status changed
journey.startedJourney / assessment session started
journey.step.completedJourney step completed
journey.completedJourney completed
journey.failedJourney failed / rejected by score gate
score.updatedScores / results available

Subscribe only to events your partner endpoint handles — reduces noise and delivery cost.

Payload envelope

Every delivery uses a stable JSON envelope:

{
  "id": "evt_abc123",
  "event": "application.created",
  "timestamp": "2026-08-03T20:00:00.000Z",
  "organizationId": "org_uuid",
  "data": {
    "...": "event-specific fields"
  }
}

Partners should adapt to this shape rather than expecting per-partner custom schemas.

Signature verification (Stripe-style)

Headers on each POST:

HeaderValue
X-InsightHire-TimestampUnix seconds
X-InsightHire-Signaturet=<ts>,v1=<hex>
X-InsightHire-EventEvent type string
X-InsightHire-Delivery-IdDelivery row ID

Verification algorithm:

signed_payload = `${timestamp}.${rawBody}`
expected_sig = hex(HMAC-SHA256(secret, signed_payload))

Compare v1 from the signature header to expected_sig using constant-time comparison. Reject timestamps older than 300 seconds (configurable tolerance).

Reference implementation: outbound-webhook-signing.ts in insighthire-api.

Delivery lifecycle

  1. InsightHire emits event via emitOutboundWebhookEvent
  2. Matching webhooks (subscribed + enabled) get organization_webhook_deliveries rows
  3. deliverOutboundWebhook POSTs signed payload to partner URL
  4. Status: PENDINGSUCCESS / FAILED / RETRYING

Monitoring

  • webhooks.list — all org webhooks with delivery counts
  • webhooks.deliveries — recent attempts with HTTP status, error, attempts count
  • webhooks.retryDelivery — manual retry for failed delivery

Test ping

webhooks.sendTestEvent sends a signed test payload:

{
  "test": true,
  "message": "InsightHire webhook test ping",
  "webhookName": "My Partner Hook"
}

Use this to verify URL reachability and signature validation before going live.

Partner implementation checklist

  1. Expose HTTPS endpoint (TLS required in production).
  2. Persist organizationId + event id for idempotency.
  3. Verify signature before processing body.
  4. Respond 2xx within timeout — non-2xx triggers retry.
  5. Handle at-least-once delivery (duplicates possible on retry).

Example verification (Node.js)

const crypto = require('crypto');

function verifyInsightHireWebhook(rawBody, signatureHeader, secret, toleranceSec = 300) {
  const parts = Object.fromEntries(
    signatureHeader.split(',').map(p => {
      const [k, ...rest] = p.trim().split('=');
      return [k, rest.join('=')];
    })
  );
  const ts = Number(parts.t);
  const v1 = parts.v1;
  if (!Number.isFinite(ts) || !v1) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - ts) > toleranceSec) return false;
  const signed = `${ts}.${rawBody}`;
  const expected = crypto.createHmac('sha256', secret).update(signed, 'utf8').digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(v1, 'hex'));
}

CRUD operations

ProcedurePurpose
webhooks.eventCatalogList subscribable events
webhooks.listList org webhooks
webhooks.createRegister endpoint
webhooks.updateEdit URL, events, rotate secret
webhooks.deleteRemove webhook
webhooks.deliveriesDelivery log
webhooks.retryDeliveryRetry failed delivery
webhooks.sendTestEventTest ping

Inbound vs outbound

DirectionPurposeSettings
Outbound (this doc)InsightHire → partner URLPartner webhooks in Integrations
InboundVendor → InsightHire (LinkedIn apply, Accurate status, Greenhouse assessment)Vendor portal + API webhook routes

Inbound webhook stats: ats.webhooks.stats and ats.webhooks.recent.