> ## Documentation Index
> Fetch the complete documentation index at: https://developer.jobmojito.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Interview and pre-screening workflows

# API use: interview and pre-screening workflows

Everything you can do from the JobMojito admin, you can also drive from your own backend: create interviews and pre-screening positions, register or invite candidates, and read results, all over plain HTTPS `POST`/`GET` calls to `https://cool.jobmojito.com/functions/v1`, authenticated with a Supabase JWT bearer token. The whole surface is described by an OpenAPI 3.1 document, which also makes it MCP-friendly if you'd rather drive it from an agent than hand-roll HTTP calls.

The shape of each flow below matches direct use. The only structural differences are *who* creates and publishes the interview (your code, via API calls, instead of a recruiter in the admin) and *how* results come back (a webhook delivered to your endpoint, instead of only appearing in the admin UI). One flow, synchronous pre-screening, has no direct-use equivalent at all, because it skips the candidate portal entirely.

A note on webhooks before the flows: JobMojito fires three events: `interview_collected` (raw answers, before scoring), `interview_result` (final score and AI analysis, delayed until the PDF is ready if you've enabled report generation), and `interview_failed` (abandoned, no speech detected, or otherwise never completed). Delivery is at-least-once with up to 10 retries over 60-second timeouts, and `interview_result` re-fires whenever a watched field changes later, including a recruiter's decision, so your handler needs to upsert by `id` and treat every delivery as idempotent, not assume single delivery or strict ordering. Separately from the webhook, JobMojito also emails the candidate directly whenever a session is abandoned or fails, so they can continue or retake it without you having to prompt them.

## Interview

1. **Create the interview:** `POST /job-interview-create` (AI-generated questions from a job description) or `POST /job-interview-create-from-array` (your own question list). Either call returns an `interview_def_set_id` you'll reuse; this same id shows up elsewhere under different field names (`interview_id`, `position_id`), so keep the [identifiers reference](https://developer.jobmojito.com/mcp/identifiers) handy.
2. **Get candidates in:** `POST /job-interview-register-users` with `type: "url"` to get signed links back for you to deliver yourself, or `type: "invitation"` to have JobMojito send and manage the email chain (invite, reminders, completion notice). `POST /invite-users` is the alternative when you're inviting people to the merchant more broadly. Both are batch endpoints: every request returns HTTP 200 with a per-row `result`, so a bad email in row 3 doesn't fail rows 1 and 2; inspect each row rather than trusting the top-level status.
3. **Candidate authenticates, confirms their profile, and takes the AI interview:** identical to direct use.
4. **If the candidate abandons or fails the session,** JobMojito fires `interview_failed` to your endpoint and separately emails the candidate so they can continue or retake it; scoring fields are typically empty on that webhook.
5. **On submission,** JobMojito fires `interview_collected` immediately (raw answers), then scores the interview and fires `interview_result` to your configured endpoint, held back until the PDF report is attached, if you've turned that on.
6. **A human still makes the call.** A reviewer records Select/Reject in JobMojito's Pending decisions screen; that decision change re-fires `interview_result` so your system picks it up without polling.

## Pre-screening with interview

1. **Define the screening rules:** `POST /pre-screening-create` with `type: "resume" | "form" | "resume_with_form"`, plus `assessment_rules` (what actually screens: nationality, residency, languages, education, visa, age, gender, resume match score, detected experience) and `form_fields` (what the candidate sees). Both arrays are replaced wholesale on every update, so always send the complete array.
2. **Define the interview stage:** `POST /job-interview-create`, same as the plain Interview flow.
3. **Get the candidate in,** the same way as above, or use the shortcut, `POST /job-interview-create-for-candidate-with-token`, which resolves the position, runs pre-screening, and returns a ready `interview_url` plus a `status` (`ai_accept`, `ai_reject`, or `recruiter_action`) in one call per candidate.
4. **Candidate authenticates and completes the pre-screening form/resume upload.**
5. **JobMojito scores it against your rules,** landing the candidate in one of three bands, identical logic to direct and ATS use:
   * Above the `resume_score_accept` threshold (or a passing form band), non-EU: auto-accepted into the interview.
   * Below `resume_score_reject`, non-EU: auto-rejected, visible via `GET /job-interview-details`; no webhook fires for pre-screening itself.
   * Mid-band (a rule's `action: "mark_for_review"`), or an EU/GDPR candidate: routed to a recruiter's Pending decisions screen regardless of score.
6. **If accepted, the candidate takes the interview** (with the same abandoned/failed email and continue-or-retake option, and `interview_failed` webhook, as the plain Interview flow), and results otherwise follow the same webhook path: `interview_collected`, then scoring, then `interview_result` to your endpoint, and a human Select/Reject re-fires the event.

## Pre-screening only (synchronous)

This is the one API-only shape with nothing else like it in direct or ATS use: there's no candidate portal and no interview at all. You already have the resume; you send it, and the score comes back in the same HTTP response.

1. **Define the position once:** `POST /pre-screening-create`, same rules/form\_fields shape as above.
2. **Screen each candidate:** `POST /job-interview-pre-screening-api-resume-text` (plaintext resume) or `POST /job-interview-pre-screening-api-resume-binary` (uploaded file), with `position_id`, `candidate_name`, `candidate_email`, and the resume. Optional `form` values (education, languages, residency, nationality, visa, age, gender) get matched against whichever rules you configured.
3. **The response returns synchronously,** no webhook involved, with `success`, `decision_status`, and a `recommendation` of `ai_accept`, `ai_reject`, or `recruiter_action`, plus `pre_screening_score`, `resume_ai_analysis`, `resume_ai_education`, `resume_ai_technical_experience`, and (when relevant) `processing_reason`.
4. **Act on `recommendation` yourself.** `ai_accept` and `ai_reject` are automated outcomes available for non-EU positions only: advance the candidate in your own system on `ai_accept`, or reject/archive on `ai_reject`. `recruiter_action` is what you get instead for EU/GDPR positions (and mid-band non-EU candidates): flag the candidate for human review in JobMojito's Pending decisions rather than deciding automatically.

If the candidate isn't in a screenable state at all, you still get HTTP 200, just a short `{ decision_status, message }` object instead of the full result, rather than an error.
