Your webhook issue requires systematic troubleshooting across all three critical areas:
1. Webhook Event Subscription:
The event name you’re using may not be correct for adp-2023.2. ADP’s recruiting webhook events follow a specific taxonomy:
recruiting.candidate.created - New candidate added
recruiting.candidate.updated - Any candidate field updated (this is what you likely need)
recruiting.application.statusChanged - Application status changed (different from candidate status)
recruiting.candidate.workflow.transitioned - Candidate moved between workflow stages
The event name candidate.status.changed doesn’t exist in ADP’s standard event catalog. You need to subscribe to recruiting.candidate.updated which fires on any candidate record change, including status updates. However, this gives you all updates, so you’ll need to filter in your endpoint code.
Alternatively, use recruiting.candidate.workflow.transitioned if you only care about major status changes that move candidates between workflow stages (Applied → Phone Screen → Interview → Offer → Hired). Minor status updates within a stage won’t trigger this event.
Update your subscription:
{
"webhookId": "wh_abc123",
"endpoint": "https://our-domain.com/webhooks/adp",
"events": [
"recruiting.candidate.updated",
"recruiting.candidate.workflow.transitioned"
],
"status": "active",
"filters": {
"fieldChanges": ["status", "workflowStage"]
}
}
Note the filters object - ADP supports filtering events by which fields changed, reducing noise at your endpoint.
2. Endpoint Registration:
Your endpoint registration looks correct, but verify these requirements:
a) HTTPS with valid certificate: ADP requires TLS 1.2+ with certificates from recognized CAs. Self-signed certificates fail silently.
b) Response requirements: Your endpoint must:
- Respond with HTTP 200-299 within 5 seconds
- Return empty body or simple JSON acknowledgment
- Not perform long-running processing in the request handler
c) Header validation: ADP sends webhook signature headers for security:
X-ADP-Signature: sha256=abc123...
X-ADP-Timestamp: 1620456789
X-ADP-Event-Type: recruiting.candidate.updated
Your endpoint should validate the signature to ensure requests are from ADP. If your validation logic rejects the request, events will fail.
d) IP whitelisting: ADP webhook requests come from specific IP ranges. Add these to your firewall allowlist:
- 52.206.x.x/16 (US East)
- 54.241.x.x/16 (US West)
- Contact ADP support for complete current IP ranges
e) Endpoint path: Ensure your endpoint path exactly matches registration. ADP doesn’t follow redirects, so if your server redirects /webhooks/adp to /webhooks/adp/, events will fail.
3. Event Filtering:
ADP’s recruiting module has complex event filtering logic:
a) Workflow stage filtering: Not all status changes trigger events. Changes must meet one of these criteria:
- Candidate moves between major workflow stages
- Status field explicitly marked as “webhook-enabled” in ADP configuration
- Change made via API (UI changes may be batched or filtered)
b) Batch operation exclusion: Status changes made through bulk operations, imports, or automated workflows may not trigger individual webhook events. They might trigger a single batch event instead.
c) Permission-based filtering: Webhook events only fire for candidates the webhook registration user has permission to view. If your API user doesn’t have access to all recruiting positions, you won’t receive events for those candidates.
Diagnostic steps:
-
Test with API-triggered changes: Instead of changing status in the UI, make a status change via API call and see if the webhook fires. This isolates whether the issue is with event generation or delivery.
-
Check ADP webhook logs: In ADP’s developer console, navigate to Webhooks → Delivery Logs. This shows:
- Whether events were generated
- Delivery attempts and response codes
- Failure reasons
If no logs appear, events aren’t being generated (subscription issue). If logs show 4xx/5xx responses, your endpoint has problems.
-
Implement webhook testing endpoint: Temporarily point your webhook to a service like webhook.site or requestbin.com to verify ADP is sending events. If events appear there but not at your endpoint, the issue is with your server configuration.
-
Verify tenant-level settings: Contact ADP support to confirm:
- Webhooks are enabled for your tenant
- Your API user has webhook administration permissions
- Recruiting module is configured to generate webhook events
- No tenant-level filters are blocking events
-
Test signature validation: Temporarily disable signature validation in your endpoint code to rule out authentication issues. If events start arriving, your signature validation logic is incorrect.
Recommended implementation:
app.post('/webhooks/adp', (req, res) => {
// 1. Immediately respond to ADP (don't make them wait)
res.status(200).json({ received: true });
// 2. Validate signature asynchronously
const signature = req.headers['x-adp-signature'];
const timestamp = req.headers['x-adp-timestamp'];
if (!validateSignature(req.body, signature, timestamp)) {
logger.error('Invalid webhook signature');
return;
}
// 3. Queue for async processing
eventQueue.push({
eventType: req.headers['x-adp-event-type'],
payload: req.body,
receivedAt: new Date()
});
});
This pattern ensures you respond quickly to ADP while processing events asynchronously, preventing timeout issues.
If after these steps events still don’t arrive, open a support ticket with ADP including your webhook ID, tenant ID, and specific candidate IDs you’ve tested with. There may be tenant-specific configuration issues only they can diagnose.