Skip to main content

Overview

Job Workflows are multi-step screening pipelines (e.g., questionnaire → standard interview → AI interviewer → meeting) attached to a job. Steps can also include AI practice interviewer and AI career coach — see Step Types for the full set. A workflow template (isTemplate: true) is a reusable definition you apply to one or more jobs or job families; applying it creates an assignment. A job’s effective workflow resolves the template that actually governs it (direct override > directly-applied template > job-family assignment > none). When you invite a candidate to a job, they are enrolled in the effective workflow and an enrollment with per-step state is created.
All workflow endpoints require the jobWorkflow organization feature. Requests for organizations without it return 403 FORBIDDEN.

Create Workflow Template

Create a reusable workflow template with an ordered list of steps. Endpoint: POST /qsi/gather/workflow-templates
curl -X POST https://api.prod.qualifi.hr/qsi/gather/workflow-templates \
  -H "x-api-key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering Screen",
    "userId": "user-456",
    "steps": [
      { "position": 1, "stepType": "questionnaire", "artifactId": "sq-uuid-1" },
      { "position": 2, "stepType": "ai_interviewer", "artifactId": "interview-uuid-1", "scoreThreshold": 70 }
    ]
  }'
{
  "name": "Engineering Screen",
  "userId": "user-456",
  "description": "Standard engineering pipeline",
  "steps": [
    { "position": 1, "stepType": "questionnaire", "artifactId": "sq-uuid-1" },
    { "position": 2, "stepType": "ai_interviewer", "artifactId": "interview-uuid-1", "scoreThreshold": 70 }
  ]
}
{
  "data": {
    "workflowTemplate": {
      "id": "template-uuid-1",
      "name": "Engineering Screen",
      "description": "Standard engineering pipeline",
      "organizationId": "org-123",
      "teamId": "team-123",
      "messageGroupId": "mg-uuid-1",
      "isTemplate": true,
      "createdById": "user-456",
      "createdAt": "2025-01-17T12:00:00.000Z",
      "updatedAt": "2025-01-17T12:00:00.000Z",
      "steps": [
        {
          "id": "step-uuid-1",
          "position": 1,
          "stepType": "questionnaire",
          "artifactId": "sq-uuid-1",
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        },
        {
          "id": "step-uuid-2",
          "position": 2,
          "stepType": "ai_interviewer",
          "artifactId": "interview-uuid-1",
          "scoreThreshold": 70,
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        }
      ]
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

List Workflow Templates

List all active workflow templates for the resolved team. Not paginated. Endpoint: GET /qsi/gather/workflow-templates
teamId
string
Override the team derived from the API key
{
  "data": {
    "workflowTemplates": [
      {
        "id": "template-uuid-1",
        "name": "Engineering Screen",
        "organizationId": "org-123",
        "teamId": "team-123",
        "messageGroupId": "mg-uuid-1",
        "isTemplate": true,
        "createdById": "user-456",
        "createdAt": "2025-01-17T12:00:00.000Z",
        "updatedAt": "2025-01-17T12:00:00.000Z",
        "steps": [
          {
            "id": "step-uuid-1",
            "position": 1,
            "stepType": "questionnaire",
            "artifactId": "sq-uuid-1",
            "createdAt": "2025-01-17T12:00:00.000Z",
            "updatedAt": "2025-01-17T12:00:00.000Z"
          }
        ]
      }
    ]
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

Get Workflow Template

Retrieve a single workflow template with its steps and assignments. Endpoint: GET /qsi/gather/workflow-templates/{id}
id
string
required
UUID of the workflow template
{
  "data": {
    "workflowTemplate": {
      "id": "template-uuid-1",
      "name": "Engineering Screen",
      "description": "Standard engineering pipeline",
      "organizationId": "org-123",
      "teamId": "team-123",
      "messageGroupId": "mg-uuid-1",
      "isTemplate": true,
      "createdById": "user-456",
      "createdAt": "2025-01-17T12:00:00.000Z",
      "updatedAt": "2025-01-17T12:00:00.000Z",
      "steps": [
        {
          "id": "step-uuid-1",
          "position": 1,
          "stepType": "questionnaire",
          "artifactId": "sq-uuid-1",
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        }
      ],
      "assignments": [
        {
          "id": "assignment-uuid-1",
          "templateId": "template-uuid-1",
          "targetType": "job",
          "targetId": "job-uuid-1",
          "source": "job_template",
          "organizationId": "org-123",
          "teamId": "team-123",
          "initialScoreThreshold": 60,
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        }
      ]
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

Update Workflow Template

Update the name, description, messaging, or steps of an existing workflow template. Endpoint: PATCH /qsi/gather/workflow-templates/{id}
id
string
required
UUID of the workflow template to update
curl -X PATCH https://api.prod.qualifi.hr/qsi/gather/workflow-templates/template-uuid-1 \
  -H "x-api-key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering Screen v2",
    "steps": [
      { "position": 1, "stepType": "questionnaire", "artifactId": "sq-uuid-1" },
      { "position": 2, "stepType": "ai_interviewer", "artifactId": "interview-uuid-1", "scoreThreshold": 75 }
    ]
  }'
{
  "name": "Engineering Screen v2",
  "steps": [
    { "position": 1, "stepType": "questionnaire", "artifactId": "sq-uuid-1" },
    { "position": 2, "stepType": "ai_interviewer", "artifactId": "interview-uuid-1", "scoreThreshold": 75 }
  ]
}
{
  "data": {
    "workflowTemplate": {
      "id": "template-uuid-1",
      "name": "Engineering Screen v2",
      "description": "Standard engineering pipeline",
      "organizationId": "org-123",
      "teamId": "team-123",
      "messageGroupId": "mg-uuid-1",
      "isTemplate": true,
      "createdById": "user-456",
      "createdAt": "2025-01-17T12:00:00.000Z",
      "updatedAt": "2025-01-17T13:00:00.000Z",
      "steps": [
        {
          "id": "step-uuid-1",
          "position": 1,
          "stepType": "questionnaire",
          "artifactId": "sq-uuid-1",
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T13:00:00.000Z"
        },
        {
          "id": "step-uuid-2",
          "position": 2,
          "stepType": "ai_interviewer",
          "artifactId": "interview-uuid-1",
          "scoreThreshold": 75,
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T13:00:00.000Z"
        }
      ]
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T13:00:00.000Z"
  }
}

Archive Workflow Template

Archive (soft-delete) a workflow template. Archived templates are no longer returned in list responses. Endpoint: DELETE /qsi/gather/workflow-templates/{id}
id
string
required
UUID of the workflow template to archive
userId
string
required
UUID of the acting user
{
  "data": {
    "workflowTemplate": {
      "id": "template-uuid-1",
      "name": "Engineering Screen",
      "description": "Standard engineering pipeline",
      "organizationId": "org-123",
      "teamId": "team-123",
      "messageGroupId": "mg-uuid-1",
      "isTemplate": true,
      "createdById": "user-456",
      "createdAt": "2025-01-17T12:00:00.000Z",
      "updatedAt": "2025-01-17T14:00:00.000Z",
      "archivedAt": "2025-01-17T14:00:00.000Z",
      "steps": []
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T14:00:00.000Z"
  }
}

Apply Workflow Template

Apply a workflow template to one or more jobs or job families, creating assignments. Endpoint: POST /qsi/gather/workflow-templates/{id}/apply
id
string
required
UUID of the workflow template to apply
curl -X POST https://api.prod.qualifi.hr/qsi/gather/workflow-templates/template-uuid-1/apply \
  -H "x-api-key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-456",
    "jobIds": ["job-uuid-1", "job-uuid-2"],
    "initialScoreThreshold": 60
  }'
{
  "userId": "user-456",
  "jobIds": ["job-uuid-1", "job-uuid-2"],
  "initialScoreThreshold": 60
}
{
  "data": {
    "assignments": [
      {
        "id": "assignment-uuid-1",
        "templateId": "template-uuid-1",
        "targetType": "job",
        "targetId": "job-uuid-1",
        "source": "job_template",
        "organizationId": "org-123",
        "teamId": "team-123",
        "initialScoreThreshold": 60,
        "createdAt": "2025-01-17T12:00:00.000Z",
        "updatedAt": "2025-01-17T12:00:00.000Z"
      },
      {
        "id": "assignment-uuid-2",
        "templateId": "template-uuid-1",
        "targetType": "job",
        "targetId": "job-uuid-2",
        "source": "job_template",
        "organizationId": "org-123",
        "teamId": "team-123",
        "initialScoreThreshold": 60,
        "createdAt": "2025-01-17T12:00:00.000Z",
        "updatedAt": "2025-01-17T12:00:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

Remove Workflow Template Assignment

Remove a workflow template assignment from a job or job family. Endpoint: DELETE /qsi/gather/workflow-template-assignments/{id}
id
string
required
UUID of the workflow template assignment to remove
{
  "data": {
    "success": true
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

Get Effective Workflow

Resolve the workflow that actually governs a job (direct override > directly-applied template > job-family assignment > none). Endpoint: GET /qsi/gather/jobs/{jobId}/effective-workflow
jobId
string
required
UUID of the job
{
  "data": {
    "effectiveWorkflow": {
      "source": "job_family",
      "assignmentId": "assignment-uuid-1",
      "initialScoreThreshold": 60,
      "template": {
        "id": "template-uuid-1",
        "name": "Engineering Screen",
        "organizationId": "org-123",
        "teamId": "team-123",
        "messageGroupId": "mg-uuid-1",
        "isTemplate": true,
        "createdById": "user-456",
        "createdAt": "2025-01-17T12:00:00.000Z",
        "updatedAt": "2025-01-17T12:00:00.000Z",
        "steps": []
      },
      "warnings": []
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}
When no workflow governs the job, the response still returns 200 with source: "none" and template: null (and no assignmentId). Check source before reading template.
{
  "data": {
    "effectiveWorkflow": {
      "source": "none",
      "template": null,
      "warnings": []
    }
  }
}

Set Workflow Override

Override a job’s workflow with a specific template, bypassing any job-family assignment. Endpoint: POST /qsi/gather/jobs/{jobId}/workflow-override
jobId
string
required
UUID of the job
curl -X POST https://api.prod.qualifi.hr/qsi/gather/jobs/job-uuid-1/workflow-override \
  -H "x-api-key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-456",
    "templateId": "template-uuid-1",
    "initialScoreThreshold": 65
  }'
{
  "userId": "user-456",
  "templateId": "template-uuid-1",
  "initialScoreThreshold": 65
}
{
  "data": {
    "effectiveWorkflow": {
      "source": "job_override",
      "assignmentId": "assignment-uuid-3",
      "initialScoreThreshold": 65,
      "template": {
        "id": "template-uuid-1",
        "name": "Engineering Screen",
        "organizationId": "org-123",
        "teamId": "team-123",
        "messageGroupId": "mg-uuid-1",
        "isTemplate": true,
        "createdById": "user-456",
        "createdAt": "2025-01-17T12:00:00.000Z",
        "updatedAt": "2025-01-17T12:00:00.000Z",
        "steps": []
      },
      "warnings": []
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

Clear Workflow Override

Remove a job’s workflow override, reverting to the job-family assignment or no workflow. Endpoint: DELETE /qsi/gather/jobs/{jobId}/workflow-override
jobId
string
required
UUID of the job
{
  "data": {
    "effectiveWorkflow": {
      "source": "job_family",
      "assignmentId": "assignment-uuid-1",
      "initialScoreThreshold": 60,
      "template": {
        "id": "template-uuid-1",
        "name": "Engineering Screen",
        "organizationId": "org-123",
        "teamId": "team-123",
        "messageGroupId": "mg-uuid-1",
        "isTemplate": true,
        "createdById": "user-456",
        "createdAt": "2025-01-17T12:00:00.000Z",
        "updatedAt": "2025-01-17T12:00:00.000Z",
        "steps": []
      },
      "warnings": []
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

Get Workflow Progress

List candidate enrollments and their per-step progress for a job, with pagination. Endpoint: GET /qsi/gather/jobs/{jobId}/workflow-progress
jobId
string
required
UUID of the job
page
number
Page number (default: 1)
pageSize
number
Items per page (default: 25, max: 100)
{
  "data": {
    "enrollments": [
      {
        "id": "enrollment-uuid-1",
        "candidateId": "candidate-uuid-1",
        "jobId": "job-uuid-1",
        "templateId": "template-uuid-1",
        "source": "job_override",
        "status": "active",
        "startedAt": "2025-01-17T12:00:00.000Z",
        "completedAt": null,
        "failedAt": null,
        "createdAt": "2025-01-17T12:00:00.000Z",
        "updatedAt": "2025-01-17T12:30:00.000Z",
        "steps": [
          {
            "id": "enrollment-step-uuid-1",
            "position": 1,
            "stepType": "questionnaire",
            "status": "completed",
            "attempt": 1,
            "artifactId": "sq-uuid-1",
            "inviteUrl": "https://app.qualifi.hr/q/token-abc",
            "inviteSentAt": "2025-01-17T12:00:00.000Z",
            "completedAt": "2025-01-17T12:20:00.000Z",
            "failedAt": null,
            "candidateInterviewId": null,
            "candidateMeetingId": null,
            "createdAt": "2025-01-17T12:00:00.000Z",
            "updatedAt": "2025-01-17T12:20:00.000Z"
          },
          {
            "id": "enrollment-step-uuid-2",
            "position": 2,
            "stepType": "ai_interviewer",
            "status": "invited",
            "attempt": 1,
            "artifactId": "interview-uuid-1",
            "inviteUrl": "https://app.qualifi.hr/i/token-def",
            "inviteSentAt": "2025-01-17T12:21:00.000Z",
            "completedAt": null,
            "failedAt": null,
            "candidateInterviewId": "ci-uuid-1",
            "candidateMeetingId": null,
            "createdAt": "2025-01-17T12:00:00.000Z",
            "updatedAt": "2025-01-17T12:21:00.000Z"
          }
        ]
      }
    ],
    "pagination": {
      "page": 1,
      "pageSize": 25,
      "total": 1,
      "totalPages": 1
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:30:00.000Z"
  }
}

List Workflow Resources

List all available artifacts (interviews, meetings, message groups, jobs, job families) that can be referenced when building workflow templates. Endpoint: GET /qsi/gather/workflow-resources
teamId
string
Override the team derived from the API key
{
  "data": {
    "workflowResources": {
      "interviews": [
        {
          "id": "interview-uuid-1",
          "title": "Engineering Technical Screen",
          "displayName": "Engineering Technical Screen",
          "stepType": "ai_interviewer",
          "hasActiveScorecard": true,
          "supportsScoreThreshold": true
        }
      ],
      "meetings": [
        {
          "id": "meeting-uuid-1",
          "title": "Hiring Manager Call",
          "displayName": "Hiring Manager Call",
          "stepType": "meeting",
          "hasActiveScorecard": false,
          "supportsScoreThreshold": false
        }
      ],
      "messageGroups": [
        {
          "id": "mg-uuid-1",
          "title": "Default Invite Messages",
          "type": "invite",
          "default": true,
          "organizationId": "org-123",
          "teamId": "team-123",
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        }
      ],
      "jobs": [
        {
          "id": "job-uuid-1",
          "title": "Senior Software Engineer",
          "type": "requisition",
          "status": "active",
          "department": "Engineering",
          "organizationId": "org-123",
          "teamId": "team-123",
          "createdById": "user-456",
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        }
      ],
      "jobFamilies": [
        {
          "id": "jf-uuid-1",
          "displayName": "Engineering",
          "teamId": "team-123",
          "organizationId": "org-123",
          "createdById": "user-456",
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        }
      ]
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}

Invite Candidate to Job

Enroll a candidate in a job’s effective workflow and send the first step’s invite. This endpoint creates or reuses a candidate record and creates a workflow enrollment. Endpoint: POST /qsi/gather/jobs/{jobId}/invite-candidate
jobId
string
required
UUID of the job to invite the candidate to
Identify the candidate one of two ways: either pass candidateId to reuse an existing candidate, or omit it and provide firstName, lastName, and at least one of email or phone to create a new one. A request that satisfies neither returns 400.
curl -X POST https://api.prod.qualifi.hr/qsi/gather/jobs/job-uuid-1/invite-candidate \
  -H "x-api-key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-456",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane.smith@example.com",
    "phone": "+15551234567"
  }'
{
  "userId": "user-456",
  "firstName": "Jane",
  "lastName": "Smith",
  "email": "jane.smith@example.com",
  "phone": "+15551234567"
}
{
  "data": {
    "enrollment": {
      "id": "enrollment-uuid-1",
      "candidateId": "candidate-uuid-1",
      "jobId": "job-uuid-1",
      "templateId": "template-uuid-1",
      "source": "job_override",
      "status": "active",
      "startedAt": "2025-01-17T12:00:00.000Z",
      "completedAt": null,
      "failedAt": null,
      "createdAt": "2025-01-17T12:00:00.000Z",
      "updatedAt": "2025-01-17T12:00:00.000Z",
      "steps": [
        {
          "id": "enrollment-step-uuid-1",
          "position": 1,
          "stepType": "questionnaire",
          "status": "invited",
          "attempt": 1,
          "artifactId": "sq-uuid-1",
          "inviteUrl": "https://app.qualifi.hr/q/token-abc",
          "inviteSentAt": "2025-01-17T12:00:00.000Z",
          "completedAt": null,
          "failedAt": null,
          "candidateInterviewId": null,
          "candidateMeetingId": null,
          "createdAt": "2025-01-17T12:00:00.000Z",
          "updatedAt": "2025-01-17T12:00:00.000Z"
        }
      ]
    },
    "firstInviteUrl": "https://app.qualifi.hr/q/token-abc"
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T12:00:00.000Z"
  }
}
firstInviteUrl is the invite link for the candidate’s first workflow step. It is included when an invite URL is available and is omitted otherwise, so treat it as optional.

Resend Workflow Step Invite

Resend the invite for a specific workflow enrollment step, advancing the inviteSentAt timestamp. This endpoint takes no request body. Endpoint: POST /qsi/gather/workflow-enrollment-steps/{id}/resend-invite
id
string
required
UUID of the workflow enrollment step
{
  "data": {
    "enrollmentStep": {
      "id": "enrollment-step-uuid-1",
      "position": 1,
      "stepType": "questionnaire",
      "status": "invited",
      "attempt": 2,
      "artifactId": "sq-uuid-1",
      "inviteUrl": "https://app.qualifi.hr/q/token-abc",
      "inviteSentAt": "2025-01-17T13:00:00.000Z",
      "completedAt": null,
      "failedAt": null,
      "candidateInterviewId": null,
      "candidateMeetingId": null,
      "createdAt": "2025-01-17T12:00:00.000Z",
      "updatedAt": "2025-01-17T13:00:00.000Z"
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2025-01-17T13:00:00.000Z"
  }
}

Step Types

Workflow steps are one of: questionnaire, standard_interview, ai_interviewer, ai_practice_interviewer, ai_career_coach, meeting.

Workflow Sources

Two response fields share the name source but describe different things — don’t conflate them when cross-referencing an assignment against an effective-workflow response:
  • assignment.source (on assignment objects in the Get Workflow Template and Apply Workflow Template responses) records how the assignment was created: job_template (template applied directly to a job), job_family (template applied to a job family), or job_override (a job-level override).
  • effectiveWorkflow.source (on the Get Effective Workflow response) records which rule won when resolving the job, in precedence order: job_override, job_template, job_family, or none (no workflow governs the job).

Enrollment & Step Status

Enrollment status: active, completed, failed, stopped. Enrollment-step status: pending, invited, in_progress, completed, waiting_for_evaluation, passed, failed.
Clients should be prepared to handle any documented status value. The full valid sets are listed above; additional values may be introduced in future API versions.

Jobs

Create and manage jobs

Candidates

Create candidates to invite into workflows