Webhooks Architecture
Detailed documentation on consuming Trackr webhooks, including events, security, signature verification, and idempotency.
Webhooks System
Trackr's Webhook System allows developers to build external integrations and event-driven applications by subscribing to real-time notifications about events happening within a Trackr workspace. Instead of continuously polling our REST API for changes, you can configure Trackr to send HTTP POST requests to your endpoints whenever specific events occur (e.g., when a job application status changes or an interview is scheduled).
This document outlines the architecture, available events, security practices, and implementation guidelines for consuming Trackr Webhooks.
Architecture & Delivery Mechanism
When an action occurs in Trackr (e.g., a user updates an application), an event is dispatched to our internal message broker (Apache Kafka). The Webhook Dispatcher service consumes these events, looks up active webhook subscriptions for the relevant user/tenant, and queues an HTTP delivery task.
Delivery Guarantees
Trackr guarantees at-least-once delivery for all webhooks. This means that under certain network conditions or failure scenarios, you might receive the exact same webhook payload more than once. Because of this, it is critical that your receiving endpoint implements idempotency (discussed below).
Retry Policy
If your endpoint fails to respond with a 2xx HTTP status code, or times out after 5 seconds, Trackr will attempt to redeliver the webhook payload.
Our backoff schedule is exponential:
- Immediately after failure
- 1 minute later
- 5 minutes later
- 30 minutes later
- 2 hours later
- 12 hours later
If all retries fail, the webhook delivery is marked as failed, and an alert can be sent to your integration dashboard. The event will remain in your delivery history for manual replay up to 14 days.
Available Events
Webhooks are categorized by the entity they relate to. You can subscribe to specific events or use the wildcard * to receive all events for a given entity.
job_application.*
job_application.created: Fired when a new job application is added to Trackr.job_application.status_changed: Fired when an application moves from one status to another (e.g., from 'applied' to 'interviewing').job_application.deleted: Fired when an application is permanently deleted.
interview.*
interview.scheduled: Fired when a new interview is scheduled.interview.rescheduled: Fired when the date or time of an interview changes.interview.completed: Fired when an interview is marked as completed and feedback is saved.
resume.*
resume.uploaded: Fired when a new resume is uploaded and processed.resume.parsed: Fired when the AI parsing engine finishes extracting data from a resume.
Webhook Payload Structure
All webhooks are sent as HTTP POST requests with a Content-Type of application/json. The payload follows a standard envelope structure:
{
"event_id": "evt_9f83a2b1c4d5e6f7",
"event_type": "job_application.status_changed",
"created_at": "2024-03-15T14:32:01Z",
"workspace_id": "ws_1234567890",
"data": {
"application_id": "app_9876543210",
"previous_status": "applied",
"new_status": "interviewing",
"company_name": "Acme Corp",
"role_title": "Senior Frontend Engineer"
}
}event_id: A unique, immutable identifier for the specific occurrence of the event. Use this for idempotency checks.event_type: The dot-separated string denoting the event.data: The specific payload payload associated with the event. The structure of this object changes depending on theevent_type.
Security and Authentication
Webhook endpoints are publicly accessible by definition, so you must verify that incoming requests are genuinely from Trackr and have not been tampered with.
1. HTTPS Required
Trackr will only deliver webhooks to URLs that begin with https://. We enforce TLS 1.2 or higher for all outbound connections.
2. Signature Verification
To verify the authenticity of the payload, Trackr cryptographically signs every webhook using Hash-based Message Authentication Code (HMAC) with SHA-256.
When you register a webhook endpoint, Trackr generates a unique Webhook Secret for that endpoint. You use this secret to verify the signature on incoming requests.
Trackr includes several headers in the request:
Trackr-Signature: The computed HMAC-SHA256 signature.Trackr-Timestamp: The Unix timestamp (in seconds) when the webhook was dispatched.Trackr-Event-Id: Matches theevent_idin the JSON payload.
How to verify the signature (Node.js Example)
const crypto = require('crypto');
function verifyTrackrWebhook(rawBody, signatureHeader, timestampHeader, webhookSecret) {
// 1. Prevent replay attacks: Check if timestamp is within 5 minutes (300 seconds)
const currentTimestamp = Math.floor(Date.now() / 1000);
if (currentTimestamp - parseInt(timestampHeader) > 300) {
throw new Error('Webhook timestamp is too old (possible replay attack)');
}
// 2. Prepare the payload string for signing
// Format: `${timestamp}.${rawBody}`
const payloadToSign = `${timestampHeader}.${rawBody}`;
// 3. Compute the expected signature
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(payloadToSign)
.digest('hex');
// 4. Compare using constant-time comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(signatureHeader)
);
}Critical Note: You must use the raw request body string (before it is parsed into JSON by middleware like body-parser) to compute the signature. Even a single changed whitespace character will cause the signature validation to fail.
Implementing Idempotency
Because Trackr guarantees at-least-once delivery, you may receive the same event_id multiple times. Your system must be idempotent, meaning processing the same event multiple times has the same outcome as processing it once.
Best Practices for Idempotency:
- Log the
event_id: Maintain a database table or Redis cache of recently processedevent_ids (store them for at least 7 days). - Check before processing: When a webhook arrives, check if the
event_idexists in your log. - Return 200 OK early: If you have already processed the event, immediately return a
200 OKstatus without executing your business logic again. - Use Database Transactions: Ensure that logging the
event_idand performing the business logic happen within the same atomic database transaction.
Testing Webhooks
Developing webhook receivers locally can be challenging because your local server (e.g., localhost:3000) is not exposed to the public internet for Trackr to reach.
We recommend using the Trackr CLI to forward webhook events to your local machine:
# Authenticate the CLI
trackr login
# Listen for webhooks and forward them to your local server
trackr webhooks listen --forward-to http://localhost:3000/api/webhooksAlternatively, you can use third-party tunneling tools like Ngrok (ngrok http 3000) or Localtunnel to generate a temporary public URL that you can register in the Trackr Dashboard.
Replay Functionality
In the Trackr Developer Dashboard, you can view a log of all webhooks sent to your endpoints. If a webhook failed, or if you are testing your handler, you can click the "Replay" button to force Trackr to resend the exact same payload and headers.
Conclusion
By following these guidelines—securing your endpoint with HTTPS, strictly verifying HMAC signatures, and implementing idempotency—you can build robust, highly-available integrations powered by Trackr's real-time Webhook system.