HiringCenter Webhooks Overview
HiringCenter Outbound Webhooks
HiringCenter can notify your systems in real time when events happen in your account—for example when a prospect is created or a task is completed. The platform POSTs signed JSON to HTTPS URLs you configure. Your server is the receiver; HiringCenter is the caller.
This is separate from the REST API paths you call with an API key. For REST resources (prospects, notes, tasks, and so on), see the HiringCenter API Overview.
You can also use polling (GET /webhooks/poll) for Zapier-style integrations that pull recent prospect data instead of accepting push deliveries.
Configure a Webhook Subscription
Create and manage webhook subscriptions in HiringCenter as an account admin or owner:
Settings → API / Webhooks
For each subscription you provide:
- Webhook URL — your public HTTPS endpoint (
hookUrl) - Event types — which events to receive (for example
prospect.created) - Endpoint secret — a per-subscription signing secret (
whsec_...) used to verify deliveries
The endpoint secret is shown once when the subscription is created or rotated. Store it securely on your server (environment variable or secrets manager). HiringCenter encrypts secrets at rest and does not return the full plaintext secret on later reads.
Webhook subscription management (subscribe, rotate, test) uses Firebase authentication in the app or master-key access. It is not available with API key authentication.
Endpoint Secret
- Format:
whsec_followed by random hex characters - Purpose: verify that each
POSTto your URL was signed by HiringCenter - Rotation: rotating a secret starts a 24-hour grace period during which deliveries may include signatures for both the new and previous secret (see Secret rotation)
HTTP Request Your Endpoint Receives
When an subscribed event fires, HiringCenter sends:
| Item | Value |
|---|---|
| Method | POST |
Content-Type | application/json |
User-Agent | HiringCenter-Webhook/2.0 |
X-HiringCenter-Signature | t=<unix_seconds>,v1=<hex_hmac> |
| Body | JSON event envelope (see below) |
Delivery rules
- Only active subscriptions (
subscribed: true) whose event list includes the fired type receive the request. - The target URL must be public HTTPS. Private or local hosts are rejected when the subscription is saved.
- Request timeout is 10 seconds.
- There is no automatic retry queue for failed deliveries.
- The signature is computed over the exact UTF-8 bytes in the body (a single
JSON.stringifyon the server).
Respond with 2xx after you accept the event. You can process the payload asynchronously. Non-2xx responses are logged as failed deliveries.
Event Types
| Event type | When it is sent |
|---|---|
prospect.created | A prospect is created (API, import, in-app, etc.). After a short consistency delay, HiringCenter loads the prospect and dispatches unless webhooks are muted for that record. |
prospect.updated | A prospect is updated. Payload includes field-level changes and the current prospect snapshot. |
task.created | A task is created via the API. |
task.updated | A task is updated. |
task.completed | A task is marked completed. |
task.deleted | A task is deleted. |
general | Test deliveries and generic subscriptions. |
These aliases normalize to prospect.created: prospect_created, prospect-created, new_prospect, new-prospect.
Event Payload Envelope
Every outbound delivery uses the same top-level shape:
Code
| Field | Description |
|---|---|
id | Unique id for this delivery (not the prospect or task id). |
type | Event type from the table above. |
apiVersion | Payload schema version (currently 2025-10-28). |
createdAt | ISO 8601 timestamp when the envelope was built. |
accountId | HiringCenter account that owns the resource. |
resource | Resource family (for example prospect for prospect.created). |
resourceId | Primary resource id when present in data (for example prospectId). |
data | Event-specific payload (shape depends on type). |
prospect.created
Code
data.prospect is the prospect record as stored in HiringCenter (firstName, lastName, email, phone, stageId, ownerId, and other fields). Additional fields may appear over time; treat unknown keys as optional.
prospect.updated
data includes:
prospectIdchanges— field-level before/after values for changed fieldsprospect— current prospect snapshot after the update
Task events
Task payloads include taskId and event-specific fields (task, updates, links, and so on). Test deliveries use sample data shaped like production events.
Suppressing Outbound Webhooks
To create a prospect without firing prospect.created webhooks, set muteWebhook on the create request:
Code
HiringCenter stores muteWebhook on the prospect document. The prospect.created trigger skips POSTing to your endpoints for that record.
Signature Verification
Every outbound POST includes an X-HiringCenter-Signature header:
Code
Each v1 value is:
Code
Where:
endpointSecretis your subscription secret (whsec_...)tis Unix time in seconds (same value as in the header)rawBodyis the exact request body as received—do not parse JSON and re-serialize before verifying
Secret rotation
During a 24-hour grace period after you rotate a secret, the header may include multiple v1 values:
Code
Accept the request if any v1 matches a valid signature computed with the current or previous secret.
Verification steps
- Read the raw body before middleware mutates it (
express.raw,req.text(), etc.). - Read
X-HiringCenter-Signature. - Parse
tand everyv1from the header (comma-separatedkey=valueparts). - Reject if the header is malformed or has no
v1. - Reject replayed requests:
abs(nowUnixSeconds - t) > toleranceSeconds(recommended 300 seconds). - Compute
expected = HMAC_SHA256(endpointSecret, t + "." + rawBody)as lowercase hex. - Compare
expectedto eachv1using a constant-time comparison; accept if any match. - Only then
JSON.parse(rawBody)and branch onevent.type/event.data.
Common verification failures
- Verifying against parsed or re-stringified JSON instead of the raw body
- Middleware that consumes or reformats the body before verification
- Ignoring timestamp tolerance (replay risk)
- Comparing signatures with a normal string equality check instead of constant-time compare
- Accepting only the first
v1during rotation grace
Node.js helper
Code
Express example
Code
Polling Alternative (Zapier)
If your integration cannot accept inbound HTTPS requests, poll recent prospect data with your API key:
Base URL: https://api.hiringcenterpro.com/v2
Code
Poll responses use a flat snake_case prospect record (first_name, last_name, created_at, and so on), not the push event envelope above. Timestamp fields in poll payloads may be ISO 8601 strings.
Supported poll eventType values currently include prospect.created (default).
Testing a Subscription
Send a production-shaped signed test delivery from HiringCenter (admin/owner in the app, or authorized internal tooling):
- Method:
POST - Path:
/webhooks/{subscriptionId}/test
The response includes the payload, request headers (including X-HiringCenter-Signature), and the HTTP status returned by your endpoint.
Test payloads include metadata.isTest: true in data where applicable.
Related Documentation
- OpenAPI spec:
docs/openapi.yaml(Webhooks tag andOutboundWebhookEventschema) - Verification reference:
docs/VERIFYING_WEBHOOKS.md - Security architecture:
docs/SECURITY_OUTGOING_WEBHOOKS.md

