ATS Webhooks That Dont Break Verification or Hiring SLAs
A practical integration pattern for getting verification signals into your ATS reliably, with audit-grade event trails and rollback controls.

If verification is not idempotent, you are one webhook retry away from a recruiter override and an audit headache.Back to all posts
The incident you do not want on a Monday morning
A VP pings you: "Why did the ATS show Verified at 9:02, then Needs Review at 9:05, then Verified again at 9:06?" Recruiting already sent the calendar invite. The hiring manager already met the candidate. Security is asking whether the identity check was bypassed. Nothing "mystical" happened. Your verification service retried a webhook after a 504, the ATS processed the same event twice, and a well-meaning recruiter manually flipped a status to keep the funnel moving. Now you have funnel leakage, reviewer fatigue, and an audit finding waiting to happen. Recommendation: integrate verification as signed events with idempotent processing, and store every transition in an append-only event log so you can explain exactly what happened, when, and why.
What you will build in one integration sprint
You will implement a verification-to-ATS bridge that (1) receives signed webhooks, (2) deduplicates events using idempotency keys, (3) updates ATS fields only via deterministic state transitions, (4) records an immutable event log for every decision and override, and (5) supports rollback controls and degraded mode when systems are down. This is how you protect time-to-interview while keeping a defensible story when a candidate disputes a decision or a regulator asks for process evidence.
Speed: verification completes before interviews without turning scheduling into a bottleneck
Cost: fewer last-minute reschedules and fewer bad hires that require replacement
Risk: fewer bypasses and clearer evidence when you need to terminate or defend a decision
Reputation: consistent, explainable outcomes across teams and geographies
Why this is now a board-level hygiene issue
Checkr reports that 31% of hiring managers say they have interviewed a candidate who later turned out to be using a false identity. Directionally, that implies identity risk is not rare noise in modern hiring, especially in high-velocity pipelines. It does not prove your organization has a 31% fraud rate, and it is survey-based, so treat it as a risk signal, not a prediction. Pindrop notes that 1 in 6 applicants to remote roles showed signs of fraud in one real-world pipeline. The implication is that remote, asynchronous hiring widens the attack surface and creates incentives for proxy behavior. It does not mean 1 in 6 of your applicants are fraudsters, because pipelines, geographies, and role types vary widely. Recommendation: assume some level of adversarial behavior will hit your funnel, and design your integrations so exceptions are handled with evidence, not improvisation.
Ownership and flow that will not collapse under pressure
Recommendation: make Recruiting Ops the process owner, Security the control owner, and Hiring Managers the decision consumers. If you do not set this explicitly, overrides will happen in the shadows and your event trail will be incomplete.
Recruiting Ops: workflow design, ATS fields, SLA for manual review queue, exception playbooks
Security: biometric and data retention approvals, access control reviews, incident response tie-in
Hiring Manager: consumes outcomes (Verified, Needs Review, Failed) and follows the escalation path
Automated: webhooks received, identity verification results posted to ATS, scheduling gate checks, candidate notifications
Manual review: only risk-tiered exceptions (mismatched signals, low liveness confidence, document anomalies), with required reason codes
No manual work: deduplication, retries, reconciliation, and evidence pack assembly should be system behavior
ATS: candidate lifecycle state (applied, phone screen, onsite, offer) and recruiter actions
Verification service: verification evidence and decisioning signals (document, face, voice, liveness, fraud flags)
Event log: the immutable record of what was received, what was written, and what was overridden
Reference architecture: signed events, idempotent writes, append-only logs
Recommendation: model verification as an event stream and keep writes into the ATS idempotent. The ATS gets the latest state for workflow speed, while your event log keeps the full timeline for defensibility. Core pattern: Verification Service -> Webhook Receiver -> Event Store -> State Machine -> ATS/HRIS Updater -> Observability. Design for resilient connectivity: when the ATS is down or rate-limited, you queue events and replay safely. Your recruiters should see a clear "Verification pending sync" state, not a blank field that triggers bypass behavior.
event_id, event_type, occurred_at, received_at, signature_valid
candidate_id, application_id, external_ats_ids
idempotency_key, delivery_attempt, processing_result
state_before, state_after, write_targets (which ATS objects were updated)
override_actor, override_reason_code, override_timestamp (if applicable)
trace_id spanning webhook -> event store -> ATS write
Implementation sequence that survives retries and outages
Recommendation: implement this in four steps, in this order, so you get safety first and speed second without rework.

Pick one canonical internal key: candidate_id + application_id (not email). Email changes and aliases create merge bugs.
Map ATS entities: Candidate, Application, Interview, Offer. Decide which object stores verification state.
Define allowed states and transitions: unverified -> pending -> verified OR needs_review OR failed. Avoid recruiter-created custom statuses that bypass gates.
Define Risk-Tiered Verification triggers: step-up only when signals warrant it, not for every role.
Verify signatures on every webhook and reject unsigned payloads.
Require an idempotency_key per event and store it before processing so duplicates short-circuit fast.
Persist the raw payload hash for forensics, but keep sensitive biometrics out of your logs.
Return 2xx only after the event is committed to your event store, not after downstream ATS writes complete.
Use an idempotent upsert keyed by (application_id, verification_check_id). Never "append" status notes without keys.
Apply compare-and-set semantics: only advance the state machine forward unless an override flow is invoked.
Write minimal fields to the ATS: current_state, decision_timestamp, evidence_pack_link, reviewer_queue_link.
Prefer OAuth/OIDC to API keys for ATS connectors. API keys tend to get shared and become un-auditable.
Kill switch: one flag to stop gating interviews on verification if you have a platform outage, while still collecting events.
Canary rollout: enable gating for 5-10% of roles or one region first (illustrative example), then expand.
Reconciliation job: nightly diff between event store and ATS fields; auto-heal missing writes.
Dashboards: webhook failure rate, duplicate event rate, manual review volume, median time from apply -> verified.
Webhook ingestion policy you can hand to Engineering
This policy is designed for a PeopleOps goal: keep the funnel moving while preventing duplicate writes and preserving a clean audit trail.
Anti-patterns that make fraud worse
Recommendation: eliminate these three patterns before you scale verification across roles.
Using email as the primary key across ATS and verification, which makes merges and impersonation easier when aliases change mid-process
Letting recruiters override verification outcomes without reason codes and without writing an override event to the log
Treating verification as a single ATS checkbox with no event history, which makes retries look like "flip-flopping" and invites bypasses
Where IntegrityLens fits
IntegrityLens AI ("Verify Candidates. Screen Instantly. Hire With Confidence.") is the first hiring pipeline that combines a full Applicant Tracking System with advanced biometric identity verification, AI screening, and technical assessments. For this integration pattern, IntegrityLens acts as both the workflow system and the evidence system, so webhooks, event logs, and Risk-Tiered Verification live in one defensible pipeline used by TA leaders, recruiting ops, and CISOs. In practice, teams use IntegrityLens to:
Run ATS workflow end-to-end, from source candidates to offer
Verify identity in under three minutes before interviews (typical document + voice + face in 2-3 minutes)
Launch 24/7 AI interviews instantly across timezones without losing traceability
Deliver coding assessments across 40+ languages with integrity signals attached
Generate Evidence Packs and push outcomes to external ATS/HRIS via Idempotent Webhooks
Operational impact you should expect (without fantasy ROI)
In a typical PeopleOps operating model, the measurable win is not a magical percentage reduction. It is fewer integrity-related fire drills and faster resolution when something looks off. Before: recruiters see inconsistent verification statuses, candidates get rescheduled, Security cannot reconstruct who approved what, and exceptions live in inboxes. After: verification decisions arrive as replay-safe events, ATS fields stay consistent, manual reviews are routed with SLAs, and every change is backed by an Evidence Pack link and an event log line item.
Lower duplicate webhook processing and fewer "status flip" tickets
Shorter time-to-clear for manual review cases due to centralized evidence
Fewer interview cancellations driven by last-minute identity uncertainty
Cleaner audit responses because you can export an event timeline per candidate
Sources
31% of hiring managers say theyve interviewed a candidate who later turned out to be using a false identity. Checkr (2025): https://checkr.com/resources/articles/hiring-hoax-manager-survey-2025 1 in 6 applicants to remote roles showed signs of fraud in one real-world hiring pipeline. Pindrop: https://www.pindrop.com/article/why-your-hiring-process-now-cybersecurity-vulnerability/
Related Resources
Key takeaways
- Treat verification as an event stream, not a one-time status field, so retries, outages, and appeals stay defensible.
- Use idempotency keys and deterministic state transitions to prevent duplicate updates and recruiter confusion.
- Keep the ATS as the workflow source of truth, but keep the verification provider as the evidence source of truth.
- Design for degraded mode: when the ATS is down, you should still verify, queue events, and reconcile later.
- Make exceptions explicit: manual review should be a routed queue with SLAs, not a Slack thread.
Use this as a control spec for Engineering and Security: what to accept, what to log, and how to update the ATS without duplicates.
It includes replay protection, deterministic state transitions, degraded mode behavior, and a kill switch for incident response.
policyVersion: "1.3"
service: "verification-webhook-bridge"
owner:
processOwner: "Recruiting Ops"
controlOwner: "Security"
approver: "PeopleOps/CHRO"
webhookSecurity:
signature:
required: true
algorithm: "HMAC-SHA256"
header: "X-IL-Signature"
replayProtection:
required: true
maxSkewSeconds: 300
timestampHeader: "X-IL-Timestamp"
ipAllowlist:
enabled: false # prefer signatures over brittle IP lists
idempotency:
keyField: "idempotency_key"
store: "event_log"
onDuplicateKey: "ack-and-skip" # do not re-run ATS writes
eventLog:
storage: "append-only"
retentionDays: 365
piiRedaction:
redactFields:
- "biometric_templates"
- "raw_document_image"
- "raw_face_image"
storeHashesOnly: true
requiredFields:
- event_id
- event_type
- occurred_at
- received_at
- candidate_id
- application_id
- idempotency_key
- signature_valid
- processing_result
- trace_id
stateMachine:
allowedStates:
- "unverified"
- "pending"
- "verified"
- "needs_review"
- "failed"
allowedTransitions:
- from: "unverified"
to: ["pending"]
- from: "pending"
to: ["verified", "needs_review", "failed"]
- from: "needs_review"
to: ["verified", "failed"]
downgradeRequiresOverrideEvent: true
actions:
onEventType:
verification.started:
atsUpdate:
fields:
verification_state: "pending"
verification_last_event_id: "${event_id}"
verification.decision:
atsUpdate:
fields:
verification_state: "${decision_state}" # verified|needs_review|failed
verification_decided_at: "${occurred_at}"
evidence_pack_url: "${evidence_pack_url}"
verification_last_event_id: "${event_id}"
ifDecisionStateIs: "needs_review"
routeToQueue:
queue: "manual-review"
slaHours: 12
requiredReasonCodes: ["liveness-low", "doc-anomaly", "voice-mismatch", "name-dob-mismatch"]
resiliency:
atsWriteTimeoutMs: 4000
onAtsDown:
behavior: "queue-for-retry"
maxRetryAttempts: 12
backoff: "exponential-jitter"
candidateFacingStatus: "pending-sync"
reconciliation:
enabled: true
schedule: "0 2 * * *"
mode: "diff-and-heal"
controls:
killSwitch:
flag: "verification_gating_enabled"
default: true
whenOff:
allowInterviewScheduling: true
continueCollectingEvents: true
requireBannerInATS: "Verification gating disabled - events still logging"
observability:
tracing:
propagateHeader: "X-Trace-Id"
metrics:
- "webhook.signature_invalid.count"
- "webhook.duplicate_event.count"
- "ats.write.failure.count"
- "manual_review.queue.depth"
- "time.apply_to_verified.median"
Outcome proof: What changes
Before
Verification outcomes arrive inconsistently across tools, ATS fields are updated manually, and webhook retries create confusing status changes that trigger recruiter bypasses and interview reschedules.
After
Verification is integrated as signed, idempotent events with an append-only log. ATS states are deterministic, exceptions route to a manual review queue with SLAs, and each decision links to an Evidence Pack for audit and appeals.
Implementation checklist
- Define canonical candidate and application IDs across ATS and verification
- Implement webhook signature verification and replay protection
- Use idempotency keys for every write into ATS/HRIS
- Create an append-only event log for every verification decision and override
- Add kill switch and canary rollout flags for verification gating
- Instrument trace IDs so Ops can follow one candidate across systems
Questions we hear from teams
- What is idempotency in ATS integrations?
- Idempotency means the same webhook event can be processed multiple times without changing the final result more than once. In hiring integrations, it prevents duplicate status flips, duplicate notes, and accidental gating bypasses when providers retry deliveries.
- What happens when the ATS is down during verification?
- Your webhook receiver should still accept and commit events to an event log, then queue ATS updates for retry with backoff. Recruiters should see a clear pending-sync state so they do not manually bypass controls to keep interviews moving.
- Should the ATS store the full verification evidence?
- Typically no. Store the decision, timestamps, and a secure link to an Evidence Pack, while keeping detailed evidence in the verification system with strict access controls and retention rules.
Ready to secure your hiring pipeline?
Let IntegrityLens help you verify identity, stop proxy interviews, and standardize screening from first touch to final offer.
Watch IntegrityLens in action
See how IntegrityLens verifies identity, detects proxy interviewing, and standardizes screening with AI interviews and coding assessments.
