Webhook-Driven Candidate Verification That Survives ATS Failures

A field-tested integration pattern for getting verification into your ATS or HRIS without duplicate actions, missing evidence, or brittle point-to-point glue.

IntegrityLens welcome visual
If you cannot replay a hiring decision from events, you cannot defend it when the workflow breaks under load.
Back to all posts

The day your ATS retried a webhook and your evidence split in two

Your ATS goes degraded for 27 minutes during peak scheduling. Webhooks back up, then replay. Two verification sessions are created for the same candidate, one passes and one flags, because the second run happened after the candidate changed networks and the device fingerprint shifted. Recruiting ops sees "verified," security sees "flagged," and the hiring manager sees a candidate already in panel interviews. This is the exact moment Analytics and Chiefs of Staff get dragged into a war-room question: "Which outcome is real, and can we prove it?" If the integration is not idempotent and your events are not correlated, you cannot answer that without manual log spelunking and a lot of reviewer fatigue. Recommended posture: design for replay. Assume every webhook will be delivered at least once, sometimes out of order, and sometimes after partial failures.

Build a verification spine: webhooks in, idempotent calls out, event log always-on

You should implement verification as an event-driven orchestration layer between your ATS/HRIS and the verification service, with three invariants: (1) every command is idempotent, (2) every event is logged with a correlation ID, and (3) the ATS remains the system of record for stage changes while verification remains the system of record for identity and fraud signals. This avoids the two most common failure modes: duplicate actions (double verification, double interview scheduling) and missing evidence (no defensible chain of custody when someone appeals or audit asks). If you only take one thing to your platform team: require an idempotency key for every create/update call, and store the result so retries are safe.

  • 31% of hiring managers reported interviewing someone who later turned out to be using a false identity (Checkr, 2025). This implies the risk is operationally common enough that you should engineer for it, not treat it as a rare edge case. It does not prove your org will see the same rate, or that every flagged case is malicious.

  • 1 in 6 applicants to remote roles showed signs of fraud in one real-world pipeline (Pindrop). This suggests remote hiring amplifies identity and impersonation risk and that detection often relies on pipeline instrumentation. It does not mean "1 in 6" generalizes across industries, geographies, or seniority bands.

Who owns what, what is automated, and where truth lives

To keep the pipeline fast and defensible, assign ownership by failure mode, not by tool. Recruiting Ops owns stage automation and candidate comms. Security owns verification policy, access controls, and exception handling. Hiring managers own interview decisions, but should not adjudicate identity disputes ad hoc. Automation should do the boring, repeatable steps: trigger verification at defined stages, enforce risk-tiered gates, and attach Evidence Pack links back to the ATS. Manual review should be reserved for exceptions: mismatched identity, liveness uncertainty, or high-risk roles requiring step-up verification. Sources of truth should be explicit: the ATS is the system of record for application state (applied, screened, interview, offer). The verification service is the system of record for identity outcomes and fraud signals. The event log is the system of record for "what happened when," across systems.

  • Recruiting Ops (Responsible): stage mapping, candidate messaging templates, re-verification triggers when rescheduling

  • Security (Accountable): verification policy, risk tiers, appeal flow, retention controls, vendor security review

  • Platform/Integrations (Responsible): webhook receiver, idempotent API wrapper, event log, observability

  • Analytics/Chief of Staff (Consulted): KPI definitions (funnel leakage, turnaround time), incident review cadence

  • Hiring Manager (Informed): only sees "cleared," "needs review," or "blocked," not raw biometric artifacts

Step-by-step implementation that does not create duplicate actions

Implement in thin slices: start with one ATS stage trigger and one downstream action, then add additional triggers after you have replay safety and observability. NEEDS_REVIEW BLOCKED and attach a link to the Evidence Pack.

  1. Normalize identifiers: pick a canonical candidate_id and application_id (ATS-native), and generate a correlation_id for every workflow instance (per application, not per person). Persist mapping in your integration store.

  2. Set webhook intake rules: verify signatures, enforce schema validation, and write every inbound event to an append-only event log before doing any downstream calls. If processing fails, you can replay from the log without asking the ATS to resend.

  3. Add idempotent command execution: when the webhook says "candidate moved to Phone Screen," call verification create/start using an idempotency key derived from (application_id + stage + policy_version). Store the response keyed by the idempotency key so retries return the same result.

  4. Orchestrate status updates back to ATS: do not write raw results into free-text notes. Update a structured field or tag like verification_status = CLEARED

  5. Build resilient connectivity: if ATS is down when you need to write back, queue outbound updates and retry with exponential backoff. Make outbound updates idempotent too (same idempotency key), so you do not flip statuses back and forth.

  6. Add kill switches and canaries: a single feature flag should disable new verification triggers without breaking in-flight cases. Roll out by requisition, department, or location and compare funnel leakage and turnaround time.

  7. Instrument observability: every log line and trace span should include correlation_id, application_id, and requisition_id. Your war-room query should take 30 seconds, not 3 hours.

  • Greenhouse, Lever, and Workday-style models: treat "stage change" and "interview scheduled" as separate triggers with different idempotency scopes.

  • If your ATS cannot store structured fields, store only a stable Evidence Pack URL and a minimal status code, and keep the detailed timeline in your event log.

  • Prefer OAuth/OIDC where supported. If you must use API keys, scope them per environment, rotate them, and restrict IPs. API keys in integration middleware become silent blast-radius expanders.

A webhook and idempotency policy you can hand to the platform team

This policy is designed to prevent duplicate verification sessions during webhook replay, keep an audit-grade timeline, and support safe rollbacks. Adjust the stage names and endpoints to your ATS.

Anti-patterns that make fraud worse

Avoid these three patterns. They increase both fraud exposure and operational noise.

IntegrityLens promo
  • Writing verification outcomes into unstructured ATS notes instead of structured fields and an Evidence Pack link, which breaks reporting and makes appeals subjective

  • Triggering verification from calendar events only (interview scheduled) rather than from ATS stage transitions, which creates gaps when interviews are rescheduled or created off-platform

  • Treating webhook retries as "rare" and skipping idempotency, which guarantees duplicate sessions during incidents and drives reviewer fatigue

What happens when the ATS is down and you still need to hire

Design your integration so an ATS outage slows the UI, not your integrity controls. The event log and idempotent command store are your safety net. Recommended pattern: accept inbound events, persist them, and process asynchronously. If the ATS cannot receive status updates, queue them and retry. If the verification provider is temporarily unavailable, do not silently skip verification. Instead, mark the candidate as "verification pending" and prevent the next stage transition until the workflow completes or is explicitly overridden with approval. Rollbacks should be boring: if you discover a mapping bug, you should be able to stop new triggers (kill switch), replay from a known checkpoint, and regenerate Evidence Packs without editing history.

  • Kill switch: disable new verification triggers by requisition or globally without code deploys

  • Canary rollout: enable on 1-2 reqs first, validate duplicate rate and write-back behavior, then expand

  • Replay tooling: reprocess events from offset N with the same idempotency semantics

  • Backpressure: cap concurrent verification starts to avoid cost spikes during webhook floods

Where IntegrityLens fits

IntegrityLens AI is the first hiring pipeline that combines a full Applicant Tracking System with advanced biometric identity verification, AI screening, and technical assessments, so you can stop juggling tools and still keep a defensible chain of evidence. In this integration pattern, IntegrityLens can be the ATS system of record or can connect to your existing ATS/HRIS via webhooks and idempotent APIs. TA leaders and recruiting ops use it to keep the funnel moving with Risk-Tiered Verification, while CISOs use Evidence Packs and Zero-Retention Biometrics to reduce exposure. Platform teams get Idempotent Webhooks and clean event logs for traceability across the pipeline.

  • ATS workflow: manage Source candidates - Verify identity - Run interviews - Assess - Offer in one place

  • Identity verification: document + voice + face in a typical 2-3 minutes, before interviews

  • AI screening interviews: available 24/7 for timezone coverage and scheduling relief

  • Technical assessments: supports 40+ programming languages

  • Security baseline: 256-bit AES encryption and controls aligned to SOC 2 Type II and ISO 27001-certified infrastructure

What to do next week (without a big-bang rebuild)

If you own analytics or operational governance, your fastest win is to standardize identifiers and demand idempotency. This reduces incident load and makes your reporting credible. Next actions: pick one trigger stage, implement signed webhook intake with an append-only event log, wrap verification calls with idempotency keys, and write a single structured status back to the ATS with an Evidence Pack link. Then run a canary on a small set of requisitions and review failure cases weekly. A useful internal metric is not "fraud caught," it is "percentage of candidates with a complete, replayable event timeline." That is what protects speed and reputation when something goes sideways.

  • If we replay the last 24 hours of ATS webhooks, do we create any duplicate verification sessions?

  • Can we trace one application_id end-to-end across ATS, verification, interview, and assessment systems in a single query?

  • What is the explicit appeal flow when verification is flagged, and where is the decision logged?

Sources

31% of hiring managers say they've 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-driven workflow, not a manual step buried in recruiter notes.
  • Idempotency keys and correlation IDs are how you stop duplicate checks, double scheduling, and mismatched evidence.
  • A minimal event log becomes your audit spine: it answers who did what, when, from which system, with which outcome.
  • Resilient connectivity means designing for ATS downtime, webhook replay, and safe rollbacks without losing your hiring trail.
ATS webhook orchestration policy (idempotent + replayable)YAML

Use this as a starting point for a webhook receiver and orchestrator.

It enforces signature verification, idempotency keys, correlation IDs, retries, and safe rollback controls.

Designed to prevent duplicate verification sessions during webhook replay and to keep an audit-grade event trail.

policyVersion: "2026-10-ats-verification-spine"
owner:
  accountable: "Security"
  responsible:
    - "Platform-Integrations"
    - "RecruitingOps"

environments:
  production:
    inboundWebhookSecretsRef: "gcp-secret://ats/webhook-signing-secret"
    outboundAuth:
      type: "oauth2"
      audience: "https://api.integritylens.ai"
  sandbox:
    inboundWebhookSecretsRef: "gcp-secret://ats-sandbox/webhook-signing-secret"

controls:
  killSwitch:
    enabled: false
    reason: ""
    scope:
      requisitionIds: []
      departments: []
  canary:
    enabled: true
    allowRequisitionIds:
      - "REQ-10492"
      - "REQ-10501"

identifiers:
  correlationId:
    source: "generated"
    format: "uuid-v4"
  idempotencyKey:
    template: "${application_id}:${trigger_event}:${policyVersion}"

webhookIntake:
  verifySignature: true
  allowedIps:
    - "203.0.113.0/24"
  schema:
    requiredFields:
      - "event_id"
      - "event_type"
      - "occurred_at"
      - "candidate_id"
      - "application_id"
      - "requisition_id"
  writeAheadLog:
    store: "append-only"
    destination: "bigquery://hiring_audit.ats_events"

triggers:
  - event_type: "application.stage_changed"
    when:
      stage_to_includes:
        - "Phone Screen"
        - "Technical Screen"
    actions:
      - name: "start-verification"
        endpoint: "POST https://api.integritylens.ai/v1/verifications"
        headers:
          Authorization: "Bearer ${oauth_token}"
          Idempotency-Key: "${idempotencyKey}"
          X-Correlation-Id: "${correlation_id}"
        body:
          candidate:
            externalCandidateId: "${candidate_id}"
            externalApplicationId: "${application_id}"
          policy:
            mode: "risk-tiered"
            tier: "standard"
          callback:
            url: "https://integrations.yourco.com/webhooks/integritylens"
        onSuccess:
          writeEvent:
            type: "verification.started"
        onFailure:
          retry:
            maxAttempts: 8
            backoff: "exponential"
          writeEvent:
            type: "verification.start_failed"

writeBack:
  atsStatusField: "custom.verification_status"
  mapping:
    CLEARED: "CLEARED"
    NEEDS_REVIEW: "NEEDS_REVIEW"
    BLOCKED: "BLOCKED"
    PENDING: "PENDING"
  evidenceLinkField: "custom.evidence_pack_url"
  outboundQueue:
    enabled: true
    destination: "pubsub://hiring-integrations/ats-writeback"
  idempotency:
    enabled: true
    keyTemplate: "${application_id}:writeback:${verification_outcome}:${policyVersion}"

observability:
  requiredLogFields:
    - "correlation_id"
    - "application_id"
    - "requisition_id"
    - "event_id"
    - "idempotency_key"
  tracing:
    enabled: true
    sampleRate: 1.0

Outcome proof: What changes

Before

Verification happened inconsistently across roles, evidence lived in multiple tools, and webhook retries occasionally created duplicated actions and mismatched statuses between systems.

After

Verification triggers were standardized on ATS stage events, idempotency eliminated duplicate verification sessions during replay, and an append-only event log enabled fast incident reconstruction and consistent Evidence Pack links in the ATS.

Governance Notes: Legal and Security signed off because biometric handling followed privacy-first controls (including Zero-Retention Biometrics where applicable), access to Evidence Packs was role-based, retention was minimized to what was necessary for hiring defensibility, and an appeal flow existed for candidates flagged as NEEDS_REVIEW. Integration secrets were managed via centralized secret storage, outbound calls used OAuth2 where possible, and all verification state changes were logged with immutable timestamps for audit.

Implementation checklist

  • Define ATS as system of record for candidate stage and disposition, not for verification evidence blobs
  • Standardize identifiers: candidate_id, application_id, requisition_id, and a single correlation_id across systems
  • Require idempotency keys on all write endpoints and store idempotency results for replay
  • Implement webhook signature verification, allowlists, and OAuth/OIDC where supported
  • Centralize an append-only event log and generate Evidence Packs from it
  • Add kill switches and canary rollouts for verification triggers

Questions we hear from teams

What is the minimum viable integration if we cannot rebuild our ATS workflows?
Start with one trigger: ATS stage change to the first live interview stage. Log the inbound event, start verification with an idempotency key, and write back a single structured verification_status plus an Evidence Pack link.
How do we prevent duplicate verification sessions during webhook replay?
Require an Idempotency-Key header on verification create/start calls and store the result by key. Use a deterministic key derived from application_id, trigger_event, and policy version so retries return the original outcome.
What is identity gating in a hiring pipeline?
Identity gating is blocking progression to a higher-trust stage (live interview, assessment, or offer) until identity verification reaches a defined outcome such as CLEARED or an approved exception.
What should we store in the ATS versus the verification system?
Keep ATS focused on candidate stage and disposition. Store verification evidence, risk signals, and session details in the verification system, and write back only a status code and a stable Evidence Pack link.

Ready to secure your hiring pipeline?

Let IntegrityLens help you verify identity, stop proxy interviews, and standardize screening from first touch to final offer.

Try it free Book a demo

Watch IntegrityLens in action

See how IntegrityLens verifies identity, detects proxy interviewing, and standardizes screening with AI interviews and coding assessments.

Related resources