Skip to main content
TapTalent sends webhook events for various operations. All webhook payloads follow a consistent structure.

Payload structure

Every webhook body looks like:
{
  "event": "event.type.name",
  "timestamp": "2024-01-20T14:45:00Z",
  "companyId": 12345,
  "data": {
    // Event-specific data
  }
}
FieldTypeDescription
eventstringThe event type (e.g. candidate.updated)
timestampstringISO 8601 UTC timestamp when the event occurred
companyIdintegerThe TapTalent company ID the event belongs to
dataobjectEvent-specific payload (see each event below)

Headers

All webhook requests include:
  • Content-Type: application/json
  • X-Webhook-Event: The event type (e.g. resume.bulk_upload_parse.started)
  • X-Webhook-Timestamp: ISO 8601 timestamp of when the event occurred
  • X-Webhook-Key: Your webhook verification secret. When you have generated a webhook key in the dashboard, TapTalent sends it in this header. Compare it to your stored key to verify the request came from TapTalent. If no key has been set, the header may be empty.

Resume events

resume.bulk_upload_parse.started

Triggered when a bulk resume upload batch starts processing.
{
  "event": "resume.bulk_upload_parse.started",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "batchId": 12345,
    "fileCount": 25,
    "jobId": 12345
  }
}
FieldTypeDescription
batchIdintegerThe batch ID for this upload
fileCountnumberTotal number of resumes in the batch
jobIdinteger or nullThe job ID if resumes were uploaded to a specific job, otherwise null

resume.bulk_upload_parse.completed

Triggered when a bulk resume upload batch completes processing.
{
  "event": "resume.bulk_upload_parse.completed",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "batchId": 12345,
    "status": "COMPLETED",
    "fileCount": 25,
    "successCount": 23,
    "failedCount": 2,
    "jobId": 12345
  }
}
FieldTypeDescription
batchIdintegerThe batch ID for this upload
statusstringBatch processing status (e.g. “COMPLETED”)
fileCountnumberTotal number of resumes in the batch
successCountnumberNumber of resumes successfully parsed
failedCountnumberNumber of resumes that failed to parse
jobIdinteger or nullThe job ID if resumes were uploaded to a specific job, otherwise null

resume.bulk_upload_parse.failed

Triggered when a bulk resume upload batch fails before processing begins (e.g. validation errors, invalid URLs).
{
  "event": "resume.bulk_upload_parse.failed",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "error": "Error message describing the failure"
  }
}
FieldTypeDescription
errorstringError message describing why the batch failed

Job events (recruiter actions)

job.created

Triggered when a recruiter creates a new job from the dashboard.
{
  "event": "job.created",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "title": "Software Engineer"
  }
}

job.updated

Triggered when a recruiter updates a job’s basic details (e.g. title, description, location) from the dashboard. Does not fire when only the job status is changed.
{
  "event": "job.updated",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "updatedFields": ["title", "description", "city"]
  }
}

job.status_changed

Triggered when a recruiter changes a job’s status (e.g. Draft → Active, Active → Inactive/Closed).
{
  "event": "job.status_changed",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "status": "INACTIVE",
    "previousStatus": "ACTIVE",
    "closingStatus": "Filled",
    "closingReason": "Position filled internally"
  }
}
FieldTypeDescription
jobIdintegerThe job ID
statusstringNew status (e.g. ACTIVE, INACTIVE, DRAFT)
previousStatusstring or nullStatus before the change
closingStatusstring or nullIf the job was closed, the selected closing reason (e.g. Filled, Cancelled)
closingReasonstring or nullOptional text or detail for the closing

Candidate events (recruiter actions)

candidate.added_to_job

Triggered when a recruiter adds one or more candidates to a job (e.g. from company list, AI search, or moving from another job).
{
  "event": "candidate.added_to_job",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "stageId": 2,
    "candidateIds": ["candidateId-1", "candidateId-2"],
    "jobCandidateIds": [101, 102],
    "count": 2
  }
}
FieldTypeDescription
jobIdintegerThe job the candidates were added to
stageIdintegerThe pipeline stage ID (optional in payload)
candidateIdsarrayCandidate IDs that were added
jobCandidateIdsarrayJob–candidate record IDs for each added candidate
countnumberNumber of candidates added

candidate.stage_changed

Triggered when a recruiter moves one or more candidates to a different pipeline stage (e.g. kanban drag-and-drop).
{
  "event": "candidate.stage_changed",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "currentStageId": 2,
    "nextStageId": 3,
    "jobCandidateIds": [101, 102],
    "candidateIds": ["candidateId_1", "candidateId_2"]
  }
}

candidate.hired

Triggered when a recruiter moves one or more candidates to the Hired stage.
{
  "event": "candidate.hired",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "jobCandidateIds": [101, 102],
    "candidateIds": ["candidateId_1", "candidateId_2"]
  }
}

candidate.rejected

Triggered when a recruiter rejects or disqualifies one or more candidates, or when an automated screening flow disqualifies a candidate.
{
  "event": "candidate.rejected",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "jobCandidateIds": [101],
    "candidateIds": ["candidateId_1"],
    "jobCandidateId": 101,
    "candidateId": "candidateId_1",
    "reason": "Automated screening flow rejected."
  }
}

candidate.removed_from_job

Triggered when one or more candidates are removed from a job. This is sent when:
  • A recruiter uses the bulk “Remove from job” / “Delete” action on candidates in that job (move-job-candidates with delete), or
  • A recruiter deletes one or more candidates from the company (DELETE /candidates), in which case one event is sent per job those candidates were in.
{
  "event": "candidate.removed_from_job",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "jobCandidateIds": [101, 102],
    "candidateIds": ["candidateId_1", "candidateId_2"]
  }
}
FieldTypeDescription
jobIdintegerThe job the candidates were removed from
jobCandidateIdsarrayJob–candidate record IDs that were removed
candidateIdsarrayCandidate IDs that were removed from the job

candidate.updated

Triggered when a recruiter updates a candidate’s profile or job-application details from the dashboard.
  • Profile (scope: "profile"): Company-level profile (e.g. name, email, phone, resume, skills) via Update company candidate details or Update job candidate details (email/phone).
  • Application (scope: "application"): Application for a specific job (e.g. expected CTC, notice period, hired date) via Update job candidate application.
Profile update example:
{
  "event": "candidate.updated",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "candidateId": "candidateId_1",
    "updatedFields": ["firstName", "email", "phone"],
    "scope": "profile"
  }
}
Application update example (includes jobCandidateId and jobId):
{
  "event": "candidate.updated",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobCandidateId": 101,
    "jobId": 12345,
    "candidateId": "candidateId_1",
    "updatedFields": ["expectedCTC", "noticePeriod"],
    "scope": "application"
  }
}

Job candidate scoring events

job.candidate.score.completed

Triggered when AI scoring is completed for a candidate’s application to a job. This event is sent after the candidate’s resume has been analyzed and matched against the job requirements, and a score has been calculated.
{
  "event": "job.candidate.score.completed",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "jobCandidateId": 101,
    "candidateId": "candidateId_1",
    "score": 85.5
  }
}
FieldTypeDescription
jobIdintegerThe job ID the candidate applied to
jobCandidateIdintegerThe job–candidate record ID
candidateIdstringThe candidate ID
scorenumberThe AI-generated match score (typically 0-100) representing how well the candidate matches the job requirements

job.candidate.score.failed

Triggered when AI scoring fails for a candidate’s application to a job. This event is sent when the scoring process encounters an error (e.g. insufficient candidate data, processing error, or service unavailability).
{
  "event": "job.candidate.score.failed",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "jobId": 12345,
    "jobCandidateId": 101,
    "candidateId": "candidateId_1",
    "error": "Scoring failed: insufficient candidate data"
  }
}
FieldTypeDescription
jobIdintegerThe job ID the candidate applied to
jobCandidateIdintegerThe job–candidate record ID
candidateIdstringThe candidate ID
errorstringError message describing why scoring failed

Assessment events

assessment.ready

Triggered when questions have been generated for an assessment (e.g. after Auto-Generate Assessment or Generate Questions). You can then fetch the assessment or invite candidates.
{
  "event": "assessment.ready",
  "timestamp": "2024-01-20T14:45:00Z",
  "data": {
    "assessmentId": "assessmentId_1",
    "message": "Assessment questions generated and ready",
    "questionCount": 5
  }
}
FieldTypeDescription
assessmentIdstringThe assessment ID
messagestringConfirmation message
questionCountnumberNumber of questions added to the assessment

interview.started

Triggered when a candidate has started an assessment interview (e.g. opened the interview and it has begun). Use this to track when invited candidates begin their assessment.
{
  "event": "interview.started",
  "timestamp": "2024-01-20T14:45:00Z",
  "companyId": "company_id_12345",
  "data": {
    "assessmentId": "assessmentId_1",
    "submissionId": "submissionId_1",
    "interviewStatus": "STARTED",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "jobCandidateId": 101
  }
}
FieldTypeDescription
assessmentIdstringThe assessment ID
submissionIdstringThe interview submission ID
interviewStatusstringStatus of the interview (e.g. STARTED)
firstNamestringCandidate’s first name (if available)
lastNamestringCandidate’s last name (if available)
emailstringCandidate’s email (if available)
jobCandidateIdnumber or nullJob-candidate ID if the candidate was invited via a job (optional)

interview.scoring_completed

Triggered when scoring has finished for an interview submission. Use this to sync results to your system or notify recruiters.
{
  "event": "interview.scoring_completed",
  "timestamp": "2024-01-20T15:00:00Z",
  "companyId": 12345,
  "data": {
    "assessmentId": "assessmentId_1",
    "submissionId": "submissionId_1",
    "status": "COMPLETED",
    "score": 78,
    "bucket": "Good Fit",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "jobCandidateId": 101
  }
}
FieldTypeDescription
assessmentIdstringThe assessment ID
submissionIdstringThe interview submission ID
statusstringStatus (e.g. COMPLETED)
scorenumberOverall score for the submission
bucketstring or nullEvaluation bucket (e.g. “Strong Fit”, “Good Fit”) if configured
firstNamestringCandidate’s first name (if available)
lastNamestringCandidate’s last name (if available)
emailstringCandidate’s email (if available)
jobCandidateIdnumber or nullJob-candidate ID if linked to a job (optional)

interview.ended

Triggered when a candidate has finished or left the interview (e.g. completed all questions, timed out, or ended the session). Use this to track completion and optionally wait for interview.scoring_completed for the final score.
{
  "event": "interview.ended",
  "timestamp": "2024-01-20T14:55:00Z",
  "companyId": 12345,
  "data": {
    "assessmentId": "assessmentId_1",
    "submissionId": "submissionId_1",
    "status": "FINISHED",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "jobCandidateId": 101
  }
}
FieldTypeDescription
assessmentIdstringThe assessment ID
submissionIdstringThe interview submission ID
statusstringStatus (e.g. FINISHED)
firstNamestringCandidate’s first name (if available)
lastNamestringCandidate’s last name (if available)
emailstringCandidate’s email (if available)
jobCandidateIdnumber or nullJob-candidate ID if linked to a job (optional)

interview.error

Triggered when an error occurs during the interview flow (e.g. failed to start, scoring failure, or permission issues). Use this to monitor failures and alert or retry as needed.
{
  "event": "interview.error",
  "timestamp": "2024-01-20T14:46:00Z",
  "companyId": 12345,
  "data": {
    "assessmentId": "assessmentId_1",
    "submissionId": "submissionId_1",
    "errorType": "START_FAILED",
    "errorMessage": "Failed to start interview",
    "timestamp": 1708363560000
  }
}
FieldTypeDescription
assessmentIdstringThe assessment ID
submissionIdstring or nullThe interview submission ID (if one was created)
errorTypestringError category (e.g. START_FAILED, SCORING_FAILED, AUDIO_PERMISSION_DENIED)
errorMessagestringHuman-readable error message
timestampnumberUnix timestamp when the error occurred

interview.complete_later

Triggered when a candidate clicks “Complete later (not recommended)” on the pre-interview setup screen. The candidate has chosen to save their link and finish the assessment later instead of starting now.
{
  "event": "interview.complete_later",
  "timestamp": "2024-01-20T14:50:00Z",
  "companyId": 12345,
  "data": {
    "assessmentId": "assessmentId_1",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "jobCandidateId": 101,
    "timestamp": 1708363800000
  }
}
FieldTypeDescription
assessmentIdstringThe assessment ID
firstNamestringCandidate’s first name (if available)
lastNamestringCandidate’s last name (if available)
emailstringCandidate’s email (if available)
jobCandidateIdnumber or nullJob-candidate ID if linked to a job (optional)
timestampnumberUnix timestamp when the candidate chose complete later

More event types may be added in future releases. Check this page for updates.