Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,070Paid calls: 1,528Letters: 13Defects: 1,322counted 3 min ago
teppi

Server definition

Hash
sha256:c69477b7e3c3633a755a498019b78bc5a61d7ff35b1909d864cc2b06f2688e02
What it is
What a remote MCP server returned when asked what it offers: 29 tools

The blob, as servednamed by its sha256

{ "instructions": "JobMojito MCP server — run AI-led conversational sessions on the JobMojito\nplatform, plus search the documentation. Every action runs as the signed-in user,\nso results respect that user's own permissions.\n\nTHREE PRODUCTS, and they are easy to confuse:\n• Interviews — a scored Q&A. `create_interview` (questions generated from a job\n description) or `create_interview_from_questions` (your own list).\n• Simulated personas — a scored free-form role-play used to assess or screen.\n `create_persona` with `portal=\"interview\"`. Invited, billed and listed exactly\n like an interview.\n• Coaching — the same role-play engine for practice. `create_persona` with\n `portal=\"coaching\"` (THE DEFAULT when omitted): the learner starts it from the\n catalogue, it spends their own coaching credits, and recruiters never see the\n result. The catalogue tools (`*_catalogue_directory`) apply to this one only.\n\n`portal` defaults to \"coaching\". For ANY hiring, screening or assessment use,\npass `portal=\"interview\"` explicitly — omitting it silently builds the wrong\nproduct, billed to the wrong credits and invisible to the recruiter.\n\nRESPONSIBLE USE (applies to every result this server returns):\nJobMojito produces assistive output for hiring workflows. Interview scores,\ntranscripts, summaries and reports are decision-support material — they are not\nhiring decisions. Present them as input for a qualified human reviewer, and never\ndescribe a candidate as accepted, rejected, or ranked as final by this system.\nWhen a user is preparing candidate-facing material, remind them that candidates\nshould be told AI is used in the process.\n\nAUTHENTICATION:\nCapability discovery works without a login, but every tool call requires the user\nto have authorized this server. If a call fails with an authentication error (401\n/ invalid_token), retry that exact call once — the server answers the retry with\na challenge that makes the client refresh its token, and the call then usually\nsucceeds without the user doing anything. Only if the second attempt fails too\nshould you ask the user to reconnect and authorize this server. Never retry an\nauth failure with different arguments; it is not an input problem.\n\nHOW TO USE THIS SERVER:\n1. To understand how something works — an endpoint, a field, a workflow, what an\n input means — `search_documentation` is usually faster and more reliable than\n experimenting. It's the single docs entry point: one call searches both the\n developer/API reference and the help center in parallel. Then\n `get_documentation(url)` reads a page in full.\n2. For a multi-step workflow (create an interview → invite candidates → review\n results), the documentation has step-by-step cookbooks worth following.\n3. The read-only tools (`list_*`, `get_*`) are the safe way to look things up\n before creating or changing anything.\n4. Merchant selection: many tools accept a `merchant_id`. When one is needed and\n none has been selected — or the user wants to switch merchants —\n `jobmojito_configuration` renders an interactive searchable picker, which is a\n better experience than asking the user to type a name. `list_my_merchants`\n returns the same options as text for clients that cannot render UI. After a\n merchant is chosen, pass `merchant_id=<chosen id>` on subsequent calls; omit it\n for the user's own account.\n\nIDENTIFIERS & ADMIN LINKS:\nIds are easy to mix up — the same interview is `interview_def_set_id` (on create),\n`position_id` (get/set-state), and `interview_id` (register/token); results use\n`interview_result_id`, NOT the result row's `id`. There is no link-building tool.\nFor the full id-to-field map, where each id comes from, and admin link patterns:\nget_documentation(\"https://developer.jobmojito.com/mcp/identifiers\").\n\nTOOLS BY CATEGORY (tool descriptions are prefixed with these labels):\n• Documentation: search_documentation, get_documentation\n• Configuration / merchants: jobmojito_configuration (searchable picker),\n list_my_merchants (text equivalent, supports a `search` filter)\n• Interview (create/manage): create_interview, create_interview_from_questions,\n get_interview_definition, set_interview_state, request_another_interview_attempt\n• Role-play (simulated persona or coaching persona — chosen with `portal`):\n create_persona\n• Coaching catalogue: list_catalogue_directories, get_catalogue_directory,\n create_catalogue_directory, update_catalogue_directory\n• Invitations: register_users_for_interview (register candidates and get their\n personal interview links), generate_interview_url (a signed link to share)\n• Results & reports: get_interview_result_details, generate_interview_report\n• Knowledge base: upload_knowledge_base_document\n• Merchant lists (read-only): list_interviews, list_candidates,\n list_interview_results, list_avatars, list_sub_merchants, get_merchant_analytics,\n get_merchant_status\n\nTypical flows:\n- \"Set up an interview for a role\" → create_interview → generate_interview_url or\n register_users_for_interview.\n- \"Invite candidates to an interview\" → register_users_for_interview (per-candidate\n links) or generate_interview_url (one shareable link).\n- \"Review a candidate's result\" → list_interview_results → get_interview_result_details\n → generate_interview_report.\n- \"Screen someone with a role-play instead of questions\" → create_persona with\n `portal=\"interview\"` → register_users_for_interview → list_interview_results.\n- \"Add a practice session learners can start themselves\" → create_persona (default\n coaching portal) with `tags` → the catalogue directory whose\n `tags_interview_set_filter` those tags satisfy lists it automatically.\n", "tools": [ { "description": "[Coaching catalogue] Create a directory (page) in the coaching portal catalogue. A directory nests other directories (`tags_sub`), lists coaching sessions whose own `tags` match its `tags_interview_set_filter`, and can carry a fully custom Markdown page (`content_md`) with `[sessions]`, `[directory:…]`, `[session:…]` and `[plan-progress]` directives. Coaching-platform feature.\n\nCreates a directory (page) in the coaching portal catalogue. A directory nests other directories through `tags_sub`, lists coaching sessions through `tags_interview_set_filter`, and can replace the default grid with a custom Markdown page through `content_md`. The id you choose is the catalogue URL segment and cannot be changed afterwards.", "inputSchema": { "properties": { "coach_plan": { "description": "Coaching-plan stage this item belongs to, used by the coaching-plan progress view. Omit/null to leave it out of any plan. Options — `demo`: Demo session. | `screening`: Screening-interview practice. | `2nd`: Second-interview practice. | `3rd`: Third-interview practice. | `closing`: Closing / salary-negotiation practice. | `job-specific`: Job-specific coaching. | `other`: Anything that does not fit the other buckets..", "enum": [ "demo", "screening", "2nd", "3rd", "closing", "job-specific", "other", null ], "example": "screening", "type": [ "string", "null" ] }, "content_md": { "description": "Markdown for a custom directory page. When set (even as an empty string) the markdown replaces the default grid and decides the layout itself; null renders the plain grid of sub-directories and sessions. Alongside normal Markdown you can place these directives, each ALONE on its own line: `[plan-progress]` (the learner's coaching-plan progress), `[directory:<tag-id>]` (a card for one sub-directory), `[session:<interview-id>]` (a card for one session), `[sessions]` (every session in this directory), `[sessions:<term>]` (sessions matching a term), `[sessions:filter=<term>,limit=<n>]` (a filtered, capped list). A directive on a line with other text is rendered as ordinary text. Chips, callouts, cards, columns and buttons are available here too — full vocabulary: https://developer.jobmojito.com/cookbooks/format-content-with-markdown", "example": "## Sales coaching\n\nPick a session to practise with.\n\n[chip:6 sessions] [chip:Beginner,tone=accent]\n\n[sessions:filter=objection-handling,limit=6]\n", "type": [ "string", "null" ] }, "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "cover_image_url": { "description": "Cover image URL shown on the directory card.", "type": [ "string", "null" ] }, "description": { "description": "Short description shown on the directory card.", "example": "Practice discovery, objection handling and closing.", "type": [ "string", "null" ] }, "id": { "description": "Directory id — also the catalogue URL segment (/catalogue/<id>) and the value other directories reference in their `tags_sub`. Lowercase letters, digits and single - or _ separators. Convention is to end language-specific directories with the language code, e.g. `sales-coaching-en`.", "example": "sales-coaching-en", "minLength": 1, "pattern": "^[a-z0-9]+(?:(?:-|_)+[a-z0-9]+)*$", "type": [ "string", "null" ] }, "merchant_id": { "description": "Merchant that owns the directory. Admin / sub-merchant callers only; otherwise taken from your token.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Language of the directory (one of the platform-languages.json codes). The catalogue groups directories by language; defaults to `en` when omitted.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Display name of the directory, shown as the page title and on its card.", "example": "Sales coaching", "minLength": 1, "type": [ "string", "null" ] }, "parent_tag": { "description": "Id of an existing directory to nest this new one under: the new id is appended to that directory's `tags_sub`. Omit to create a top-level directory (reachable via a direct link, or by adding it to another directory later).", "example": "home-employee-en", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status of the catalogue directory. Options — `draft`: Not published — the directory exists but is not served to visitors. | `active`: Published and served in the catalogue. | `archived`: Retired — kept for reference but no longer served..", "enum": [ "draft", "active", "archived", null ], "example": "active", "type": [ "string", "null" ] }, "tags_interview_set_filter": { "description": "Tag filter selecting which coaching sessions this directory lists: a session appears when its own `tags` contain EVERY tag here (an AND, not an OR). Only `active` coaching/persona sessions with visibility `public` or `merchant_public` are listed. Set the matching tags on the session with the create-interview / job-interview-update `tags` field.", "example": [ "sales", "objection-handling" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "tags_sub": { "description": "Ids of the directories nested under this one, in display order. Replaces the whole list — send the full set, not just the additions. A referenced directory only appears if it exists and is visible to the viewer.", "example": [ "sales-coaching-objections-en", "sales-coaching-closing-en" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "visibility": { "description": "Who can see the catalogue directory. Options — `public`: Shared across every merchant. Platform admins only — a merchant caller is rejected by row-level security. | `merchant_public`: Listed in the merchant's own catalogue — the normal choice. | `merchant_invite`: Owned by the merchant but not listed; reachable only for invited users. | `merchant_unlisted`: Owned by the merchant but not listed; reachable only via a direct link..", "enum": [ "public", "merchant_public", "merchant_invite", "merchant_unlisted", null ], "example": "merchant_public", "type": [ "string", "null" ] } }, "required": [ "id", "name" ], "type": "object" }, "name": "create_catalogue_directory", "outputSchema": { "description": "The created catalogue directory.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "catalogue_url": { "description": "Public URL of the directory page, when the merchant has a coaching-portal domain configured. Null otherwise.", "example": "https://coaching.example.com/catalogue/sales-coaching-en", "type": [ "string", "null" ] }, "id": { "description": "Id of the created directory.", "example": "sales-coaching-en", "type": [ "string", "null" ] }, "merchant_id": { "description": "Owning merchant id. Null for a platform-wide (`public`) directory.", "type": [ "string", "null" ] }, "parent_tag": { "description": "The directory this one was nested under, when `parent_tag` was supplied.", "type": [ "string", "null" ] } }, "required": [ "id", "merchant_id", "parent_tag", "catalogue_url" ], "type": "object", "x-fastmcp-top-level-schema": "CatalogueTagCreateResponse" } }, { "description": "[Interviews] Create a new interview and auto-generate its question sequence from position data. The `interview_template_id` you pass also sets the modality (voice-only vs realtime/pre-recorded avatar) — see `list_avatars`.\n\nCreates a new interview / coaching / assessment definition, generates its description, questions and candidate expectations via AI, and provisions default steps. Optionally provisions an embed key.", "inputSchema": { "properties": { "additional_context": { "additionalProperties": {}, "description": "Arbitrary additional context object merged into AI generation.", "type": [ "object", "null" ] }, "candidate_expectations": { "description": "Free-text candidate expectations folded into AI generation.", "type": [ "string", "null" ] }, "candidate_video_introduction": { "description": "Whether a candidate video introduction is optional or required.", "enum": [ "optional", "required", null ], "example": "optional", "type": [ "string", "null" ] }, "code": { "description": "Optional external code/reference for the interview.", "example": "my code", "type": [ "string", "null" ] }, "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "cover_image_url": { "description": "Cover image URL.", "example": "https://example.com/cover.png", "type": [ "string", "null" ] }, "custom_scoring": { "additionalProperties": {}, "description": "Custom result-scoring overrides merged with defaults and template overrides.", "type": [ "object", "null" ] }, "description": { "description": "Short, two-sentence job description shown to the candidate. Provide it to use it as-is; leave it null/blank and it is AI-generated from the position name and any other context.", "example": "Backend role focused on Python, async APIs, and AWS.", "type": [ "string", "null" ] }, "description_long": { "description": "Full job description in Markdown (Job Purpose, Responsibilities, Required & Preferred Qualifications). Provide it to use it as-is; leave it null/blank and it is AI-generated (interview and assessment types only). Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons — formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown", "type": [ "string", "null" ] }, "environment": { "description": "Which of your webhook environments results from this interview are delivered to. Defaults to production. Options — `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..", "enum": [ "production", "uat", "development", "demo", null ], "example": "production", "type": [ "string", "null" ] }, "hiring_for_company": { "description": "Who the position is really for. Omit/null (or an object with name null/blank) when hiring for yourself; { name: 'undisclosed' } for an unnamed external client; or { name: '<company>' } plus optional description/location/sector/company_size for a named client. Stored in creation_parameters.hiring_for_company.", "example": { "name": "undisclosed" }, "properties": { "company_size": { "description": "Approximate headcount of the end employer.", "example": "100-200", "type": [ "string", "null" ] }, "description": { "description": "Short description of the end employer, used as background context by the agent.", "example": "Unimo Enterprises is a leading logistics and supply chain solutions provider.", "type": [ "string", "null" ] }, "location": { "description": "Primary location of the end employer.", "example": "Sri Lanka", "type": [ "string", "null" ] }, "name": { "description": "End-employer name. Omit/null when hiring for yourself, 'undisclosed' for an unnamed external client, or the client's company name.", "example": "Unimo Enterprises", "type": [ "string", "null" ] }, "sector": { "description": "Industry / sector of the end employer.", "example": "Logistics and Supply Chain", "type": [ "string", "null" ] } }, "type": [ "object", "null" ] }, "include_closing_prompt": { "description": "Include a closing prompt. Defaults to true.", "example": true, "type": [ "boolean", "null" ] }, "include_rapport_question": { "description": "Include an opening rapport question. Defaults to false.", "example": true, "type": [ "boolean", "null" ] }, "instructional_video": { "description": "Show an instructional video before approval. Defaults to false.", "example": true, "type": [ "boolean", "null" ] }, "instructional_video_custom_text": { "description": "Custom narration text for the instructional video.", "type": [ "string", "null" ] }, "interview_attempts": { "description": "Allowed candidate attempts (1-20).", "example": 1, "maximum": 20, "minimum": 1, "type": [ "number", "null" ] }, "interview_available_till": { "description": "ISO date/time after which the interview is no longer available to candidates. null keeps it always available.", "example": "2026-12-31", "type": [ "string", "null" ] }, "interview_conversation_speed": { "description": "Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options — `slower`: The avatar speaks more slowly — easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..", "enum": [ "slower", "normal", "faster", null ], "example": "normal", "type": [ "string", "null" ] }, "interview_department": { "description": "Department the position belongs to.", "example": "Engineering", "type": [ "string", "null" ] }, "interview_length": { "anyOf": [ { "type": "number" }, { "type": "string" }, {} ], "description": "Number of questions to generate (1-40). Also capped by max_duration, which allows one question per 2 minutes: 20 min -> 10 questions, 30 min -> 15, 45 min -> 22, 60 min -> 30, 80 min -> 40. Asking for more than the cap is not an error — you get the cap, and the response reports the real count in questions_generated. Omit this field to let the AI pick 5-8.", "example": 8 }, "interview_salary": { "description": "Salary range shown for the position.", "example": "$80k - $100k", "type": [ "string", "null" ] }, "interview_template_id": { "description": "Id of the interview template to base this interview on.", "example": "baa3bf7c-6926-46fd-9005-16738a31f72d", "format": "uuid", "minLength": 1, "type": [ "string", "null" ] }, "interview_tone": { "description": "Interview tone — configures the AI avatar's speaking style and the tone of the AI-generated questions and follow-ups. Case-insensitive; omit to default to relaxed. Options — `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level — short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing — for interviews built from your own questions (create_interview_from_questions) where the wording is a script..", "enum": [ "relaxed", "simple", "professional", "persuasive", "exact", null ], "example": "professional", "type": [ "string", "null" ] }, "interview_type": { "description": "Interview style — configures the AI avatar and shapes both the AI-generated questions and the follow-up questions asked during the interview. Defaults to pre-screening when omitted. Options — `pre-screening`: Pre-screening — quick qualification check focusing on basic requirements and availability. | `pre-screening-with-test-questions`: Pre-screening with test questions — pre-screening plus practical questions to test relevant skills. | `second-interview`: Second round interview — deeper dive for candidates who passed initial screening. | `remote-freelancer-verification`: Remote worker verification — verify remote work capabilities and communication skills. | `strength-based-interview`: Strength-based interview — focus on what candidates enjoy and excel at to predict job satisfaction. | `potential-based-interview`: Potential-based interview — assess learning ability and growth potential rather than past experience. | `process-verification-from-knowledge-base`: Knowledge Base interview — generate questions from your knowledge base documents..", "enum": [ "pre-screening", "pre-screening-with-test-questions", "second-interview", "remote-freelancer-verification", "strength-based-interview", "potential-based-interview", "process-verification-from-knowledge-base", null ], "example": "pre-screening-with-test-questions", "type": [ "string", "null" ] }, "is_embedded": { "description": "Set true when the interview will be embedded as an iframe on an external page. Provisions an embed key and returns embed_id / embed_signing_key, which are used to authenticate/sign the iframe embed.", "example": false, "type": [ "boolean", "null" ] }, "knowledge_base_store_id": { "description": "Knowledge base store id to source additional context from.", "type": [ "string", "null" ] }, "location": { "description": "Job location — a city/country, or `remote`. Required and must not be empty: when the job description gives no location, pass `Not specified`.", "example": "remote", "minLength": 1, "type": [ "string", "null" ] }, "max_duration": { "description": "Maximum interview duration in seconds. Scopes how many questions are generated (see interview_length) and is stored on the interview as the live session limit and the basis for the credit multiplier. Defaults to 1200 (20 minutes) when omitted.", "example": 1200, "type": [ "number", "null" ] }, "max_followups": { "description": "Maximum number of AI follow-up questions. 0 disables follow-ups; presets are 0-3 (none/low/normal/high) and custom values start at 4; null uses the template default (Normal).", "example": 2, "maximum": 999, "minimum": 0, "type": [ "integer", "null" ] }, "merchant_id": { "description": "Merchant id. Admin / sub-merchant callers only; otherwise taken from your token.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform language code used for the interview. Must be one of the platform-languages.json codes.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Interview / position name.", "example": "Project manager", "minLength": 1, "type": [ "string", "null" ] }, "pdf_export_auto_config": { "description": "Auto-generate a candidate PDF report with these options once the interview completes. null disables auto-export.", "properties": { "ai_recruiter_assessment": { "description": "Include the AI recruiter assessment.", "type": [ "boolean", "null" ] }, "ai_scoring_rubric": { "description": "Include the AI scoring rubric.", "type": [ "boolean", "null" ] }, "analytics": { "description": "Include analytics.", "type": [ "boolean", "null" ] }, "answer_recording": { "description": "Include per-answer recordings.", "type": [ "boolean", "null" ] }, "contact_details": { "description": "Include candidate contact details.", "type": [ "boolean", "null" ] }, "files": { "description": "Include uploaded candidate files.", "type": [ "boolean", "null" ] }, "group_by_question": { "description": "Group transcript answers by expected question.", "type": [ "boolean", "null" ] }, "mojito_language_code": { "description": "Report language code (a platform-languages.json code).", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "session_recording": { "description": "Include the full-session recording.", "type": [ "boolean", "null" ] }, "template": { "description": "Report layout: classic, modern, or one_pager. Omit for the merchant default (modern when unset).", "enum": [ "classic", "modern", "one_pager", null ], "type": [ "string", "null" ] }, "transcript": { "description": "Include the interview transcript.", "type": [ "boolean", "null" ] } }, "type": [ "object", "null" ] }, "questions_random_subset": { "description": "Ask only a random subset of the questions, expressed as a fraction between 0.01 and 0.9 (e.g. 0.5 = 50%). null asks all questions.", "example": 0.5, "maximum": 0.9, "minimum": 0.01, "type": [ "number", "null" ] }, "recording": { "description": "Cheating/proctoring detection mode for candidate answers — this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options — `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..", "enum": [ "audio_first_5_answers", "audio_all", "video_all", "video_first_5_answers", null ], "example": "video_all", "type": [ "string", "null" ] }, "recording_full_session": { "description": "Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options — `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..", "enum": [ "audio_all", "video_all", null ], "example": "video_all", "type": [ "string", "null" ] }, "recruiter_profile_id": { "description": "Profile id of the recruiter owning this interview. Must be a merchant/merchant_owner/admin profile of the same merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "type": [ "string", "null" ] }, "required_pronunciation": { "description": "Require pronunciation assessment (restricts to pronunciation-capable languages). Defaults to false.", "example": false, "type": [ "boolean", "null" ] }, "result_enable_edit_transcript": { "description": "Allow editing the transcript on the result view. Defaults to true.", "example": true, "type": [ "boolean", "null" ] }, "result_view": { "description": "Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options — `none`: No results screen at all — the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..", "enum": [ "none", "minimal", "minimal_with_score", "advanced", "full", "full_expand_scores", null ], "example": "full", "type": [ "string", "null" ] }, "seniority_level": { "description": "Target seniority level for the role; auto-detected from the job description when omitted. Options — `entry-level`: Early-career or graduate roles. | `intermediate`: Some experience required. | `senior`: Experienced professional. | `managerial`: Team or department lead. | `director`: Director-level responsibility. | `executive`: C-suite or executive role..", "enum": [ "entry-level", "intermediate", "senior", "managerial", "director", "executive", null ], "example": "senior", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status of the interview. Options — `draft`: Created but not published — not visible to candidates and cannot be run yet. Use to stage an interview before going live. | `active`: Published and live — candidates can run it..", "enum": [ "draft", "active", null ], "example": "active", "type": [ "string", "null" ] }, "tags": { "description": "Free-form tags stored on the interview. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed.", "example": [ "interview-practice", "sales" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "thank_you_message": { "description": "Custom thank-you message shown after the interview.", "type": [ "string", "null" ] }, "type": { "description": "Product type of the interview. Options — `interview`: Standard candidate interview for a role — answers are AI-scored and produce a hiring recommendation. | `coaching`: Practice/coaching session — candidate-facing feedback to help them improve; not a hiring evaluation. Only available on the coaching portal, NOT the interview portal. | `assessment`: Skills/knowledge assessment — evaluates competencies and is scored like an interview..", "enum": [ "interview", "coaching", "assessment", null ], "example": "interview", "type": [ "string", "null" ] }, "use_enhanced_expectations": { "description": "Reserved flag passed through to generation.", "type": [ "boolean", "null" ] }, "visibility": { "description": "Who can discover and access the interview. Options — `merchant_public`: Listed on the merchant's public interview list — anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only — only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link — not listed anywhere; share the link manually..", "enum": [ "merchant_public", "merchant_invite", "merchant_unlisted", null ], "example": "merchant_public", "type": [ "string", "null" ] }, "welcome_message": { "description": "Custom welcome message shown to the candidate.", "type": [ "string", "null" ] } }, "required": [ "name", "location", "interview_template_id", "mojito_language_code", "status", "type", "visibility" ], "type": "object" }, "name": "create_interview", "outputSchema": { "description": "Id of the created interview, the number of questions generated and the stored max_duration. Includes embed_id/embed_signing_key when is_embedded=true.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "embed_id": { "description": "Embed id, present only when is_embedded=true.", "type": [ "string", "null" ] }, "embed_signing_key": { "description": "Embed signing key, present only when is_embedded=true.", "type": [ "string", "null" ] }, "interview_def_set_id": { "description": "Id of the newly created interview definition set.", "example": "00000000-0000-0000-0000-000000000000", "type": [ "string", "null" ] }, "max_duration": { "description": "Live session limit in seconds stored on the interview — the value sent, or the 1200 default when omitted.", "example": 1200, "type": [ "number", "null" ] }, "questions_generated": { "description": "Number of questions actually generated. May be lower than the requested interview_length, which is capped by max_duration.", "example": 8, "type": [ "number", "null" ] } }, "required": [ "interview_def_set_id", "questions_generated", "max_duration" ], "type": "object", "x-fastmcp-top-level-schema": "JobInterviewCreateResponse" } }, { "description": "[Interviews] Create a new interview from an explicit array of questions. The AI rephrases your wording by default; pass `interview_tone=\"exact\"` to have each question asked verbatim, which is what you want when the wording is a script (compliance, translated, or legally reviewed text).\n\nCreates a new interview definition set from a caller-provided array of questions, builds its default and generated steps, optionally activates it, and optionally creates an embed key.", "inputSchema": { "properties": { "additional_context": { "additionalProperties": {}, "description": "Extra context forwarded to expectation generation.", "type": [ "object", "null" ] }, "candidate_expectations": { "description": "Free-text candidate expectations.", "type": [ "string", "null" ] }, "candidate_expectations_json": { "description": "Pre-generated candidate expectations, bucketed by requirement level (weak/moderate/strong); auto-generated when omitted for type=interview. Extra keys are preserved.", "properties": { "moderate": { "description": "Requirements expected of a solid, competent candidate.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "strong": { "description": "High-bar requirements only standout candidates clear.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "weak": { "description": "Baseline requirements every viable candidate should meet (table stakes).", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "type": [ "object", "null" ] }, "candidate_video_introduction": { "description": "Whether a candidate video introduction is optional or required.", "enum": [ "optional", "required", null ], "type": [ "string", "null" ] }, "code": { "description": "Optional external code/reference.", "type": [ "string", "null" ] }, "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "cover_image_url": { "description": "Cover image URL.", "type": [ "string", "null" ] }, "custom_scoring": { "additionalProperties": {}, "description": "Custom scoring overrides merged with defaults.", "type": [ "object", "null" ] }, "description": { "description": "Short interview description.", "example": "Project manager role", "minLength": 1, "type": [ "string", "null" ] }, "description_long": { "description": "Long-form interview description. Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons — formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown", "type": [ "string", "null" ] }, "disable_deduplication": { "description": "When true, skip step deduplication on insert.", "type": [ "boolean", "null" ] }, "environment": { "description": "Which of your webhook environments results from this interview are delivered to. Defaults to production. Options — `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..", "enum": [ "production", "uat", "development", "demo", null ], "example": "production", "type": [ "string", "null" ] }, "hiring_for_company": { "description": "Who the position is really for. Omit/null (or an object with name null/blank) when hiring for yourself; { name: 'undisclosed' } for an unnamed external client; or { name: '<company>' } plus optional description/location/sector/company_size for a named client. Stored in creation_parameters.hiring_for_company.", "example": { "name": "undisclosed" }, "properties": { "company_size": { "description": "Approximate headcount of the end employer.", "example": "100-200", "type": [ "string", "null" ] }, "description": { "description": "Short description of the end employer, used as background context by the agent.", "example": "Unimo Enterprises is a leading logistics and supply chain solutions provider.", "type": [ "string", "null" ] }, "location": { "description": "Primary location of the end employer.", "example": "Sri Lanka", "type": [ "string", "null" ] }, "name": { "description": "End-employer name. Omit/null when hiring for yourself, 'undisclosed' for an unnamed external client, or the client's company name.", "example": "Unimo Enterprises", "type": [ "string", "null" ] }, "sector": { "description": "Industry / sector of the end employer.", "example": "Logistics and Supply Chain", "type": [ "string", "null" ] } }, "type": [ "object", "null" ] }, "instructional_video": { "description": "Enable an instructional video before approval.", "type": [ "boolean", "null" ] }, "instructional_video_custom_text": { "description": "Custom text for the instructional video.", "type": [ "string", "null" ] }, "interview_attempts": { "description": "Allowed attempts, 1-20.", "example": 1, "type": [ "number", "null" ] }, "interview_available_till": { "description": "ISO date/time after which the interview is no longer available to candidates. null keeps it always available.", "example": "2026-12-31", "type": [ "string", "null" ] }, "interview_conversation_speed": { "description": "Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options — `slower`: The avatar speaks more slowly — easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..", "enum": [ "slower", "normal", "faster", null ], "example": "normal", "type": [ "string", "null" ] }, "interview_department": { "description": "Department the position belongs to.", "example": "Engineering", "type": [ "string", "null" ] }, "interview_salary": { "description": "Salary range shown for the position.", "example": "$80k - $100k", "type": [ "string", "null" ] }, "interview_template_id": { "description": "Id of the interview template to use. Must reference an existing interview_templates row.", "example": "46b98d37-1557-4391-beca-03037ead19f2", "minLength": 1, "type": [ "string", "null" ] }, "interview_tone": { "description": "Tone — configures the AI avatar's speaking style and the follow-up questions it generates; the base `questions` you supply are not affected. Case-insensitive; omit to default to relaxed. Options — `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level — short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing — for interviews built from your own questions (create_interview_from_questions) where the wording is a script..", "enum": [ "relaxed", "simple", "professional", "persuasive", "exact", null ], "example": "professional", "type": [ "string", "null" ] }, "interview_type": { "description": "Interview style — configures the AI avatar and the follow-up questions it generates during the interview. The base `questions` you supply are used as-is and are NOT affected by this setting. Options — `pre-screening`: Pre-screening — quick qualification check focusing on basic requirements and availability. | `pre-screening-with-test-questions`: Pre-screening with test questions — pre-screening plus practical questions to test relevant skills. | `second-interview`: Second round interview — deeper dive for candidates who passed initial screening. | `remote-freelancer-verification`: Remote worker verification — verify remote work capabilities and communication skills. | `strength-based-interview`: Strength-based interview — focus on what candidates enjoy and excel at to predict job satisfaction. | `potential-based-interview`: Potential-based interview — assess learning ability and growth potential rather than past experience. | `process-verification-from-knowledge-base`: Knowledge Base interview — generate questions from your knowledge base documents..", "enum": [ "pre-screening", "pre-screening-with-test-questions", "second-interview", "remote-freelancer-verification", "strength-based-interview", "potential-based-interview", "process-verification-from-knowledge-base", null ], "example": "pre-screening-with-test-questions", "type": [ "string", "null" ] }, "is_embedded": { "description": "Set true when the interview will be embedded as an iframe on an external page. Creates an embed key and returns embed_id/embed_signing_key, used to authenticate/sign the iframe embed.", "type": [ "boolean", "null" ] }, "knowledge_base_store_id": { "description": "Optional knowledge base store id; validated for existence.", "type": [ "string", "null" ] }, "location": { "description": "Job location — a city/country, or `remote`. Required and must not be empty: when the job description gives no location, pass `Not specified`.", "example": "remote", "minLength": 1, "type": [ "string", "null" ] }, "max_followups": { "description": "Maximum number of AI follow-up questions. 0 disables follow-ups; presets are 0-3 (none/low/normal/high) and custom values start at 4; null uses the template default (Normal).", "example": 2, "maximum": 999, "minimum": 0, "type": [ "integer", "null" ] }, "merchant_id": { "description": "Target merchant id (admins / sub-merchant only).", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform language code (one of the platform-languages.json codes); must also resolve to a supported language with an Azure speech mapping.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Interview/position name.", "example": "Project manager", "minLength": 1, "type": [ "string", "null" ] }, "pdf_export_auto_config": { "description": "Auto-generate a candidate PDF report with these options once the interview completes. null disables auto-export.", "properties": { "ai_recruiter_assessment": { "description": "Include the AI recruiter assessment.", "type": [ "boolean", "null" ] }, "ai_scoring_rubric": { "description": "Include the AI scoring rubric.", "type": [ "boolean", "null" ] }, "analytics": { "description": "Include analytics.", "type": [ "boolean", "null" ] }, "answer_recording": { "description": "Include per-answer recordings.", "type": [ "boolean", "null" ] }, "contact_details": { "description": "Include candidate contact details.", "type": [ "boolean", "null" ] }, "files": { "description": "Include uploaded candidate files.", "type": [ "boolean", "null" ] }, "group_by_question": { "description": "Group transcript answers by expected question.", "type": [ "boolean", "null" ] }, "mojito_language_code": { "description": "Report language code (a platform-languages.json code).", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "session_recording": { "description": "Include the full-session recording.", "type": [ "boolean", "null" ] }, "template": { "description": "Report layout: classic, modern, or one_pager. Omit for the merchant default (modern when unset).", "enum": [ "classic", "modern", "one_pager", null ], "type": [ "string", "null" ] }, "transcript": { "description": "Include the interview transcript.", "type": [ "boolean", "null" ] } }, "type": [ "object", "null" ] }, "questions": { "description": "Ordered list of interview questions to create as steps.", "items": { "additionalProperties": {}, "properties": { "candidate_expectations_json": { "description": "Per-question candidate expectations, bucketed by requirement level (weak/moderate/strong). Extra keys are preserved.", "properties": { "moderate": { "description": "Requirements expected of a solid, competent candidate.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "strong": { "description": "High-bar requirements only standout candidates clear.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "weak": { "description": "Baseline requirements every viable candidate should meet (table stakes).", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "type": [ "object", "null" ] }, "conditional_question_main_id": { "description": "For a conditional question, the id (the \"id\" field above) of the parent question in this same array that triggers it. The parent must appear earlier in the array than the conditional question referencing it.", "type": [ "string", "null" ] }, "duration": { "description": "Answer duration in seconds for this question.", "type": [ "number", "null" ] }, "external_data": { "additionalProperties": {}, "description": "Arbitrary JSON metadata stored on the question.", "type": [ "object", "null" ] }, "external_id": { "description": "External identifier stored on the question. job-interview-update matches on this first, so an ATS that owns stable ids can send its own array and have the diff line up without round-tripping our ids.", "type": [ "string", "null" ] }, "id": { "description": "Identifier for this question. job-interview-get returns the question's real id here; send it back to job-interview-update so an unchanged question keeps its existing record (and with it its answer rules and any rendered avatar video). Also the handle another question references via conditional_question_main_id. On job-interview-create-from-array it is a caller-local value, only needed for those references.", "type": [ "string", "null" ] }, "is_candidate_asking_recruiter": { "description": "Candidate-asks-recruiter prompt (view 'candidate asking recruiter').", "type": [ "boolean", "null" ] }, "is_conditional": { "description": "Conditional follow-up question (view 'with listening conditional'). Use with conditional_question_main_id.", "type": [ "boolean", "null" ] }, "is_expert": { "description": "Expert listening question (view 'with listening expert').", "type": [ "boolean", "null" ] }, "is_multiple_choice": { "description": "Multiple-choice question (view 'multiple choice').", "type": [ "boolean", "null" ] }, "is_without_scoring": { "description": "Question is asked but not scored (view 'without scoring').", "type": [ "boolean", "null" ] }, "knowledge_base_id": { "description": "Knowledge-base store id (uuid) the question draws context from.", "type": [ "string", "null" ] }, "label": { "description": "Optional label/tag stored on the question.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Per-question language override (one of the platform-languages.json codes). Inherits the interview language when omitted.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "question": { "description": "The question text shown to the candidate.", "type": [ "string", "null" ] }, "question_alternatives": { "description": "Alternative phrasings for the question.", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "required": [ "question" ], "type": "object" }, "minItems": 1, "type": [ "array", "null" ] }, "questions_random_subset": { "description": "Fraction of questions to randomly ask, between 0.01 and 0.9.", "type": [ "number", "null" ] }, "recording": { "description": "Cheating/proctoring detection mode for candidate answers — this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options — `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..", "enum": [ "audio_first_5_answers", "audio_all", "video_all", "video_first_5_answers", null ], "example": "video_all", "type": [ "string", "null" ] }, "recording_full_session": { "description": "Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options — `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..", "enum": [ "audio_all", "video_all", null ], "example": "video_all", "type": [ "string", "null" ] }, "recruiter_profile_id": { "description": "Profile id of the recruiter owning this interview. Must be a merchant/merchant_owner/admin profile of the same merchant.", "type": [ "string", "null" ] }, "required_pronunciation": { "description": "Require pronunciation assessment (restricts to pronunciation-capable languages). Defaults to false.", "example": false, "type": [ "boolean", "null" ] }, "result_enable_edit_transcript": { "description": "Allow editing the transcript on the result view. Defaults to true.", "example": true, "type": [ "boolean", "null" ] }, "result_view": { "description": "Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options — `none`: No results screen at all — the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..", "enum": [ "none", "minimal", "minimal_with_score", "advanced", "full", "full_expand_scores", null ], "example": "full", "type": [ "string", "null" ] }, "seniority_level": { "description": "Target seniority level for the role; auto-detected from the job description when omitted. Options — `entry-level`: Early-career or graduate roles. | `intermediate`: Some experience required. | `senior`: Experienced professional. | `managerial`: Team or department lead. | `director`: Director-level responsibility. | `executive`: C-suite or executive role..", "enum": [ "entry-level", "intermediate", "senior", "managerial", "director", "executive", null ], "example": "senior", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status of the interview. Options — `draft`: Created but not published — not visible to candidates and cannot be run yet. Use to stage an interview before going live. | `active`: Published and live — candidates can run it..", "enum": [ "draft", "active", null ], "example": "active", "type": [ "string", "null" ] }, "tags": { "description": "Free-form tags stored on the interview. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed.", "example": [ "interview-practice", "sales" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "thank_you_message": { "description": "Custom thank-you message.", "type": [ "string", "null" ] }, "type": { "description": "Product type of the interview. Options — `interview`: Standard candidate interview for a role — answers are AI-scored and produce a hiring recommendation. | `coaching`: Practice/coaching session — candidate-facing feedback to help them improve; not a hiring evaluation. Only available on the coaching portal, NOT the interview portal. | `assessment`: Skills/knowledge assessment — evaluates competencies and is scored like an interview..", "enum": [ "interview", "coaching", "assessment", null ], "example": "interview", "type": [ "string", "null" ] }, "visibility": { "description": "Who can discover and access the interview. Options — `merchant_public`: Listed on the merchant's public interview list — anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only — only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link — not listed anywhere; share the link manually..", "enum": [ "merchant_public", "merchant_invite", "merchant_unlisted", null ], "example": "merchant_public", "type": [ "string", "null" ] }, "welcome_message": { "description": "Custom welcome message.", "type": [ "string", "null" ] } }, "required": [ "name", "location", "interview_template_id", "mojito_language_code", "description", "status", "type", "visibility", "questions" ], "type": "object" }, "name": "create_interview_from_questions", "outputSchema": { "description": "The created interview definition set id, plus embed credentials when is_embedded=true.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "embed_id": { "description": "Embed id, present only when is_embedded=true.", "type": [ "string", "null" ] }, "embed_signing_key": { "description": "Embed signing key, present only when is_embedded=true.", "type": [ "string", "null" ] }, "interview_def_set_id": { "description": "Id of the newly created interview definition set.", "type": [ "string", "null" ] } }, "required": [ "interview_def_set_id" ], "type": "object", "x-fastmcp-top-level-schema": "JobInterviewCreateFromArrayResponse" } }, { "description": "[Interviews] Create a role-play persona: an avatar that plays a defined role in a free-form conversation instead of a scored Q&A interview. FIRST CHOOSE `portal`, because it selects between two different products: `portal=\"interview\"` builds a SIMULATED PERSONA a recruiter invites candidates to — scored, billed to merchant credits, and listed with the recruiter's other results; `portal=\"coaching\"` (THE DEFAULT) builds a coaching persona learners start themselves from the catalogue, billed to their own coaching credits and never visible to recruiters. Pass `portal=\"interview\"` explicitly for any hiring, screening or assessment use. Then set `persona_role_avatar`/`persona_role_user` for the roles and `opening_line` for the avatar's first spoken line (defaults to a generic 'Hello').\n\nFIRST DECIDE `portal`. This endpoint creates two different products and the default is NOT the recruiter one:\n- `portal: \"interview\"` — an INTERVIEW ROLE-PLAY. Use this whenever the goal is to ASSESS or SCREEN candidates: hiring, assessments, sales role-plays for job applicants, anything a recruiter runs. Candidates are invited through the normal invitation flow, results appear in the recruiter's result list, it is billed against merchant credits, and attempts are capped via `interview_attempts` — exactly like an interview.\n- `portal: \"coaching\"` (THE DEFAULT) — a coaching persona for practice/training on the coaching portal. Consumed against the mentee's own coaching credits, self-started from the catalogue, and its results are NOT visible to recruiters. Omitting `portal` gives you this one, so pass `portal: \"interview\"` explicitly for any recruiting/assessment use case.\nThe conversation itself behaves identically in both.\n\nThe avatar plays a defined role in a free-form conversation instead of running a scored Q&A interview. No AI question/description generation runs; the persona role fields ARE the configuration. The session runs as: a welcome message → the avatar's OPENING LINE (the first thing it says, set via `opening_line`) → the candidate replies and the free-form role-play begins → a closing message. Because there is no question list, `opening_line` is how the avatar starts the scene — set it to a concrete in-character line; if omitted it defaults to a generic \"Hello\". Set `welcome_message` and `thank_you_message` too — omitting them leaves the generic platform defaults. Also set `candidate_expectations`: it is the yardstick the session is scored against. The four avatar prompts divide up as: `persona_avatar_who_is` (identity and what drives it), `persona_avatar_knowledge` (the private facts it may use), `persona_avatar_progress` (how the conversation is allowed to move forward, and what gates the later personal details), and `persona_avatar_end_conditions` (when to stop). Without `persona_avatar_progress` the avatar has no defined arc and tends to either concede immediately or never concede at all. Provisions the default conversational steps and optionally an embed key.", "inputSchema": { "properties": { "candidate_expectations": { "description": "Mentee assessment goals — free-text describing what the candidate is expected to achieve (max 2100 chars).", "maxLength": 2100, "type": [ "string", "null" ] }, "candidate_video_introduction": { "description": "Whether a candidate video introduction is optional or required.", "enum": [ "optional", "required", null ], "example": "optional", "type": [ "string", "null" ] }, "code": { "description": "Optional external code/reference for the persona.", "example": "my code", "type": [ "string", "null" ] }, "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "cover_image_url": { "description": "Cover image URL.", "example": "https://example.com/cover.png", "type": [ "string", "null" ] }, "description": { "description": "Short persona description shown to the candidate on the pre-session poster. Candidate-visible — keep it to max 2 sentences. Unlike job-interview-create, personas run no AI generation, so this is never auto-generated: leave it null/blank and the poster simply shows no description; set it to frame the scene.", "example": "A quick sales role-play with an unhappy customer. Your goal is to resolve their complaint and keep the account.", "type": [ "string", "null" ] }, "environment": { "description": "Which of your webhook environments results from this interview are delivered to. Defaults to production. Options — `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..", "enum": [ "production", "uat", "development", "demo", null ], "example": "production", "type": [ "string", "null" ] }, "interview_attempts": { "description": "Allowed candidate attempts (1-20), defaulting to 3. Only meaningful when `portal` is `interview`; coaching personas are unlimited. A recruiter can still grant an extra attempt afterwards.", "example": 3, "maximum": 20, "minimum": 1, "type": [ "number", "null" ] }, "interview_conversation_speed": { "description": "Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options — `slower`: The avatar speaks more slowly — easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..", "enum": [ "slower", "normal", "faster", null ], "example": "normal", "type": [ "string", "null" ] }, "interview_location": { "description": "Optional location label shown for the session.", "example": "remote", "type": [ "string", "null" ] }, "interview_template_id": { "description": "Id of the interview template (avatar) the persona uses.", "example": "baa3bf7c-6926-46fd-9005-16738a31f72d", "format": "uuid", "minLength": 1, "type": [ "string", "null" ] }, "is_embedded": { "description": "Set true when the persona will be embedded as an iframe on an external page. Provisions an embed key and returns embed_id / embed_signing_key.", "example": false, "type": [ "boolean", "null" ] }, "max_duration": { "description": "Maximum conversation duration in seconds. Defaults to 1200 (20 min) when omitted.", "example": 1200, "type": [ "number", "null" ] }, "merchant_id": { "description": "Merchant id. Admin / sub-merchant callers only; otherwise taken from your token.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform language code used for the conversation. Must be one of the platform-languages.json codes.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Persona / session name.", "example": "Difficult customer role-play", "minLength": 1, "type": [ "string", "null" ] }, "opening_line": { "description": "The avatar's opening line — the FIRST thing it says out loud when the session starts, before the candidate has said anything. This is a literal spoken line, NOT a description: write the exact words the avatar should say, in character and consistent with persona_role_avatar. For an escalated scenario it should already convey that state (e.g. an angry customer opens angrily). If omitted, the platform inserts a generic default (\"Hello\"), which is usually a weak opener — set this for anything other than a neutral greeting.", "example": "Oh, finally — someone actually comes over! I've been waiting for ages. Are you going to help me or not?", "type": [ "string", "null" ] }, "persona_avatar_end_conditions": { "description": "When the avatar should end the session. Prefer referring to persona_avatar_progress: wrap up when progress is complete (turning point unlocked and a plan accepted, or steps \"Done when\" reached), or when the conversation has clearly broken down.", "type": [ "string", "null" ] }, "persona_avatar_knowledge": { "description": "Private facts the avatar can use (numbers, dates, names, objections), plus any personal details shareable only after progress and only if natural — timing written inline, not as labelled subsections. Those personal details are never required for the goal.", "type": [ "string", "null" ] }, "persona_avatar_progress": { "description": "How the conversation moves forward — one plain-text value starting with `Mode: turning point` (resistance) or `Mode: steps` (difficult conversation protocol), then the labelled lines for that mode (Initial hold / Unlocks when / … or Framework / Steps / …), including a Gates line: do not share later personal details from persona_avatar_knowledge until progress is earned.", "example": "Mode: turning point\nInitial hold: ...\nUnlocks when: ...\nAfter unlock: ...\nHard limits: ...\nNo goalposts: ...\nGates: ...", "type": [ "string", "null" ] }, "persona_avatar_who_is": { "description": "Who the avatar represents: name, role, context, personality, woven with what drives them underneath (motive, fear, what they refuse until heard, what they do not know until told). One continuous description; no labelled subsections.", "type": [ "string", "null" ] }, "persona_role_avatar": { "description": "The role the AI avatar plays. Candidate-visible — shown on the pre-session poster as 'Role of the agent', so write it as candidate-facing setup and keep it to max 2 sentences. Example: 'is to act as a happy customer responding to questions'.", "example": "is to act as a happy customer responding to questions", "minLength": 1, "type": [ "string", "null" ] }, "persona_role_user": { "description": "The role the candidate (mentee) plays. Candidate-visible — shown on the pre-session poster as 'Your role', so write it as candidate-facing setup and keep it to max 2 sentences. Example: 'is to be a sales person trying to sell an additional product to the customer'.", "example": "is to be a sales person trying to sell an additional product to the customer", "minLength": 1, "type": [ "string", "null" ] }, "portal": { "description": "REQUIRED IN PRACTICE — pick deliberately; the default is the coaching product, not the recruiting one. `interview`: an interview role-play. Choose this for ANY recruiting or assessment use case (screening candidates, hiring, sales role-plays for applicants). Candidates are invited through the normal invitation flow, results are visible to the recruiter alongside ordinary interview results, it is billed against your merchant credits on the same basis as an interview, and attempts are capped (see `interview_attempts`). | `coaching` (DEFAULT when omitted): the classic coaching persona for practice/training. Runs on the coaching portal, is consumed against the mentee's own coaching credits, is started by the mentee from the catalogue or a shared link, and its results are NOT visible to recruiters. The conversation itself behaves identically in both cases — only the portal, billing, visibility and attempt limits differ.", "enum": [ "coaching", "interview", null ], "example": "interview", "type": [ "string", "null" ] }, "recording": { "description": "Cheating/proctoring detection mode for candidate answers — this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options — `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..", "enum": [ "audio_first_5_answers", "audio_all", "video_all", "video_first_5_answers", null ], "example": "video_all", "type": [ "string", "null" ] }, "recording_full_session": { "description": "Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options — `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..", "enum": [ "audio_all", "video_all", null ], "example": "video_all", "type": [ "string", "null" ] }, "recruiter_profile_id": { "description": "Profile id of the recruiter owning this persona. Must be a merchant/merchant_owner/admin profile of the same merchant.", "type": [ "string", "null" ] }, "result_view": { "description": "Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options — `none`: No results screen at all — the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..", "enum": [ "none", "minimal", "minimal_with_score", "advanced", "full", "full_expand_scores", null ], "example": "full", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status of the interview. Options — `draft`: Created but not published — not visible to candidates and cannot be run yet. Use to stage an interview before going live. | `active`: Published and live — candidates can run it..", "enum": [ "draft", "active", null ], "example": "active", "type": [ "string", "null" ] }, "tags": { "description": "Free-form tags stored on the persona. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed.", "example": [ "interview-practice", "sales" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "thank_you_message": { "description": "Custom thank-you message shown after the session — set it; omitting it leaves a generic platform default.", "example": "Thanks — your role-play has been recorded and will be reviewed by the hiring team.", "type": [ "string", "null" ] }, "visibility": { "description": "Who can discover and access the interview. Options — `merchant_public`: Listed on the merchant's public interview list — anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only — only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link — not listed anywhere; share the link manually..", "enum": [ "merchant_public", "merchant_invite", "merchant_unlisted", null ], "example": "merchant_public", "type": [ "string", "null" ] }, "welcome_message": { "description": "Custom welcome message spoken to the candidate before the role-play starts — set it; omitting it leaves a generic platform default. This is the scene-setting message; the avatar's first in-character line is `opening_line`, which comes after it.", "example": "Welcome! You are about to speak with a customer who is unhappy about a recent price increase.", "type": [ "string", "null" ] } }, "required": [ "name", "interview_template_id", "mojito_language_code", "status", "visibility", "persona_role_avatar", "persona_role_user" ], "type": "object" }, "name": "create_persona", "outputSchema": { "description": "Id of the created persona. Includes embed_id/embed_signing_key when is_embedded=true.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "embed_id": { "description": "Embed id, present only when is_embedded=true.", "type": [ "string", "null" ] }, "embed_signing_key": { "description": "Embed signing key, present only when is_embedded=true.", "type": [ "string", "null" ] }, "interview_def_set_id": { "description": "Id of the newly created persona definition set.", "example": "00000000-0000-0000-0000-000000000000", "type": [ "string", "null" ] } }, "required": [ "interview_def_set_id" ], "type": "object", "x-fastmcp-top-level-schema": "PersonaCreateResponse" } }, { "description": "[Results] Generate an interview result report (HTML/PDF/JSON) for a completed interview. The report is decision-support material for a human reviewer, not an automated hiring decision.\n\nGenerates an interview result report as a PDF (returns a signed URL), raw HTML, or structured JSON. Provide either `interview_result_id` for a single result or `interview_result_ids` for a combined multi-result report.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "export_features_result": { "properties": { "ai_recruiter_assessment": { "default": true, "description": "Include the AI recruiter assessment: resume analysis, overall AI analysis, and the why-hire / why-not-hire summaries.", "type": [ "boolean", "null" ] }, "ai_scoring_rubric": { "default": false, "description": "Include the AI scoring rubric — the candidate-expectation buckets (strong / moderate / weak). Only takes effect when ai_recruiter_assessment is also true.", "type": [ "boolean", "null" ] }, "analytics": { "default": true, "description": "Include speech analytics for each answer (speech accuracy, fluency, recognition confidence, sentiment, cadence / words-per-minute).", "type": [ "boolean", "null" ] }, "answer_recording": { "default": false, "description": "Include a signed recording URL (audio/video) for each individual answer.", "type": [ "boolean", "null" ] }, "contact_details": { "default": true, "description": "Include the candidate's contact details (email, LinkedIn, phone number, physical address).", "type": [ "boolean", "null" ] }, "files": { "default": true, "description": "Include the candidate's uploaded files (resume and cover letter) as signed page URLs.", "type": [ "boolean", "null" ] }, "group_by_question": { "default": false, "description": "Group answers under their expected questions (instead of chronological order), including questions that were not reached.", "type": [ "boolean", "null" ] }, "mojito_language_code": { "description": "Report language. Optional: if omitted, the report uses each result's own language code. If provided and it differs from the result's language, the report content is translated, which costs 0.1 credit per result.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "session_recording": { "default": false, "description": "Include the full interview session recording and the video introduction as signed URLs.", "type": [ "boolean", "null" ] }, "template": { "description": "Report layout for this export. Same values as the top-level `template`; the top-level field wins when both are given. Kept here so a saved auto-export configuration carries its template.", "enum": [ "classic", "modern", "one_pager" ], "example": "modern", "type": "string" }, "transcript": { "default": true, "description": "Include the full interview transcript: each question, the candidate answer, and the per-answer AI analysis.", "type": [ "boolean", "null" ] } }, "type": "object" }, "export_type": { "enum": [ "pdf", "html", "json", null ], "type": [ "string", "null" ] }, "interview_result_id": { "example": "93c98d21-e04d-4a84-9afa-ed154cf73636", "format": "uuid", "type": [ "string", "null" ] }, "interview_result_ids": { "description": "Generate a single combined report for multiple results.", "items": { "format": "uuid", "type": "string" }, "type": [ "array", "null" ] }, "store_file": { "description": "When true (pdf only), persist the file to storage and return a signed URL.", "type": [ "boolean", "null" ] }, "template": { "allOf": [ { "description": "Report layout for this export. Same values as the top-level `template`; the top-level field wins when both are given. Kept here so a saved auto-export configuration carries its template.", "enum": [ "classic", "modern", "one_pager" ], "example": "modern", "type": "string" }, { "description": "Report layout: `classic`, `modern` or `one_pager`. Omit for the merchant default (modern when unset)." } ] } }, "required": [ "export_type" ], "type": "object" }, "name": "generate_interview_report", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "result": { "anyOf": [ { "description": "Returned when `export_type` is `pdf`.", "properties": { "pdf_export_url": { "description": "Signed URL of the generated PDF.", "format": "uri", "type": [ "string", "null" ] }, "pdf_export_valid_until": { "description": "ISO timestamp until which the signed URL is valid.", "example": "2026-09-01T12:00:00.000Z", "type": [ "string", "null" ] } }, "required": [ "pdf_export_url", "pdf_export_valid_until" ], "title": "PDF export", "type": "object" }, { "description": "Returned when `export_type` is `html`.", "properties": { "html_export": { "description": "The full report rendered as an HTML document string.", "type": [ "string", "null" ] } }, "required": [ "html_export" ], "title": "HTML export", "type": "object" }, { "description": "Returned when `export_type` is `json`.", "properties": { "json_export": { "properties": { "results": { "items": { "properties": { "data": { "additionalProperties": {}, "type": [ "object", "null" ] }, "files": { "items": { "properties": { "page": { "type": [ "number", "null" ] }, "page_signed": { "type": [ "string", "null" ] }, "type": { "type": [ "string", "null" ] } }, "required": [ "type", "page", "page_signed" ], "type": "object" }, "type": [ "array", "null" ] } }, "required": [ "data", "files" ], "type": "object" }, "type": [ "array", "null" ] }, "table": { "description": "Overview table HTML, present only for multi-result exports.", "type": [ "string", "null" ] } }, "required": [ "results" ], "type": [ "object", "null" ] } }, "required": [ "json_export" ], "title": "JSON export", "type": "object" } ], "description": "The generated report. Exactly one of the three shapes below is returned, selected by the request `export_type`: `pdf` → `{ pdf_export_url, pdf_export_valid_until }`; `html` → `{ html_export }`; `json` → `{ json_export }`.", "x-fastmcp-top-level-schema": "JobInterviewPdfResponse" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "[Interviews] Generate a signed public interview URL/token.\n\nGenerates a public, token-signed URL for an existing interview, profile, or result. The required id fields depend on `type`.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "hide_menu": { "anyOf": [ { "type": "string" }, { "type": "boolean" } ], "description": "Pass the string 'false' to show the navigation menu; any other value hides it (default)." }, "interview_id": { "description": "Interview or position id. Required for interview-for-profile and interview-results-for-position.", "type": [ "string", "null" ] }, "interview_profile_id": { "description": "Candidate profile id. Required for interview-for-profile and results-for-profile.", "type": [ "string", "null" ] }, "interview_result_id": { "description": "Interview result id. Required for interview-result-candidate and interview-result-talent-seeker.", "type": [ "string", "null" ] }, "merchant_id": { "description": "Override merchant id (admin / sub-merchant only).", "type": [ "string", "null" ] }, "type": { "description": "Which kind of signed URL to generate.", "enum": [ "interview-for-profile", "results-for-profile", "interview-result-candidate", "interview-result-talent-seeker", "interview-results-for-position", null ], "type": [ "string", "null" ] } }, "required": [ "type" ], "type": "object" }, "name": "generate_interview_url", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "result": { "description": "The signed interview URL.", "example": "https://interviews.example.com/interview/take/<id>/?interview_token=<jwt>&view_hm=true", "type": "string", "x-fastmcp-top-level-schema": "JobInterviewTokenResponse" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "[Coaching catalogue] Read one catalogue directory in full: its settings, its custom Markdown page (`content_md`), its resolved sub-directories, and the coaching sessions its tag filter currently matches — which is how you verify that a session's `tags` actually place it in this directory. Read before updating: `content_md`, `tags_sub` and `tags_interview_set_filter` are replaced wholesale, so you need the current value to extend it.\n\nReads one catalogue directory in full: its settings, its custom Markdown page (`content_md`), the sub-directories it nests, and the coaching sessions its `tags_interview_set_filter` currently matches. Read a directory before updating it — `content_md`, `tags_sub` and `tags_interview_set_filter` are replaced wholesale by catalogue-tag-update, so you need the current value to extend rather than overwrite it.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "id": { "description": "Id of the catalogue directory to read (the catalogue URL segment).", "example": "sales-coaching-en", "minLength": 1, "type": "string" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "get_catalogue_directory", "outputSchema": { "description": "One catalogue directory with its content page, sub-directories and matched sessions.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "catalogue_url": { "description": "Public URL of this directory page, when the merchant has a coaching-portal domain configured.", "example": "https://coaching.example.com/catalogue/sales-coaching-en", "type": [ "string", "null" ] }, "coach_plan": { "description": "Coaching-plan stage, when the directory belongs to one.", "type": [ "string", "null" ] }, "content_md": { "description": "Markdown for a custom directory page. When set (even as an empty string) the markdown replaces the default grid and decides the layout itself; null renders the plain grid of sub-directories and sessions. Alongside normal Markdown you can place these directives, each ALONE on its own line: `[plan-progress]` (the learner's coaching-plan progress), `[directory:<tag-id>]` (a card for one sub-directory), `[session:<interview-id>]` (a card for one session), `[sessions]` (every session in this directory), `[sessions:<term>]` (sessions matching a term), `[sessions:filter=<term>,limit=<n>]` (a filtered, capped list). A directive on a line with other text is rendered as ordinary text. Chips, callouts, cards, columns and buttons are available here too — full vocabulary: https://developer.jobmojito.com/cookbooks/format-content-with-markdown", "example": "## Sales coaching\n\nPick a session to practise with.\n\n[chip:6 sessions] [chip:Beginner,tone=accent]\n\n[sessions:filter=objection-handling,limit=6]\n", "type": [ "string", "null" ] }, "cover_image_url": { "description": "Cover image URL.", "type": [ "string", "null" ] }, "created_at": { "description": "Creation timestamp (ISO 8601).", "type": [ "string", "null" ] }, "description": { "description": "Short description shown on the directory card.", "type": [ "string", "null" ] }, "id": { "description": "Directory id — also the catalogue URL segment.", "example": "sales-coaching-en", "type": [ "string", "null" ] }, "is_start_directory": { "description": "True when this is the directory the merchant's catalogue opens on.", "type": [ "boolean", "null" ] }, "matched_sessions": { "description": "The coaching/persona sessions this directory currently lists, applying the same rules as the live portal: `active`, type `coaching` or `persona`, visibility `public` or `merchant_public` for this merchant, and `tags` containing every tag of `tags_interview_set_filter`. Empty when the filter is null. Capped at 200.", "items": { "additionalProperties": {}, "properties": { "id": { "description": "Interview definition id of the coaching/persona session.", "type": [ "string", "null" ] }, "name": { "description": "Session name.", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status (always `active` here — nothing else is listed).", "type": [ "string", "null" ] }, "tags": { "description": "The session's own tags — the superset that matched this directory's filter.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "type": { "description": "Product type — `coaching` or `persona`.", "type": [ "string", "null" ] }, "type_avatar": { "description": "Avatar/voice modality of the session.", "type": [ "string", "null" ] }, "type_credit": { "description": "Credit bucket the session draws from.", "type": [ "string", "null" ] }, "visibility": { "description": "Visibility.", "type": [ "string", "null" ] } }, "required": [ "id", "name", "type", "type_avatar", "status", "visibility", "type_credit", "tags" ], "type": "object" }, "type": [ "array", "null" ] }, "matched_sessions_truncated": { "description": "True when more sessions match than the 200 returned — narrow `tags_interview_set_filter` if you see this.", "type": [ "boolean", "null" ] }, "merchant_id": { "description": "Owning merchant id. Null for a platform-wide directory.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Directory language.", "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Display name.", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status.", "type": [ "string", "null" ] }, "sub_directories": { "description": "The directories listed in `tags_sub`, resolved and in display order. An id in `tags_sub` that does not resolve (deleted, or not visible to you) is simply absent here — compare the two to spot a broken link.", "items": { "additionalProperties": {}, "properties": { "description": { "description": "Short description.", "type": [ "string", "null" ] }, "id": { "description": "Sub-directory id.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Directory language.", "type": [ "string", "null" ] }, "name": { "description": "Display name.", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status.", "type": [ "string", "null" ] }, "visibility": { "description": "Visibility.", "type": [ "string", "null" ] } }, "required": [ "id", "name", "description", "status", "visibility", "mojito_language_code" ], "type": "object" }, "type": [ "array", "null" ] }, "tags_interview_set_filter": { "description": "Tag filter selecting which coaching sessions this directory lists: a session appears when its own `tags` contain EVERY tag here (an AND, not an OR). Only `active` coaching/persona sessions with visibility `public` or `merchant_public` are listed. Set the matching tags on the session with the create-interview / job-interview-update `tags` field.", "example": [ "sales", "objection-handling" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "tags_sub": { "description": "Ids of the directories nested under this one, in display order. Replaces the whole list — send the full set, not just the additions. A referenced directory only appears if it exists and is visible to the viewer.", "example": [ "sales-coaching-objections-en", "sales-coaching-closing-en" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "updated_at": { "description": "Last update timestamp (ISO 8601).", "type": [ "string", "null" ] }, "visibility": { "description": "Who can see it.", "type": [ "string", "null" ] } }, "required": [ "id", "name", "description", "mojito_language_code", "visibility", "status", "coach_plan", "cover_image_url", "merchant_id", "tags_sub", "tags_interview_set_filter", "content_md", "created_at", "updated_at", "catalogue_url", "is_start_directory", "sub_directories", "matched_sessions", "matched_sessions_truncated" ], "type": "object", "x-fastmcp-top-level-schema": "CatalogueTagGetResponse" } }, { "description": "Fetch the full content of a single JobMojito documentation page.\n\nAccepts a URL returned by `search_documentation`. For developer docs the\nclean Markdown (.md) variant is fetched automatically. Only\ndeveloper.jobmojito.com and help.jobmojito.com URLs are allowed.", "inputSchema": { "additionalProperties": false, "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "max_chars": { "default": 20000, "description": "Truncate content to this many characters (default 20000).", "type": "integer" }, "url": { "description": "The documentation page URL.", "type": "string" } }, "required": [ "url" ], "type": "object" }, "name": "get_documentation", "outputSchema": { "additionalProperties": true, "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" } }, "type": "object" } }, { "description": "[Interviews] Get the definition/configuration of an interview (position), including its ordered `questions` array. The questions come back in the same format create_interview_from_questions accepts, so you can read an interview here, change the array, and send it to update_interview. Each question's `id` identifies it — keep the ids you did not mean to change.\n\nRetrieves the interview definition for a given interview-definition id or position id. Returns the compiled `calc_definition_json`, the ordered `questions` array (in the same format job-interview-create-from-array accepts, so it round-trips into job-interview-update) plus basic metadata. Access is subject to the caller's row-level security.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "position_id": { "description": "Identifier of either an interview definition (single-stage) or a position definition (multi-stage). The function resolves whichever matches.", "example": "00000000-0000-0000-0000-000000000000", "format": "uuid", "minLength": 1, "type": "string" } }, "required": [ "position_id" ], "type": "object" }, "name": "get_interview_definition", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "calc_definition_json": { "description": "The compiled interview definition JSON (structure varies by interview type)." }, "candidate_expectations": { "description": "Free-text candidate expectations. Null for multi-stage positions.", "type": [ "string", "null" ] }, "candidate_expectations_json": { "description": "Structured candidate expectations JSON — the scoring rubric. Null for multi-stage positions." }, "candidate_notification_channel": { "description": "SMS / WhatsApp candidate notifications: null = off, reminders = with both e-mail reminders, last_reminder = only with the final reminder, all = invitation + reminders + pre-screening accepted.", "enum": [ "reminders", "last_reminder", "all", null ], "type": [ "string", "null" ] }, "candidate_video_introduction": { "description": "Whether a candidate video introduction is hidden/optional/required. Null for multi-stage positions.", "enum": [ "hidden", "optional", "required", null ], "type": [ "string", "null" ] }, "coach_plan": { "description": "Coaching-plan stage this session belongs to. Null for multi-stage positions and for sessions outside any plan.", "enum": [ "demo", "screening", "2nd", "3rd", "closing", "job-specific", "other", null ], "type": [ "string", "null" ] }, "code": { "description": "Caller-supplied external code/reference.", "type": [ "string", "null" ] }, "country_availability": { "description": "Portal availability by the candidate's country: {countries_allowed?: string[], countries_allowed_eu?: boolean, countries_blocked?: string[], countries_blocked_eu?: boolean} (ISO 3166-1 alpha-2, EU = EU + EEA + Switzerland; blocked wins), judged by the candidate's IP on the portal; invited candidates keep access. Null = not used, every country. Set it with job-interview-update." }, "cover_image_url": { "description": "Cover image URL.", "type": [ "string", "null" ] }, "created_at": { "example": "2026-01-15T09:30:00.000Z", "type": [ "string", "null" ] }, "creation_parameters": { "description": "The creation parameters recorded at build time (interview_type, interview_tone, interview_length, additional_context, include_rapport_question, include_closing_prompt, knowledge_base_store_id, seniority_level, hiring_for_company)." }, "description": { "description": "Short description.", "type": [ "string", "null" ] }, "environment": { "description": "Which webhook environment this interview's results are delivered to. Null for multi-stage positions, whose stages each carry their own.", "enum": [ "production", "uat", "development", "demo", null ], "example": "production", "type": [ "string", "null" ] }, "interview_available_till": { "description": "ISO date/time after which the interview is no longer available to candidates. Null means always available.", "type": [ "string", "null" ] }, "interview_conversation_speed": { "description": "Conversation pace of the AI avatar (slower/normal/faster). Null keeps the template default. Null for multi-stage positions.", "type": [ "string", "null" ] }, "interview_department": { "description": "Department the position belongs to.", "example": "Engineering", "type": [ "string", "null" ] }, "interview_description_long": { "description": "Long description (create/update field `description_long`). Rendered as Markdown on the candidate-facing position page — formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown", "type": [ "string", "null" ] }, "interview_location": { "description": "Location (create field `location`).", "type": [ "string", "null" ] }, "interview_salary": { "description": "Salary range shown for the position.", "example": "$80k - $100k", "type": [ "string", "null" ] }, "interview_template_id": { "description": "Interview template id. For multi-stage positions this is the first interview step's template.", "type": [ "string", "null" ] }, "interview_template_type": { "description": "Type of the linked interview template. `interactive_elevenlabs` is voice-only; the others (`interactive_spatius`, `interactive_heygen`, `offline_heygen`, `offline_elai`, `offline_synthesia`) are avatar-based. Null when the template could not be resolved.", "enum": [ "offline_elai", "offline_synthesia", "interactive_heygen", "offline_heygen", "interactive_elevenlabs", "interactive_spatius", null ], "type": [ "string", "null" ] }, "is_multistage": { "description": "True when the id resolved to a multi-stage position rather than a single interview.", "type": [ "boolean", "null" ] }, "is_voice_only": { "description": "Convenience flag derived from interview_template_type: true when voice-only (`interactive_elevenlabs`), false when avatar-based, null when the template type could not be resolved.", "type": [ "boolean", "null" ] }, "knowledge_base_store_id": { "description": "Linked knowledge base store id. Null for multi-stage positions.", "type": [ "string", "null" ] }, "max_duration": { "description": "Live session limit in seconds. Null for multi-stage positions.", "type": [ "number", "null" ] }, "max_followups": { "description": "Maximum number of AI follow-up questions; null uses the template default. Null for multi-stage positions.", "type": [ "number", "null" ] }, "merchant_id": { "description": "Owning merchant id.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform (mojito) language code.", "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Interview or position name.", "type": [ "string", "null" ] }, "pdf_export_auto_config": { "description": "Auto-PDF-report options applied when the interview completes; null when auto-export is off. Null for multi-stage positions." }, "questions": { "description": "The interview questions, in the order they are asked, in the same format job-interview-create-from-array accepts — so this array can be edited and sent straight back to job-interview-update, or used to create a copy of this interview. Each `id` is the question's real identifier: send it back unchanged and the question keeps its existing record (and with it its answer rules and any rendered avatar video). The welcome, thank-you and instructional-video steps are NOT included — they are not questions in this format, and job-interview-update leaves them untouched. Null for multi-stage positions, whose questions live on the individual interview stages.", "items": { "additionalProperties": {}, "properties": { "candidate_expectations_json": { "description": "Per-question candidate expectations, bucketed by requirement level (weak/moderate/strong). Extra keys are preserved.", "properties": { "moderate": { "description": "Requirements expected of a solid, competent candidate.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "strong": { "description": "High-bar requirements only standout candidates clear.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "weak": { "description": "Baseline requirements every viable candidate should meet (table stakes).", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "type": [ "object", "null" ] }, "conditional_question_main_id": { "description": "For a conditional question, the id (the \"id\" field above) of the parent question in this same array that triggers it. The parent must appear earlier in the array than the conditional question referencing it.", "type": [ "string", "null" ] }, "duration": { "description": "Answer duration in seconds for this question.", "type": [ "number", "null" ] }, "external_data": { "additionalProperties": {}, "description": "Arbitrary JSON metadata stored on the question.", "type": [ "object", "null" ] }, "external_id": { "description": "External identifier stored on the question. job-interview-update matches on this first, so an ATS that owns stable ids can send its own array and have the diff line up without round-tripping our ids.", "type": [ "string", "null" ] }, "id": { "description": "Identifier for this question. job-interview-get returns the question's real id here; send it back to job-interview-update so an unchanged question keeps its existing record (and with it its answer rules and any rendered avatar video). Also the handle another question references via conditional_question_main_id. On job-interview-create-from-array it is a caller-local value, only needed for those references.", "type": [ "string", "null" ] }, "is_candidate_asking_recruiter": { "description": "Candidate-asks-recruiter prompt (view 'candidate asking recruiter').", "type": [ "boolean", "null" ] }, "is_conditional": { "description": "Conditional follow-up question (view 'with listening conditional'). Use with conditional_question_main_id.", "type": [ "boolean", "null" ] }, "is_expert": { "description": "Expert listening question (view 'with listening expert').", "type": [ "boolean", "null" ] }, "is_multiple_choice": { "description": "Multiple-choice question (view 'multiple choice').", "type": [ "boolean", "null" ] }, "is_without_scoring": { "description": "Question is asked but not scored (view 'without scoring').", "type": [ "boolean", "null" ] }, "knowledge_base_id": { "description": "Knowledge-base store id (uuid) the question draws context from.", "type": [ "string", "null" ] }, "label": { "description": "Optional label/tag stored on the question.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Per-question language override (one of the platform-languages.json codes). Inherits the interview language when omitted.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "question": { "description": "The question text shown to the candidate.", "type": [ "string", "null" ] }, "question_alternatives": { "description": "Alternative phrasings for the question.", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "required": [ "question" ], "type": "object" }, "type": [ "array", "null" ] }, "questions_random_subset": { "description": "Fraction of the questions actually asked (0.01-0.9); null asks all of them. Null for multi-stage positions.", "type": [ "number", "null" ] }, "recording": { "description": "Per-answer recording mode. Null for multi-stage positions.", "enum": [ "audio_first_5_answers", "audio_all", "video_all", "video_first_5_answers", null ], "type": [ "string", "null" ] }, "recording_full_session": { "description": "Full-session recording mode. Null for multi-stage positions.", "enum": [ "audio_first_5_answers", "audio_all", "video_all", "video_first_5_answers", null ], "type": [ "string", "null" ] }, "recruiter_profile_id": { "description": "Profile id of the recruiter owning this interview/position.", "type": [ "string", "null" ] }, "required_pronunciation": { "description": "Whether a pronunciation assessment is required. Null for multi-stage positions.", "type": [ "boolean", "null" ] }, "result_enable_edit_transcript": { "description": "Whether the candidate may edit the transcript on the result view. Null for multi-stage positions.", "type": [ "boolean", "null" ] }, "result_scoring": { "description": "Resolved result-scoring config (update field `custom_scoring`; its `max_retries` is the update field `interview_attempts`). Null means the platform defaults apply. Null for multi-stage positions." }, "result_view": { "description": "Result view level. Null for multi-stage positions.", "enum": [ "minimal", "advanced", "full", "full_expand_scores", "minimal_with_score", "none", null ], "type": [ "string", "null" ] }, "slug": { "description": "URL slug of the public listing, when one was generated.", "type": [ "string", "null" ] }, "speech_language_code": { "description": "Azure speech language code. Null for multi-stage positions.", "type": [ "string", "null" ] }, "speech_language_name": { "description": "Azure speech language display name. Null for multi-stage positions.", "type": [ "string", "null" ] }, "stage": { "description": "Hiring-pipeline stage. Null for multi-stage positions.", "enum": [ "Interest", "Application submitted", "Interview 1st planned", "Interview 1st completed", "Interview 2nd planned", "Interview 2nd completed", "Interview 3rd planned", "Interview 3rd completed", "Offer negotiations", "Hired", "Rejected", "Offer declined", "Other", null ], "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status of the interview/position.", "enum": [ "draft", "active", "archived", "deleted", "preparing", "completed", null ], "type": [ "string", "null" ] }, "tags": { "description": "Free-form tags. Also the coaching-catalogue mapping key: a catalogue directory lists this session when its `tags_interview_set_filter` is a subset of these tags. Null for multi-stage positions.", "example": [ "interview-practice", "sales" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "type": { "description": "Interview type. Null for multi-stage positions.", "enum": [ "coaching", "interview", "persona", "persona_interview", "public_avatar", "assessment", null ], "type": [ "string", "null" ] }, "type_credit": { "description": "Credit bucket the interview draws from. Null for multi-stage positions.", "enum": [ "resume_check", "interview_coach_starter", "interview_coach_contributor", "interview_coach_manager", "cover_letter", null ], "type": [ "string", "null" ] }, "updated_at": { "example": "2026-01-20T14:05:00.000Z", "type": [ "string", "null" ] }, "visibility": { "description": "Who can see and access the interview/position.", "enum": [ "public", "merchant_public", "merchant_invite", "merchant_unlisted", "sub_item", null ], "type": [ "string", "null" ] } }, "required": [ "name", "created_at", "updated_at", "questions", "is_multistage", "status", "visibility", "stage", "type", "environment", "code", "interview_location", "cover_image_url", "merchant_id", "interview_template_id", "interview_template_type", "is_voice_only", "knowledge_base_store_id", "mojito_language_code", "speech_language_code", "speech_language_name", "recording", "recording_full_session", "type_credit", "result_view", "candidate_video_introduction", "description", "interview_description_long", "candidate_expectations", "interview_department", "interview_salary", "interview_available_till", "candidate_notification_channel", "recruiter_profile_id", "slug", "tags", "coach_plan", "interview_conversation_speed", "max_followups", "max_duration", "questions_random_subset", "required_pronunciation", "result_enable_edit_transcript" ], "type": "object", "x-fastmcp-top-level-schema": "JobInterviewGetResponse" } }, { "description": "[Results] Get full interview result details including transcript and scores. Scores are assistive output for a human reviewer. One result is a large record, so `view` controls how much of it comes back — the default (`standard`) omits only the raw machine assessment data.\n\nReturns an interview result with its full transcript and AI assessment. Optionally attaches signed recording URLs.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "get_signed_recordings": { "default": "false", "description": "When true, includes short-lived signed recording URLs for the session, the video introduction, and each transcript answer.", "enum": [ "true", "false" ], "example": "false", "type": "string" }, "interview_result_id": { "description": "The interview result to fetch the transcript and details for.", "example": "93c98d21-e04d-4a84-9afa-ed154cf73636", "format": "uuid", "minLength": 1, "type": "string" }, "view": { "default": "standard", "description": "How much of the record to return. Handled by the MCP server, not the JobMojito API — it only narrows the response, never the query.\n\n- `summary`: scores, the overall AI analysis, and each question with the candidate's answer — no per-answer AI commentary, recording paths or raw assessment data. Use this to review or compare candidates.\n- `standard`: everything a human reviewer reads: the full transcript with per-answer analysis, scores and recordings, minus the raw machine assessment blobs. This is the default.\n- `full`: every field, including the per-answer raw assessment data — condensed: pronunciation and sentiment scores per recognised segment with the lowest-scoring words, reading/gaze statistics, STT reliability, proctor status and seconds per detected speaker. Word-, character- and frame-level arrays are left out (listed in `_omitted`). Only ask for this if you need those assessment details.", "enum": [ "summary", "standard", "full" ], "type": "string" } }, "required": [ "interview_result_id" ], "type": "object" }, "name": "get_interview_result_details", "outputSchema": { "additionalProperties": {}, "description": "The interview result with its transcript, produced by the interview_transcript RPC. Additional fields may be present (passthrough).", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "ai_analysis": { "description": "Candidate-facing AI analysis of the whole interview.", "type": [ "string", "null" ] }, "ai_analysis_other": { "description": "Session-level AI analyses keyed by analysis name (jsonb). `strengths_concerns`: { strengths: string[], concerns: string[] } (0-4 items each, recruiter-facing; called `hiring_reasons` with `reasons_to_hire` / `reasons_not_to_hire` inside before 2026-09-15, and rows written before then may still carry that shape). `takeaways`: { what_went_well: string[], next_steps: { text, priority: impact | quick | longterm, guidance: { kind: say | structure | length | exercise | perspective, text }, proof? }[], fixed?: string[] } (coaching / persona sessions, learner-facing; `proof` entries are { kind: quote | ai_summary | transcript_ref | document, text, ref?: { result_question_id } }; `fixed` lists the steps from the previous attempt that the learner did this time). `multi_department`: the multi-department-selection analysis. `score_rationale`: the rubric bracket of the session score and evidenced counts. `key_statement`: { quote, result_question_id }, the one verbatim quotation a recruiter would remember the candidate by (interview / persona_interview, absent when nothing distinctive was said). Further keys may be added." }, "ai_analysis_recruiter": { "description": "Recruiter-facing AI analysis of the whole interview.", "type": [ "string", "null" ] }, "ai_analysis_recruiter_why_hire": { "description": "Reasons to hire (list). Deprecated: a copy of ai_analysis_other.strengths_concerns.strengths, kept for existing integrations." }, "ai_analysis_recruiter_why_not_hire": { "description": "Reasons not to hire (list). Deprecated: a copy of ai_analysis_other.strengths_concerns.concerns, kept for existing integrations." }, "ai_completion_reason": { "description": "Why the interview completed (ai_completed_reason).", "type": [ "string", "null" ] }, "ai_interview_coverage_percentage": { "description": "Percentage of the intended interview the AI judged to be covered.", "type": [ "number", "null" ] }, "duration": { "description": "Total duration in deciseconds (duration_ds).", "type": [ "number", "null" ] }, "end": { "description": "Interview end timestamp (training_end, ISO 8601).", "type": [ "string", "null" ] }, "recording_is_video": { "description": "Whether the session recording is video.", "type": [ "boolean", "null" ] }, "recording_local_path": { "description": "Storage path of the full session recording.", "type": [ "string", "null" ] }, "recording_url": { "description": "Signed session-recording URL; present only when get_signed_recordings=true.", "type": [ "string", "null" ] }, "recruiter_risks": { "description": "Detected recruiter risk flags (jsonb)." }, "score": { "description": "Overall interview score.", "type": [ "number", "null" ] }, "score_answer": { "description": "Aggregate answer sub-score.", "type": [ "number", "null" ] }, "score_pronunciation": { "description": "Pronunciation sub-score.", "type": [ "number", "null" ] }, "score_sentiment": { "description": "Sentiment sub-score.", "type": [ "number", "null" ] }, "score_simulation": { "description": "Overall simulated score.", "type": [ "number", "null" ] }, "score_text": { "description": "Human-readable score summary.", "type": [ "string", "null" ] }, "score_words_per_minute": { "description": "Speaking-pace (words per minute) sub-score.", "type": [ "number", "null" ] }, "start": { "description": "Interview start timestamp (training_start, ISO 8601).", "type": [ "string", "null" ] }, "status": { "description": "Coach/interview status (coach_status), e.g. started, completed.", "type": [ "string", "null" ] }, "transcript": { "description": "Ordered interactions (questions + answers) of the interview.", "items": { "additionalProperties": {}, "properties": { "ai_analysis": { "description": "AI analysis of this answer.", "type": [ "string", "null" ] }, "ai_analysis_recruiter": { "description": "Recruiter-facing AI analysis of this answer.", "type": [ "string", "null" ] }, "answer": { "description": "The candidate answer transcript text.", "type": [ "string", "null" ] }, "answer_assessment_raw_data": { "description": "Raw per-answer assessment data (pronunciation/sentiment/etc.)." }, "duration": { "description": "Duration of this interaction in deciseconds (duration_ds).", "type": [ "number", "null" ] }, "external_data": { "description": "External data carried from the question definition." }, "external_id": { "description": "External identifier carried from the question definition.", "type": [ "string", "null" ] }, "id": { "description": "interview_result_question id.", "type": [ "string", "null" ] }, "is_answer": { "description": "True for a candidate answer turn, false for an avatar/question turn.", "type": [ "boolean", "null" ] }, "mojito_language_code": { "description": "Platform language code of this interaction.", "type": [ "string", "null" ] }, "question_asked": { "description": "The question text actually asked to the candidate.", "type": [ "string", "null" ] }, "question_original": { "description": "Original question text from the definition (when question_original_id is set).", "type": [ "string", "null" ] }, "question_original_id": { "description": "Source interview_def_question id (null for generated follow-ups).", "type": [ "string", "null" ] }, "recording_is_video": { "description": "Whether this answer recording is video (vs audio).", "type": [ "boolean", "null" ] }, "recording_local_path": { "description": "Storage path of this answer recording (private-recordings bucket).", "type": [ "string", "null" ] }, "recording_url": { "description": "Signed URL for recording_local_path; present only when get_signed_recordings=true.", "type": [ "string", "null" ] }, "score": { "description": "Score for this interaction.", "type": [ "number", "null" ] }, "score_answer_ai": { "description": "AI answer score.", "type": [ "number", "null" ] }, "score_answer_ai_simulation": { "description": "Simulated AI answer score.", "type": [ "number", "null" ] }, "score_simulation": { "description": "Simulated score for this interaction.", "type": [ "number", "null" ] }, "view": { "description": "Question view/type (e.g. with listening, multiple choice, without scoring).", "type": [ "string", "null" ] } }, "type": "object" }, "type": [ "array", "null" ] }, "user_feedback_recruiter": { "description": "Recruiter-entered feedback note.", "type": [ "string", "null" ] }, "video_introduction_local_path": { "description": "Storage path of the candidate video introduction.", "type": [ "string", "null" ] }, "video_introduction_url": { "description": "Signed video-introduction URL; present only when get_signed_recordings=true.", "type": [ "string", "null" ] } }, "type": "object", "x-fastmcp-top-level-schema": "JobInterviewDetailsResponse" } }, { "description": "[Results] Get the merchant's daily event analytics.\n\nDaily event-count time-series for a merchant over a date range (the admin-portal analytics events graph), scoped to your token's merchant (or a merchant_id override). Optionally drilled to a single interview. Capped at 1000 records per page. Note: only day/event combinations with a non-zero count are returned — any day/event pair absent from the response should be treated as a count of 0 by the caller.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "date_from": { "description": "Start of the date range (inclusive), YYYY-MM-DD.", "example": "2026-01-01", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" }, "date_to": { "description": "End of the date range (inclusive), YYYY-MM-DD.", "example": "2026-01-01", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" }, "interview_id": { "description": "Optional interview (interview_def_set) or position (position_def_set) id to drill the event counts down. The type is detected automatically: a position aggregates the daily counts across every interview that makes up the position; an interview filters to that single definition.", "format": "uuid", "type": "string" }, "limit": { "default": 50, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" } }, "required": [ "date_from", "date_to" ], "type": "object" }, "name": "get_merchant_analytics", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "Daily event counts for the requested range, ordered by day ascending. Only day/event combinations with a non-zero count are returned; missing combinations should be treated as 0 by the caller.", "items": { "additionalProperties": {}, "properties": { "day": { "description": "Calendar day (YYYY-MM-DD).", "example": "2026-01-15", "type": [ "string", "null" ] }, "event": { "description": "Event type (e.g. interview, interview_invitation, interview_page_visit).", "type": [ "string", "null" ] }, "event_number": { "description": "Count of this event on this day. Always greater than 0 — zero-count day/event combinations are omitted.", "example": 12, "type": [ "number", "null" ] } }, "required": [ "day", "event", "event_number" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantAnalyticsResponse" } }, { "description": "[Results] Get the merchant's credit usage.\n\nPer-event credit-usage ledger for a merchant: every billable analytics event (interview, pre-screening, public avatar, simulation, …) that consumed credits, ordered most recent first. Scoped to your token's merchant, or a merchant_id override for admins / sub-merchant operators. The credits consumed by each event are in stats.credit_amount. Capped at 1000 records per page.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "interview_id": { "description": "Optional interview (interview_def_set) or position (position_def_set) id to drill the credit-usage ledger down to a single interview or position. The type is detected automatically: for a position the response combines pre-screening and interview-result credits across the whole position; for an interview it returns that interview's credit events (including simulations and report translations).", "format": "uuid", "type": "string" }, "limit": { "default": 50, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" } }, "required": [], "type": "object" }, "name": "get_merchant_credit_usage", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "Credit-consuming analytics events for the merchant, most recent first. Each row is one billable event; the credits it consumed are in stats.credit_amount.", "items": { "additionalProperties": {}, "properties": { "candidate_name": { "description": "Candidate display name from the linked profile interview, when available.", "type": [ "string", "null" ] }, "credit_amount": { "description": "Number of credits deducted by this event, surfaced from stats.credit_amount for convenience. Null when the amount is absent.", "example": 1, "type": [ "number", "null" ] }, "event": { "description": "Billable event type that consumed the credit (e.g. interview, interview_reviewing, interview_failed, interview_incomplete, pre_screening, candidate_report_translation, candidate_kyc, public_avatar, interview_simulation).", "example": "interview", "type": [ "string", "null" ] }, "event_date": { "description": "When the credit-consuming event occurred (ISO 8601).", "example": "2026-01-15T09:30:00.000Z", "type": [ "string", "null" ] }, "id": { "description": "Analytics event id.", "format": "uuid", "type": [ "string", "null" ] }, "object_uuid": { "description": "Primary object the event refers to (e.g. the interview result / attempt).", "format": "uuid", "type": [ "string", "null" ] }, "parent_object_uuid": { "description": "Parent object of the event (e.g. the interview definition), when applicable.", "format": "uuid", "type": [ "string", "null" ] }, "profile_id": { "description": "Underlying person (profile) id, when linked.", "format": "uuid", "type": [ "string", "null" ] }, "profile_interview_id": { "description": "Candidate enrolment (profile interview) id, when linked.", "format": "uuid", "type": [ "string", "null" ] }, "stats": { "description": "Event stats JSON. Contains credit_amount (the credits consumed by this event) plus event-specific fields." } }, "required": [ "id", "event_date", "event", "credit_amount", "candidate_name", "profile_id", "profile_interview_id", "object_uuid", "parent_object_uuid" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantCreditsUsedResponse" } }, { "description": "[Admin] Get a merchant status snapshot: credit balances, subscription, pending-work counts, candidate/result totals, and invitation headroom.\n\nStatus snapshot for a merchant: interview-credit balances, subscription type/status, pending-work counts (undecided / ongoing / uncredited interviews), candidate & result totals with 14-day history, and invitation headroom. Scoped to your token's merchant (or a merchant_id override for admins / sub-merchant operators). Also echoes the caller's profile_id and default_merchant_id from the token, plus the effective merchant_id.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" } }, "required": [], "type": "object" }, "name": "get_merchant_status", "outputSchema": { "additionalProperties": {}, "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "candidates": { "description": "Total candidates (non-archived profile_interview rows) for the merchant.", "example": 212, "type": [ "number", "null" ] }, "candidates_history": { "description": "Daily new-candidate counts for the last 14 days, most recent first.", "example": [ 3, 5, 0, 2, 8, 1, 0, 4, 6, 2, 1, 0, 3, 5 ], "items": { "type": "number" }, "type": [ "array", "null" ] }, "credits_interview_extra": { "description": "Extra (top-up) interview credits available on top of the monthly allowance.", "example": 25, "type": [ "number", "null" ] }, "credits_interview_monthly": { "description": "Remaining monthly interview credits.", "example": 8, "type": [ "number", "null" ] }, "credits_interview_monthly_limit": { "description": "Monthly interview-credit allowance for the current plan.", "example": 10, "type": [ "number", "null" ] }, "credits_interview_single": { "description": "Single-position interview credits available.", "example": 0, "type": [ "number", "null" ] }, "default_merchant_id": { "description": "The caller's home merchant id pinned in the JWT (app_metadata.merchant_id). Null if the token carries no merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "type": [ "string", "null" ] }, "definitions_active": { "description": "Count of active interview + position definitions.", "example": 4, "type": [ "number", "null" ] }, "interview_result_history": { "description": "Daily new-interview-result counts for the last 14 days, most recent first.", "example": [ 1, 2, 0, 1, 3, 0, 0, 2, 1, 1, 0, 0, 1, 2 ], "items": { "type": "number" }, "type": [ "array", "null" ] }, "interview_results": { "description": "Total non-archived interview results for the merchant.", "example": 137, "type": [ "number", "null" ] }, "interviews_ongoing": { "description": "Interviews currently in progress (coach_status = started).", "example": 1, "type": [ "number", "null" ] }, "interviews_undecided": { "description": "Completed interviews awaiting a recruiter decision.", "example": 3, "type": [ "number", "null" ] }, "interviews_without_credits": { "description": "Completed interviews that have not yet consumed a credit.", "example": 2, "type": [ "number", "null" ] }, "invitations_available": { "description": "Remaining invitations this period. Null for unlimited (Special) plans.", "example": 22, "type": [ "number", "null" ] }, "invitations_limit": { "description": "Maximum invitations allowed this period (4x available credits). Null for unlimited (Special) plans.", "example": 40, "type": [ "number", "null" ] }, "invitations_sent": { "description": "Interview invitations sent during the current subscription period.", "example": 18, "type": [ "number", "null" ] }, "merchant_id": { "description": "The merchant this status is scoped to — the default_merchant_id unless an admin / sub-merchant operator overrode it via the merchant_id query param.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "type": [ "string", "null" ] }, "profile_id": { "description": "The calling user's profile id (auth user id), taken from the JWT.", "example": "9b2c1e54-7a3d-4f8e-9c10-2b6a4d5e7f01", "type": [ "string", "null" ] }, "subscription_status": { "description": "Subscription status (e.g. active, past_due, canceled). Null when no subscription.", "example": "active", "type": [ "string", "null" ] }, "subscription_type": { "description": "Subscription plan name (e.g. Free, Starter, Growth, Special).", "example": "Growth", "type": [ "string", "null" ] } }, "required": [ "profile_id", "default_merchant_id", "merchant_id", "credits_interview_monthly", "credits_interview_monthly_limit", "credits_interview_extra", "credits_interview_single", "definitions_active", "interviews_without_credits", "interviews_undecided", "interviews_ongoing", "interview_results", "candidates", "candidates_history", "interview_result_history", "subscription_type", "subscription_status", "invitations_sent", "invitations_limit", "invitations_available" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantStatus" } }, { "description": "Show the interactive JobMojito merchant picker (UI).\n\nALWAYS call this when the user wants to choose, switch, or set a\nmerchant, or when a tool needs a `merchant_id` and none is selected.\nIt renders a searchable picker with clickable options. Do NOT list\nmerchants as text or ask the user to type a name — render this\npicker instead. After calling it, STOP and wait for the user's\nselection; then pass `merchant_id=<chosen id>` on every JobMojito\ncall (omit it for the user's own account).", "inputSchema": { "additionalProperties": false, "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" } }, "type": "object" }, "name": "jobmojito_configuration", "outputSchema": null }, { "description": "[Admin] List available avatar/voice templates. Each item's `type` decides the interview modality: `interactive_elevenlabs` = voice-only (no video avatar); `interactive_spatius` = realtime interactive 3D avatar (rendered in the candidate's browser, 1.25 credits, no early stop); `interactive_heygen` = premium realtime interactive video avatar; `offline_heygen` = pre-recorded, non-interactive avatar. An item's `id` is the `interview_template_id` you pass to the create-interview tools, so pick the template whose type matches the experience you want. Note: `offline_elai` and `offline_synthesia` are legacy integrations that may still appear here but cannot be used to create new interviews. Rows are large, so this returns 15 at a time; page with `offset` while `pagination.has_more` is true, or narrow with `type`/`filter_text`.\n\nPaginated list of a merchant's avatar templates (the admin-portal avatars list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "filter_text": { "description": "Case-insensitive search on template name or voice language name.", "type": "string" }, "include_archived": { "default": "false", "description": "Include archived templates (excluded by default).", "enum": [ "true", "false" ], "example": "false", "type": "string" }, "include_public": { "default": "false", "description": "Also include public templates shared across merchants, in addition to this merchant's own.", "enum": [ "true", "false" ], "example": "false", "type": "string" }, "limit": { "default": 15, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "mojito_language_code": { "description": "Filter by platform language code. Omit for all languages.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi" ], "example": "en", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" }, "status": { "description": "Filter by status. Omit for all except archived (see include_archived).", "enum": [ "active", "draft", "archived", "deleted" ], "example": "active", "type": "string" }, "type": { "description": "Filter by avatar template type. Omit for all.", "enum": [ "interactive_heygen", "interactive_elevenlabs", "interactive_spatius", "offline_heygen", "offline_elai", "offline_synthesia" ], "example": "interactive_heygen", "type": "string" } }, "required": [], "type": "object" }, "name": "list_avatars", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "The merchant's avatar templates for this page, newest-updated first.", "items": { "additionalProperties": {}, "properties": { "background_blur": { "description": "Background blur intensity (0–1); higher is blurrier.", "type": [ "number", "null" ] }, "background_url": { "description": "Background image URL.", "type": [ "string", "null" ] }, "created_at": { "description": "Creation timestamp (ISO 8601).", "type": [ "string", "null" ] }, "id": { "description": "Avatar template id.", "type": [ "string", "null" ] }, "media_url": { "description": "Avatar media URL.", "type": [ "string", "null" ] }, "merchant_id": { "description": "Owning merchant id.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform language code.", "type": [ "string", "null" ] }, "name": { "description": "Template name.", "type": [ "string", "null" ] }, "status": { "description": "Status (active/draft/archived/deleted).", "type": [ "string", "null" ] }, "type": { "description": "Avatar template type.", "type": [ "string", "null" ] }, "updated_at": { "description": "Last update timestamp (ISO 8601).", "type": [ "string", "null" ] }, "video_avatar_aspect_ratio": { "description": "Avatar aspect ratio.", "type": [ "string", "null" ] }, "video_avatar_image_url": { "description": "Avatar still-image URL.", "type": [ "string", "null" ] }, "video_background_remove": { "description": "Whether the video background is removed.", "type": [ "boolean", "null" ] }, "video_voice_language_name": { "description": "Voice language display name.", "type": [ "string", "null" ] }, "visibility": { "description": "Visibility (public/merchant_…).", "type": [ "string", "null" ] } }, "required": [ "id" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantAvatarListResponse" } }, { "description": "[Candidates] List the merchant's candidates.\n\nPaginated list of a merchant's candidates (the admin-portal candidates list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "filter_emoji": { "description": "Filter by the candidate emoji marker.", "type": "string" }, "filter_text": { "description": "Search on candidate name, email, external id, phone and CV skills. Every word must match (case and accents ignored; longer words tolerate typos). Without order_by, the best matches come first.", "type": "string" }, "limit": { "default": 50, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" }, "order_by": { "default": "created_at_newest", "description": "Sort order of the result set.", "enum": [ "name_accending", "name_decending", "created_at_newest", "created_at_oldest" ], "example": "created_at_newest", "type": "string" }, "source": { "description": "Filter by how the candidate entered: invited or self-registered. Omit for both.", "enum": [ "invited", "registered" ], "example": "registered", "type": "string" }, "tab": { "description": "Filter candidates by recent activity. Omit (or empty) to include all.", "enum": [ "interview", "pre-screening", "no-action", "leads", "" ], "example": "interview", "type": "string" } }, "required": [], "type": "object" }, "name": "list_candidates", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "The merchant's candidates for this page.", "items": { "additionalProperties": {}, "properties": { "avatar_local_path": { "description": "Avatar storage path.", "type": [ "string", "null" ] }, "avatar_url": { "description": "Avatar image URL.", "type": [ "string", "null" ] }, "created_at": { "description": "Creation timestamp (ISO 8601).", "type": [ "string", "null" ] }, "deleted_at": { "description": "Deletion timestamp (ISO 8601), if deleted.", "type": [ "string", "null" ] }, "email": { "description": "Candidate email.", "type": [ "string", "null" ] }, "email_auth": { "description": "Auth email (login).", "type": [ "string", "null" ] }, "emoji": { "description": "Emoji marker.", "type": [ "string", "null" ] }, "external_id": { "description": "External identifier.", "type": [ "string", "null" ] }, "id": { "description": "Candidate (profile_interview) id.", "type": [ "string", "null" ] }, "interview_count": { "description": "Number of interviews taken.", "type": [ "number", "null" ] }, "interview_last": { "description": "Most recent interview timestamp (ISO 8601).", "type": [ "string", "null" ] }, "kyc_image_local_path": { "description": "KYC image storage path.", "type": [ "string", "null" ] }, "kyc_processing_status": { "description": "KYC processing status.", "type": [ "string", "null" ] }, "last_login_at": { "description": "Last login timestamp (ISO 8601).", "type": [ "string", "null" ] }, "linked_in": { "description": "LinkedIn URL.", "type": [ "string", "null" ] }, "merchant_id": { "description": "Owning merchant id.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform language code.", "type": [ "string", "null" ] }, "name": { "description": "Candidate name.", "type": [ "string", "null" ] }, "phone_number": { "description": "Phone number.", "type": [ "string", "null" ] }, "physical_address": { "description": "Physical address.", "type": [ "string", "null" ] }, "pre_screening_count": { "description": "Number of pre-screenings taken.", "type": [ "number", "null" ] }, "profile_id": { "description": "Underlying profile id.", "type": [ "string", "null" ] }, "public_avatar_count": { "description": "Number of public-avatar conversations.", "type": [ "number", "null" ] }, "skills": { "description": "Skills read from the candidate's latest CV; null until extracted.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "status": { "description": "Status (active/invited/deleted).", "type": [ "string", "null" ] }, "updated_at": { "description": "Last update timestamp (ISO 8601).", "type": [ "string", "null" ] } }, "required": [ "id" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantCandidateListResponse" } }, { "description": "[Coaching catalogue] List the coaching-catalogue directories you can see (your merchant's own plus the platform-wide public ones). Start here to find a directory id, to pick a parent for a new one, or to walk the tree with `parent_tag`; `is_start_directory` marks the page the catalogue opens on. The custom Markdown page is not included — read it with get_catalogue_directory. Returns 25 at a time; page with `offset` while `pagination.has_more` is true.\n\nPaginated list of the coaching-catalogue directories visible to you: your merchant's own, plus the platform-wide `public` ones unless you set include_public=false. Use it to find a directory id before updating one, to pick a `parent_tag`, or to walk the tree with `parent_tag`. The custom Markdown page is not included — fetch it per directory with catalogue-tag-get.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "filter_text": { "description": "Case-insensitive search on the directory id, name and description.", "type": "string" }, "include_public": { "default": "true", "description": "Include the platform-wide `public` directories shared across merchants.", "enum": [ "true", "false" ], "example": "true", "type": "string" }, "limit": { "default": 25, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "mojito_language_code": { "description": "Filter by the directory language. Omit for all languages.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi" ], "example": "en", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" }, "parent_tag": { "description": "Return only the directories nested directly under this one (its `tags_sub`), in the parent's own order. Combine with the other filters to narrow further.", "type": "string" }, "status": { "description": "Filter by lifecycle status. Omit to include every status you can see (deleted directories are never returned).", "enum": [ "draft", "active", "archived" ], "example": "active", "type": "string" }, "visibility": { "description": "Filter by visibility.", "enum": [ "public", "merchant_public", "merchant_invite", "merchant_unlisted" ], "example": "merchant_public", "type": "string" } }, "required": [], "type": "object" }, "name": "list_catalogue_directories", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "The catalogue directories for this page, ordered by id.", "items": { "additionalProperties": {}, "properties": { "coach_plan": { "description": "Coaching-plan stage, when the directory belongs to one.", "type": [ "string", "null" ] }, "cover_image_url": { "description": "Cover image URL.", "type": [ "string", "null" ] }, "created_at": { "description": "Creation timestamp (ISO 8601).", "type": [ "string", "null" ] }, "description": { "description": "Short description shown on the directory card.", "type": [ "string", "null" ] }, "has_content_page": { "description": "True when the directory has a custom Markdown page. Read the Markdown itself with catalogue-tag-get.", "type": [ "boolean", "null" ] }, "id": { "description": "Directory id — also the catalogue URL segment and the value referenced in a parent's `tags_sub`.", "example": "sales-coaching-en", "type": [ "string", "null" ] }, "is_start_directory": { "description": "True for the directory the merchant's catalogue opens on — the root to navigate down from.", "type": [ "boolean", "null" ] }, "merchant_id": { "description": "Owning merchant id. Null for a platform-wide directory.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Directory language.", "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Display name.", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status (draft/active/archived).", "type": [ "string", "null" ] }, "tags_interview_set_filter": { "description": "Tag filter selecting the coaching sessions this directory lists: a session appears when its own `tags` contain every tag here.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "tags_sub": { "description": "Ids of the directories nested under this one, in display order.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "updated_at": { "description": "Last update timestamp (ISO 8601).", "type": [ "string", "null" ] }, "visibility": { "description": "Who can see it (public/merchant_public/merchant_invite/merchant_unlisted).", "type": [ "string", "null" ] } }, "required": [ "id", "has_content_page", "is_start_directory" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "CatalogueTagListResponse" } }, { "description": "[Results] List the merchant's interview results. Rows carry the candidate's scores and recruiter risk flags, so this returns 20 at a time; page with `offset` while `pagination.has_more` is true, or narrow with `tab`/`interview_id`/`filter_text`.\n\nPaginated list of a merchant's interview results (the admin-portal results list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "filter_emoji": { "description": "Filter by the candidate emoji marker.", "type": "string" }, "filter_text": { "description": "Case-insensitive search on candidate name or email.", "type": "string" }, "interview_id": { "description": "Filter to a single interview definition id.", "format": "uuid", "type": "string" }, "limit": { "default": 20, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" }, "order_by": { "default": "created_at_newest", "description": "Sort order of the result set.", "enum": [ "score", "created_at_newest", "created_at_oldest", "updated_at_newest" ], "example": "created_at_newest", "type": "string" }, "profile_interview_id": { "description": "Filter to a single candidate (profile_interview) id.", "format": "uuid", "type": "string" }, "risks": { "description": "Comma-separated list of recruiter-risk keys to filter by (matches any).", "type": "string" }, "step": { "description": "Filter by pipeline step type (pre-screening, interview or meeting). Omit for all.", "enum": [ "pre-screening", "interview", "meeting" ], "example": "interview", "type": "string" }, "tab": { "description": "Filter by decision/completion state. Omit (or empty) to include all.", "enum": [ "decided-rejected", "undecided", "shortlist", "decided-selected", "completed", "incomplete", "archived-interview", "public_avatar", "archived-public_avatar", "" ], "example": "undecided", "type": "string" }, "type": { "default": "interview", "description": "Product type of results to list.", "enum": [ "interview", "coaching", "assessment", "public_avatar", "persona", "persona_interview" ], "example": "interview", "type": "string" } }, "required": [], "type": "object" }, "name": "list_interview_results", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "The merchant's interview results for this page.", "items": { "additionalProperties": {}, "properties": { "candidate_email": { "description": "Candidate email.", "type": [ "string", "null" ] }, "candidate_name": { "description": "Candidate name.", "type": [ "string", "null" ] }, "coach_status": { "description": "Interview/coach status (started/completed/…).", "type": [ "string", "null" ] }, "created_at": { "description": "Creation timestamp (ISO 8601).", "type": [ "string", "null" ] }, "decision_status": { "description": "Hiring decision (selected/rejected/…).", "type": [ "string", "null" ] }, "definition_id": { "description": "Interview definition id.", "type": [ "string", "null" ] }, "duration_ds": { "description": "Duration in deciseconds.", "type": [ "number", "null" ] }, "emoji": { "description": "Emoji marker.", "type": [ "string", "null" ] }, "external_id": { "description": "External identifier.", "type": [ "string", "null" ] }, "id": { "description": "Position result row id.", "type": [ "string", "null" ] }, "interview_result_id": { "description": "Interview result id (use with merchant-... detail endpoints).", "type": [ "string", "null" ] }, "interview_result_pre_screening_id": { "description": "Pre-screening result id, if any.", "type": [ "string", "null" ] }, "interview_started": { "description": "Whether the interview was started.", "type": [ "boolean", "null" ] }, "is_multi_stage": { "description": "Whether multi-stage.", "type": [ "boolean", "null" ] }, "is_test": { "description": "Whether a test result.", "type": [ "boolean", "null" ] }, "kyc_processing_status": { "description": "KYC processing status.", "type": [ "string", "null" ] }, "merchant_id": { "description": "Owning merchant id.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform language code.", "type": [ "string", "null" ] }, "position_def_step_id": { "description": "Position step definition id the row belongs to (null for single-stage interviews).", "type": [ "string", "null" ] }, "position_name": { "description": "Position / interview name.", "type": [ "string", "null" ] }, "position_result_step_id": { "description": "Position result step id.", "type": [ "string", "null" ] }, "position_step": { "description": "Pipeline step.", "type": [ "string", "null" ] }, "position_step_count": { "description": "Number of steps in the position process.", "type": [ "number", "null" ] }, "position_step_index": { "description": "1-based position of the step in the position process.", "type": [ "number", "null" ] }, "position_step_name": { "description": "Custom name of the position step, null when the step uses its default label.", "type": [ "string", "null" ] }, "processing_error": { "description": "Processing error, if any.", "type": [ "string", "null" ] }, "processing_status": { "description": "Processing status.", "type": [ "string", "null" ] }, "profile_id": { "description": "Candidate profile id.", "type": [ "string", "null" ] }, "profile_interview_id": { "description": "Candidate (profile_interview) id.", "type": [ "string", "null" ] }, "recruiter_risks": { "description": "Detected recruiter risk flags (jsonb)." }, "recruiter_shortlist": { "description": "Whether recruiter-shortlisted.", "type": [ "boolean", "null" ] }, "score": { "description": "Overall score.", "type": [ "number", "null" ] }, "score_answer_ai": { "description": "AI answer sub-score.", "type": [ "number", "null" ] }, "score_interview_ai": { "description": "AI interview sub-score.", "type": [ "number", "null" ] }, "score_pronunciation": { "description": "Pronunciation sub-score.", "type": [ "number", "null" ] }, "score_sentiment": { "description": "Sentiment sub-score.", "type": [ "number", "null" ] }, "score_simulation": { "description": "Simulated overall score.", "type": [ "number", "null" ] }, "score_words_per_minute": { "description": "Speaking-pace sub-score.", "type": [ "number", "null" ] }, "status": { "description": "Row status.", "type": [ "string", "null" ] }, "type": { "description": "Product type.", "type": [ "string", "null" ] }, "updated_at": { "description": "Last update timestamp (ISO 8601).", "type": [ "string", "null" ] } }, "required": [ "id" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantResultListResponse" } }, { "description": "[Interviews] List the merchant's interview definitions.\n\nPaginated list of a merchant's interview definitions (the admin-portal interview list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "filter_emoji": { "description": "Filter by the interview emoji marker.", "type": "string" }, "filter_text": { "description": "Case-insensitive search on the interview name.", "type": "string" }, "limit": { "default": 50, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" }, "show_demo": { "default": "false", "description": "Include demo/sample interviews.", "enum": [ "true", "false" ], "example": "false", "type": "string" }, "show_public": { "default": "false", "description": "Include interviews shared publicly across merchants (coaching/avatars).", "enum": [ "true", "false" ], "example": "false", "type": "string" }, "status": { "description": "Filter by lifecycle status. Omit to include all statuses.", "enum": [ "draft", "active", "archived", "deleted", "preparing", "completed" ], "example": "active", "type": "string" }, "type": { "default": "interview", "description": "Product type of interviews to list.", "enum": [ "interview", "coaching", "assessment", "public_avatar", "persona", "persona_interview" ], "example": "interview", "type": "string" } }, "required": [], "type": "object" }, "name": "list_interviews", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "The merchant's interview definitions for this page, newest-updated first.", "items": { "additionalProperties": {}, "properties": { "billing_single_position": { "description": "Single-position billing flag.", "type": [ "boolean", "null" ] }, "billing_single_position_end_at": { "description": "Single-position billing end (ISO 8601).", "type": [ "string", "null" ] }, "calc_duration": { "description": "Calculated duration.", "type": [ "number", "null" ] }, "cover_image_url": { "description": "Cover image URL.", "type": [ "string", "null" ] }, "created_at": { "description": "Creation timestamp (ISO 8601).", "type": [ "string", "null" ] }, "emoji": { "description": "Emoji marker.", "type": [ "string", "null" ] }, "environment": { "description": "Environment (production/test/…).", "type": [ "string", "null" ] }, "id": { "description": "Interview definition id.", "type": [ "string", "null" ] }, "interview_count": { "description": "Number of interviews run against this definition.", "type": [ "number", "null" ] }, "interview_last": { "description": "Timestamp of the most recent interview (ISO 8601).", "type": [ "string", "null" ] }, "is_ats": { "description": "Whether the interview is ATS-integrated.", "type": [ "boolean", "null" ] }, "is_multi_stage": { "description": "Whether the interview is multi-stage.", "type": [ "boolean", "null" ] }, "merchant_id": { "description": "Owning merchant id.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Platform language code.", "type": [ "string", "null" ] }, "name": { "description": "Interview name.", "type": [ "string", "null" ] }, "recording": { "description": "Per-answer recording/proctoring mode.", "type": [ "string", "null" ] }, "recording_full_session": { "description": "Full-session recording mode.", "type": [ "string", "null" ] }, "speech_language_code": { "description": "Speech language code.", "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status.", "type": [ "string", "null" ] }, "type": { "description": "Product type (interview/coaching/…).", "type": [ "string", "null" ] }, "type_avatar": { "description": "Avatar type used by the interview.", "type": [ "string", "null" ] }, "updated_at": { "description": "Last update timestamp (ISO 8601).", "type": [ "string", "null" ] }, "visibility": { "description": "Visibility (merchant_public/invite/unlisted/…).", "type": [ "string", "null" ] } }, "required": [ "id" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantInterviewListResponse" } }, { "description": "[Admin] List supported platform (mojito) languages: the `code` to pass as `mojito_language_code`, English/local names, SVG flag URL, per-interface enablement flags, and Azure speech accents.\n\nReturns all supported platform (mojito) languages: the mojito language code, English and local names, and an SVG flag image URL. Use the `code` as `mojito_language_code` when creating interviews or personas.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" } }, "required": [], "type": "object" }, "name": "list_languages", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "languages": { "description": "Supported platform languages, sorted by English name.", "items": { "properties": { "accents": { "description": "Azure speech regional accents / variants available for this language, each with its locale `code` and `name`.", "items": { "properties": { "code": { "description": "Azure speech locale code for the accent/regional variant.", "example": "en-US", "type": [ "string", "null" ] }, "name": { "description": "Human-readable accent name.", "example": "English (United States)", "type": [ "string", "null" ] } }, "required": [ "code", "name" ], "type": "object" }, "type": [ "array", "null" ] }, "admin_interface": { "description": "Whether this language is enabled on the admin interface.", "example": true, "type": [ "boolean", "null" ] }, "coaching_interface": { "description": "Whether this language is enabled on the coaching (consumer) interface.", "example": true, "type": [ "boolean", "null" ] }, "code": { "description": "Mojito platform language code. Pass this as `mojito_language_code` when creating interviews / personas.", "example": "en", "type": [ "string", "null" ] }, "flag_emoji": { "description": "Flag emoji for the language.", "example": "🇺🇸", "type": [ "string", "null" ] }, "flag_image": { "description": "URL to an SVG flag image for the language (same source the app UI renders).", "example": "https://cdn.jsdelivr.net/npm/[email protected]/dist/images/US.svg", "type": [ "string", "null" ] }, "flag_unicode": { "description": "Unicode code points for the flag emoji.", "example": "U+1F1FA U+1F1F8", "type": [ "string", "null" ] }, "interview_interface": { "description": "Whether this language is enabled on the interview interface.", "example": true, "type": [ "boolean", "null" ] }, "name_english": { "description": "Language name in English.", "example": "English", "type": [ "string", "null" ] }, "name_local": { "description": "Language name written in the language itself.", "example": "English", "type": [ "string", "null" ] } }, "required": [ "code", "name_english", "name_local", "flag_image", "flag_emoji", "flag_unicode", "coaching_interface", "interview_interface", "admin_interface", "accents" ], "type": "object" }, "type": [ "array", "null" ] } }, "required": [ "languages" ], "type": "object", "x-fastmcp-top-level-schema": "PlatformLanguagesListResponse" } }, { "description": "FALLBACK merchant list for clients WITHOUT UI support.\n\nDo NOT use this to choose or switch merchants when a UI is available —\ncall `jobmojito_configuration` instead (it renders an interactive picker),\nand do not hand-format a merchant list as text. Use this tool only when the\nclient cannot render MCP App UI. Returns the user's own account plus any\nsub-merchants; after a pick, pass `merchant_id=<chosen id>` on subsequent\ncalls (OMIT for the own account).", "inputSchema": { "additionalProperties": false, "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "search": { "default": "", "description": "Optional case-insensitive filter on sub-merchant name.", "type": "string" } }, "type": "object" }, "name": "list_my_merchants", "outputSchema": { "additionalProperties": true, "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" } }, "type": "object" } }, { "description": "[Admin] List sub-merchants under the merchant account.\n\nPaginated list of the sub-merchants the caller administers (the admin-portal sub-merchants list). Visibility is enforced by row-level security. Capped at 1000 records per page.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "filter_text": { "description": "Case-insensitive search on the sub-merchant name.", "type": "string" }, "limit": { "default": 50, "description": "Maximum number of records to return (1–1000).", "example": 50, "maximum": 1000, "minimum": 1, "type": "integer" }, "merchant_id": { "description": "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant.", "example": "28106cba-1c27-4e53-b149-32113e5e8e31", "format": "uuid", "type": "string" }, "offset": { "default": 0, "description": "Number of records to skip from the start of the result set.", "example": 0, "minimum": 0, "type": "integer" }, "order_by": { "default": "created_at_newest", "description": "Sort order of the result set.", "enum": [ "name", "created_at_newest", "created_at_oldest" ], "example": "created_at_newest", "type": "string" } }, "required": [], "type": "object" }, "name": "list_sub_merchants", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "data": { "description": "The sub-merchants the caller administers for this page.", "items": { "additionalProperties": {}, "properties": { "admin_profiles": { "description": "Admin profiles linked to this sub-merchant (jsonb)." }, "billing_country": { "description": "Billing country.", "type": [ "string", "null" ] }, "business_type": { "description": "Business type.", "type": [ "string", "null" ] }, "consumer_webanalytics": { "description": "Consumer web-analytics id.", "type": [ "string", "null" ] }, "contact_email": { "description": "Primary contact email.", "type": [ "string", "null" ] }, "contact_person": { "description": "Primary contact name.", "type": [ "string", "null" ] }, "created_at": { "description": "Creation timestamp (ISO 8601).", "type": [ "string", "null" ] }, "credits_used_30d": { "description": "Credits used in the last 30 days.", "type": [ "number", "null" ] }, "credits_used_total": { "description": "Total credits used.", "type": [ "number", "null" ] }, "frontend_domain": { "description": "Consumer frontend domain.", "type": [ "string", "null" ] }, "id": { "description": "Sub-merchant id.", "type": [ "string", "null" ] }, "image_logo_url": { "description": "Logo image URL.", "type": [ "string", "null" ] }, "info_notes": { "description": "Internal notes.", "type": [ "string", "null" ] }, "interview_count": { "description": "Total interviews run.", "type": [ "number", "null" ] }, "interview_frontend_domain": { "description": "Interview frontend domain.", "type": [ "string", "null" ] }, "interview_latest": { "description": "Most recent interview timestamp (ISO 8601).", "type": [ "string", "null" ] }, "interview_subscription_status": { "description": "Interview subscription status.", "type": [ "string", "null" ] }, "interview_subscription_type": { "description": "Interview subscription type.", "type": [ "string", "null" ] }, "interview_webanalytics": { "description": "Interview web-analytics id.", "type": [ "string", "null" ] }, "merchant_features": { "description": "Enabled feature flags (jsonb)." }, "name": { "description": "Sub-merchant name.", "type": [ "string", "null" ] }, "register_domain": { "description": "Registration domain.", "type": [ "string", "null" ] }, "status": { "description": "Status.", "type": [ "string", "null" ] }, "stripe_interview_subscription_start": { "description": "Subscription start (ISO 8601).", "type": [ "string", "null" ] }, "users": { "description": "Users linked to this sub-merchant (jsonb)." } }, "required": [ "id" ], "type": "object" }, "type": [ "array", "null" ] }, "pagination": { "properties": { "has_more": { "description": "True when more records exist beyond this page (offset + returned < total).", "example": true, "type": [ "boolean", "null" ] }, "limit": { "description": "Page size used for this response.", "example": 50, "type": [ "integer", "null" ] }, "offset": { "description": "Offset used for this response.", "example": 0, "type": [ "integer", "null" ] }, "total": { "description": "Total matching records across all pages.", "example": 137, "type": [ "integer", "null" ] } }, "required": [ "total", "limit", "offset", "has_more" ], "type": "object" } }, "required": [ "data", "pagination" ], "type": "object", "x-fastmcp-top-level-schema": "MerchantSubMerchantListResponse" } }, { "description": "[Interviews] Register users/candidates for a specific interview and return their personal interview links.\n\nRegisters (or updates) one or more candidate profiles for an interview and returns a one-time interview URL for each. Accepts a Supabase user JWT (merchant/admin) or the service key (merchant_id then required).", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "hide_iframe": { "anyOf": [ { "type": "boolean" }, { "type": "string" }, {} ], "description": "When true (or the string \"true\"), the interview UI hides its iframe chrome (view_hi)." }, "hide_menu": { "anyOf": [ { "type": "boolean" }, { "type": "string" }, {} ], "description": "When true (or the string \"true\"), the interview UI hides its menu (view_hm)." }, "interview_id": { "description": "Interview definition (interview_def_set) or position (position_def_set) id to register users for.", "example": "04e09fa5-3fb8-4236-b37d-fca2bcd1cb66", "format": "uuid", "minLength": 1, "type": [ "string", "null" ] }, "is_test": { "anyOf": [ { "type": "boolean" }, { "type": "string" }, {} ], "description": "When true (or the string \"true\"), mints a test token that can take a draft/unpublished interview and flags the result as a test. For a DRAFT interview it also recompiles the definition (interview_recalc_definition) first, so the test session includes the current questions/welcome. This makes it a single-call \"trigger interview test\"." }, "merchant_id": { "description": "Merchant id. Required when authenticating with the service key; for user tokens it is optional and only honored for admin / sub-merchant accounts.", "example": "b5201178-46dd-4a20-a1af-7ffd647f834b", "format": "uuid", "type": [ "string", "null" ] }, "send_email": { "description": "Whether to send an invitation email to each registered candidate.", "type": [ "boolean", "null" ] }, "users": { "description": "Candidates to register for the interview. Each gets a one-time interview URL.", "example": [ { "email": "[email protected]", "external_id": "abcd", "name": "Peter Parker" }, { "email": "[email protected]", "name": "Mary Jane Watson" } ], "items": { "properties": { "email": { "description": "Email used to identify and invite the candidate. Validated per item, not request-level.", "example": "[email protected]", "type": [ "string", "null" ] }, "external_id": { "description": "Optional caller-supplied id, stored on the candidate profile.", "example": "abcd", "type": [ "string", "null" ] }, "name": { "description": "Display name of the candidate.", "example": "Peter Parker", "type": [ "string", "null" ] }, "phone": { "description": "Optional mobile number in international format (E.164, e.g. +421903123456). Enables SMS / WhatsApp invitation and reminder notifications when the interview has candidate_notification_channel set. Never overwrites a phone already stored on the candidate.", "example": "+421903123456", "type": [ "string", "null" ] } }, "type": "object" }, "type": [ "array", "null" ] } }, "required": [ "users", "interview_id" ], "type": "object" }, "name": "register_users_for_interview", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "result": { "description": "The input users, each annotated with its registration result and (on success) interview URL.", "items": { "additionalProperties": {}, "properties": { "email": { "type": [ "string", "null" ] }, "external_id": { "type": [ "string", "null" ] }, "interview_url": { "description": "One-time interview URL containing the minted interview_token. Present only on success.", "type": [ "string", "null" ] }, "name": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] }, "result": { "description": "\"ok\" on success, otherwise an \"Error: ...\" message for that user.", "example": "ok", "type": [ "string", "null" ] } }, "type": "object" }, "type": "array", "x-fastmcp-top-level-schema": "JobInterviewRegisterUsersResponse" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "[Results] Re-open a submitted interview result so the candidate can retry.\n\nMarks a submitted (active + completed) interview result as unsuccessful so the candidate can retake it. Resets the result to draft and clears the recruiter decision.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "interview_result_id": { "description": "The interview result to reopen for another attempt.", "example": "93c98d21-e04d-4a84-9afa-ed154cf73636", "format": "uuid", "minLength": 1, "type": [ "string", "null" ] } }, "required": [ "interview_result_id" ], "type": "object" }, "name": "request_another_interview_attempt", "outputSchema": { "description": "Empty object on success.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" } }, "type": "object", "x-fastmcp-top-level-schema": "RequestAnotherAttemptResponse" } }, { "description": "Search ALL JobMojito documentation. This is the single entry point.\n\nOne call searches both documentation sources in parallel and returns a\nmerged, source-labeled list — you do not need to choose a source or call\na separate tool:\n • \"developer\" — developer.jobmojito.com: API reference, request/response\n schemas, tables, webhooks, code examples, integration guides.\n • \"help\" — help.jobmojito.com: recruiter, candidate, and administrator\n product guides (how the platform behaves for end users).\n\nUse this whenever you need to understand how a feature, endpoint, field,\nor workflow works — including before calling an action tool you're unsure\nabout. Then call `get_documentation(url)` with a returned URL to read the\nfull page.", "inputSchema": { "additionalProperties": false, "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "limit": { "default": 8, "description": "Max results per source (1-25).", "type": "integer" }, "query": { "description": "Natural-language search query or keywords.", "type": "string" }, "source": { "default": "all", "description": "\"all\" (default), \"developer\", or \"help\" to restrict the search.", "type": "string" } }, "required": [ "query" ], "type": "object" }, "name": "search_documentation", "outputSchema": { "additionalProperties": true, "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" } }, "type": "object" } }, { "description": "[Interviews] Change the state of an interview/position (e.g. open, closed).\n\nChanges the lifecycle status of an interview or position (draft, active, archived, preparing, completed, deleted) and/or manages its embed key. Provide at least one of `status` or `is_embedded`.", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "is_embedded": { "description": "Controls iframe embedding of the interview on an external page. When true, ensures an embed key exists (returns embed_id/embed_signing_key, used to authenticate/sign the iframe embed). When false, removes the embed keys (disables embedding).", "type": [ "boolean", "null" ] }, "position_id": { "description": "Interview definition id or position id whose state should change.", "example": "00000000-0000-0000-0000-000000000000", "format": "uuid", "minLength": 1, "type": [ "string", "null" ] }, "status": { "description": "New lifecycle status to apply.", "enum": [ "draft", "active", "archived", "deleted", "preparing", "completed", null ], "type": [ "string", "null" ] } }, "required": [ "position_id" ], "type": "object" }, "name": "set_interview_state", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "result": { "anyOf": [ { "properties": { "success": { "type": [ "boolean", "null" ] } }, "required": [ "success" ], "type": "object" }, { "properties": { "embed_id": { "type": [ "string", "null" ] }, "embed_signing_key": { "type": [ "string", "null" ] } }, "required": [ "embed_id", "embed_signing_key" ], "type": "object" } ], "description": "Returns `{ embed_id, embed_signing_key }` when an embed key was created/returned (is_embedded=true), otherwise `{ success: true }`.", "x-fastmcp-top-level-schema": "JobInterviewSetStateResponse" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "[Coaching catalogue] Update a coaching catalogue directory: rename it, change which sessions it lists (`tags_interview_set_filter`), re-order its sub-directories (`tags_sub`), or author its custom Markdown page (`content_md`). Only the fields you send are changed. Coaching-platform feature.\n\nUpdates a directory (page) of the coaching portal catalogue. Only the fields present in the request body are written — everything else keeps its current value, and sending null clears a nullable field. Use it to rename a directory, re-point which sessions it lists (`tags_interview_set_filter`), re-order or replace its sub-directories (`tags_sub`), or author its custom Markdown page (`content_md`).", "inputSchema": { "properties": { "coach_plan": { "description": "Coaching-plan stage this item belongs to, used by the coaching-plan progress view. Omit/null to leave it out of any plan. Options — `demo`: Demo session. | `screening`: Screening-interview practice. | `2nd`: Second-interview practice. | `3rd`: Third-interview practice. | `closing`: Closing / salary-negotiation practice. | `job-specific`: Job-specific coaching. | `other`: Anything that does not fit the other buckets..", "enum": [ "demo", "screening", "2nd", "3rd", "closing", "job-specific", "other", null ], "example": "screening", "type": [ "string", "null" ] }, "content_md": { "description": "Markdown for the custom directory page. Sending null removes the custom page and restores the default grid; sending a string replaces the whole page. Directives, each ALONE on its own line: `[plan-progress]`, `[directory:<tag-id>]`, `[session:<interview-id>]`, `[sessions]`, `[sessions:<term>]`, `[sessions:filter=<term>,limit=<n>]`. Chips, callouts, cards, columns and buttons are available too — formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown", "example": "## Sales coaching\n\nPick a session to practise with.\n\n[chip:6 sessions] [chip:Beginner,tone=accent]\n\n[sessions:filter=objection-handling,limit=6]\n", "type": [ "string", "null" ] }, "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "cover_image_url": { "description": "Cover image URL shown on the directory card. null clears it.", "type": [ "string", "null" ] }, "description": { "description": "Short description shown on the directory card.", "type": [ "string", "null" ] }, "id": { "description": "Id of the directory to update (the catalogue URL segment). The id itself cannot be changed — create a new directory instead.", "example": "sales-coaching-en", "minLength": 1, "pattern": "^[a-z0-9]+(?:(?:-|_)+[a-z0-9]+)*$", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Language of the directory (one of the platform-languages.json codes). The catalogue groups directories by language.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "name": { "description": "Display name of the directory.", "example": "Sales coaching", "minLength": 1, "type": [ "string", "null" ] }, "status": { "description": "Lifecycle status of the catalogue directory. Options — `draft`: Not published — the directory exists but is not served to visitors. | `active`: Published and served in the catalogue. | `archived`: Retired — kept for reference but no longer served..", "enum": [ "draft", "active", "archived", null ], "example": "active", "type": [ "string", "null" ] }, "tags_interview_set_filter": { "description": "Tag filter selecting which coaching sessions this directory lists: a session appears when its own `tags` contain EVERY tag here (an AND, not an OR). Only `active` coaching/persona sessions with visibility `public` or `merchant_public` are listed. Set the matching tags on the session with the create-interview / job-interview-update `tags` field.", "example": [ "sales", "objection-handling" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "tags_sub": { "description": "Ids of the directories nested under this one, in display order. Replaces the whole list — send the full set, not just the additions. A referenced directory only appears if it exists and is visible to the viewer.", "example": [ "sales-coaching-objections-en", "sales-coaching-closing-en" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "visibility": { "description": "Who can see the catalogue directory. Options — `public`: Shared across every merchant. Platform admins only — a merchant caller is rejected by row-level security. | `merchant_public`: Listed in the merchant's own catalogue — the normal choice. | `merchant_invite`: Owned by the merchant but not listed; reachable only for invited users. | `merchant_unlisted`: Owned by the merchant but not listed; reachable only via a direct link..", "enum": [ "public", "merchant_public", "merchant_invite", "merchant_unlisted", null ], "example": "merchant_public", "type": [ "string", "null" ] } }, "required": [ "id" ], "type": "object" }, "name": "update_catalogue_directory", "outputSchema": { "description": "Confirmation of what was updated.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "catalogue_url": { "description": "Public URL of the directory page, when the merchant has a coaching-portal domain configured. Null otherwise.", "example": "https://coaching.example.com/catalogue/sales-coaching-en", "type": [ "string", "null" ] }, "id": { "description": "Id of the updated directory.", "example": "sales-coaching-en", "type": [ "string", "null" ] }, "updated_fields": { "description": "Names of the fields that were written.", "example": [ "content_md", "tags_interview_set_filter" ], "items": { "type": "string" }, "type": [ "array", "null" ] } }, "required": [ "id", "updated_fields", "catalogue_url" ], "type": "object", "x-fastmcp-top-level-schema": "CatalogueTagUpdateResponse" } }, { "description": "[Interviews] Update the configuration of an existing interview/position: name, description, avatar template, recording, scoring, tags and the rest of the create-time settings. Only the fields you send are changed. To change the questions, send `questions` — the WHOLE list you want the interview to end up with, in order, in the format get_interview_definition returns. OMIT `questions` and the existing questions are left completely alone; there is no way to change one question on its own, so read the interview first, edit that array, and send it back. Resending an unchanged array does nothing. Not updated by this tool at all: the welcome and thank-you messages and the instructional-video screen (stored as steps, not questions), and the language, which the existing questions are already written in. Use `tags` to place a coaching session into a catalogue directory. MULTI-STAGE POSITIONS: some per-interview settings do not exist at position level and are rejected with a 422 naming the field — `candidate_expectations_json` is the one seen in practice. Read the position with get_interview_definition, then update the individual stage you mean instead of sending that field to the position.\n\nUpdates the configuration of an existing interview (single-stage) or position (multi-stage). Only the fields present in the request body are written — everything else keeps its current value, and sending null clears a nullable field. The question list is only touched when you send `questions`; omit that field and the questions are left exactly as they are. When sent, it must be the complete list and is applied as a diff against what is stored (matched on external_id, then id, then identical content), so unchanged questions keep their existing records, edited ones are unlinked and re-created, and dropped ones are unlinked — and re-sending the array job-interview-get returned changes nothing. See the field description, and `questions_diff` in the response for what was decided. Questions of an interview that is already `active` can only be changed on interactive avatar templates, where re-publishing is instant; on the offline (pre-rendered video) templates set the interview back to `draft` first. The welcome / thank-you messages and the instructional-video screen are stored as steps rather than questions and are never changed here. `mojito_language_code` cannot be changed — the existing questions and rendered videos are in the original language — so create a new interview to change language. A multi-stage position only carries the shared identity fields (name, code, location, description, description_long, cover_image_url, department, salary, available_till, recruiter, status, visibility, hiring_for_company); sending an interview-only field for a position is a 422.", "inputSchema": { "properties": { "candidate_expectations": { "description": "Free-text candidate expectations.", "type": [ "string", "null" ] }, "candidate_expectations_json": { "description": "Structured candidate expectations (the scoring rubric), bucketed by requirement level (weak/moderate/strong). null clears the rubric. Extra keys are preserved.", "properties": { "moderate": { "description": "Requirements expected of a solid, competent candidate.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "strong": { "description": "High-bar requirements only standout candidates clear.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "weak": { "description": "Baseline requirements every viable candidate should meet (table stakes).", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "type": [ "object", "null" ] }, "candidate_notification_channel": { "description": "SMS / WhatsApp notifications to the candidate, sent alongside the e-mails: \"reminders\" = with both e-mail reminders (day 1 and day 3); \"last_reminder\" = only with the final day-3 reminder; \"all\" = invitation, both reminders and the pre-screening-accepted step. null switches them off. WhatsApp is tried first, SMS when the number is not on WhatsApp. Available on paid plans (Starter and above) and needs a phone number on the candidate.", "enum": [ "reminders", "last_reminder", "all", null ], "type": [ "string", "null" ] }, "candidate_video_introduction": { "description": "Whether a candidate video introduction is hidden, optional or required. null is treated like hidden.", "enum": [ "hidden", "optional", "required", null ], "type": [ "string", "null" ] }, "coach_plan": { "description": "Coaching-plan stage this item belongs to, used by the coaching-plan progress view. Omit/null to leave it out of any plan. Options — `demo`: Demo session. | `screening`: Screening-interview practice. | `2nd`: Second-interview practice. | `3rd`: Third-interview practice. | `closing`: Closing / salary-negotiation practice. | `job-specific`: Job-specific coaching. | `other`: Anything that does not fit the other buckets..", "enum": [ "demo", "screening", "2nd", "3rd", "closing", "job-specific", "other", null ], "example": "screening", "type": [ "string", "null" ] }, "code": { "description": "External code/reference. Blank is stored as null.", "type": [ "string", "null" ] }, "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "country_availability": { "description": "Which countries the interview / position is open to on the candidate portal, judged by the IP address the candidate opens it from (an unknown location only passes when countries_allowed / countries_allowed_eu are empty). From a closed country it is left out of the portal listings, and a direct link shows \"not available in your region\". Invited candidates (register_users / invite links) and candidates who already started keep access; API and MCP calls themselves are never restricted. Null = not used, every country.", "properties": { "countries_allowed": { "description": "Available ONLY to candidates in these countries (ISO 3166-1 alpha-2).", "example": [ "PH", "IN" ], "items": { "pattern": "^[A-Za-z]{2}$", "type": "string" }, "type": [ "array", "null" ] }, "countries_allowed_eu": { "description": "Adds every EU country (plus EEA and Switzerland) to countries_allowed.", "type": [ "boolean", "null" ] }, "countries_blocked": { "description": "NOT available to candidates in these countries (ISO 3166-1 alpha-2). Wins over the allowed side.", "example": [ "US" ], "items": { "pattern": "^[A-Za-z]{2}$", "type": "string" }, "type": [ "array", "null" ] }, "countries_blocked_eu": { "description": "Adds every EU country (plus EEA and Switzerland) to countries_blocked.", "type": [ "boolean", "null" ] } }, "type": [ "object", "null" ] }, "cover_image_url": { "description": "Cover image URL.", "type": [ "string", "null" ] }, "custom_scoring": { "additionalProperties": {}, "description": "Result-scoring overrides (max_score, early_stop, speech_cadence, ai_pronunciation, sentiment_analysis, ai_assessment_answer, ai_assessment_resume, ai_assessment_session). Merged onto the stored configuration, so keys you omit keep their current value.", "type": [ "object", "null" ] }, "description": { "description": "Short interview description.", "type": [ "string", "null" ] }, "description_long": { "description": "Long-form interview description (column `interview_description_long`). Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons — formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown", "type": [ "string", "null" ] }, "environment": { "description": "Which of your webhook environments results from this interview are delivered to. Defaults to production. Options — `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..", "enum": [ "production", "uat", "development", "demo", null ], "example": "production", "type": [ "string", "null" ] }, "hiring_for_company": { "description": "Who the position is really for. null (or an object with name null/blank) means hiring for yourself; { name: 'undisclosed' } for an unnamed external client; or { name: '<company>' } plus optional description/location/sector/company_size. Stored in creation_parameters.hiring_for_company.", "example": { "name": "undisclosed" }, "properties": { "company_size": { "description": "Approximate headcount of the end employer.", "example": "100-200", "type": [ "string", "null" ] }, "description": { "description": "Short description of the end employer, used as background context by the agent.", "example": "Unimo Enterprises is a leading logistics and supply chain solutions provider.", "type": [ "string", "null" ] }, "location": { "description": "Primary location of the end employer.", "example": "Sri Lanka", "type": [ "string", "null" ] }, "name": { "description": "End-employer name. Omit/null when hiring for yourself, 'undisclosed' for an unnamed external client, or the client's company name.", "example": "Unimo Enterprises", "type": [ "string", "null" ] }, "sector": { "description": "Industry / sector of the end employer.", "example": "Logistics and Supply Chain", "type": [ "string", "null" ] } }, "type": [ "object", "null" ] }, "interview_attempts": { "description": "Allowed candidate attempts (1-20). Stored as result_scoring.max_retries.", "example": 1, "maximum": 20, "minimum": 1, "type": [ "number", "null" ] }, "interview_available_till": { "description": "ISO date/time after which the interview is no longer available to candidates. null keeps it always available.", "example": "2026-12-31", "type": [ "string", "null" ] }, "interview_conversation_speed": { "description": "Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options — `slower`: The avatar speaks more slowly — easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..", "enum": [ "slower", "normal", "faster", null ], "example": "normal", "type": [ "string", "null" ] }, "interview_department": { "description": "Department the position belongs to. Blank is stored as null.", "example": "Engineering", "type": [ "string", "null" ] }, "interview_salary": { "description": "Salary range shown for the position. Blank is stored as null.", "example": "$80k - $100k", "type": [ "string", "null" ] }, "interview_template_id": { "description": "Id of the interview template (avatar/voice) to use. Must reference an existing interview_templates row. Also decides the modality — see list_avatars / merchant-avatar-list.", "example": "46b98d37-1557-4391-beca-03037ead19f2", "minLength": 1, "type": [ "string", "null" ] }, "interview_tone": { "description": "Tone — configures the AI avatar's speaking style and the follow-up questions it generates. Stored in creation_parameters; existing questions are NOT regenerated. Case-insensitive; omit to default to relaxed. Options — `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level — short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing — for interviews built from your own questions (create_interview_from_questions) where the wording is a script..", "enum": [ "relaxed", "simple", "professional", "persuasive", "exact", null ], "example": "professional", "type": [ "string", "null" ] }, "interview_type": { "description": "Interview style — configures the AI avatar and the follow-up questions it generates during the interview. Stored in creation_parameters; existing questions are NOT regenerated. Options — `pre-screening`: Pre-screening — quick qualification check focusing on basic requirements and availability. | `pre-screening-with-test-questions`: Pre-screening with test questions — pre-screening plus practical questions to test relevant skills. | `second-interview`: Second round interview — deeper dive for candidates who passed initial screening. | `remote-freelancer-verification`: Remote worker verification — verify remote work capabilities and communication skills. | `strength-based-interview`: Strength-based interview — focus on what candidates enjoy and excel at to predict job satisfaction. | `potential-based-interview`: Potential-based interview — assess learning ability and growth potential rather than past experience. | `process-verification-from-knowledge-base`: Knowledge Base interview — generate questions from your knowledge base documents..", "enum": [ "pre-screening", "pre-screening-with-test-questions", "second-interview", "remote-freelancer-verification", "strength-based-interview", "potential-based-interview", "process-verification-from-knowledge-base", null ], "example": "pre-screening-with-test-questions", "type": [ "string", "null" ] }, "knowledge_base_store_id": { "description": "Knowledge base store id the interview draws context from; validated for existence. null unlinks it.", "type": [ "string", "null" ] }, "location": { "description": "Interview location (column `interview_location`). Blank is stored as null.", "example": "remote", "type": [ "string", "null" ] }, "max_duration": { "description": "Live session limit in seconds. Also the basis for the credit multiplier.", "example": 1200, "type": [ "number", "null" ] }, "max_followups": { "description": "Maximum number of AI follow-up questions. 0 disables follow-ups; presets are 0-3 (none/low/normal/high) and custom values start at 4; null uses the template default (Normal).", "example": 2, "maximum": 999, "minimum": 0, "type": [ "integer", "null" ] }, "name": { "description": "Interview / position name.", "example": "Project manager", "type": [ "string", "null" ] }, "pdf_export_auto_config": { "description": "Auto-generate a candidate PDF report with these options once the interview completes. null disables auto-export.", "properties": { "ai_recruiter_assessment": { "description": "Include the AI recruiter assessment.", "type": [ "boolean", "null" ] }, "ai_scoring_rubric": { "description": "Include the AI scoring rubric.", "type": [ "boolean", "null" ] }, "analytics": { "description": "Include analytics.", "type": [ "boolean", "null" ] }, "answer_recording": { "description": "Include per-answer recordings.", "type": [ "boolean", "null" ] }, "contact_details": { "description": "Include candidate contact details.", "type": [ "boolean", "null" ] }, "files": { "description": "Include uploaded candidate files.", "type": [ "boolean", "null" ] }, "group_by_question": { "description": "Group transcript answers by expected question.", "type": [ "boolean", "null" ] }, "mojito_language_code": { "description": "Report language code (a platform-languages.json code).", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "session_recording": { "description": "Include the full-session recording.", "type": [ "boolean", "null" ] }, "template": { "description": "Report layout: classic, modern, or one_pager. Omit for the merchant default (modern when unset).", "enum": [ "classic", "modern", "one_pager", null ], "type": [ "string", "null" ] }, "transcript": { "description": "Include the interview transcript.", "type": [ "boolean", "null" ] } }, "type": [ "object", "null" ] }, "position_id": { "description": "Id of the interview definition (single-stage) or position definition (multi-stage) to update. The same id you pass to job-interview-get.", "example": "00000000-0000-0000-0000-000000000000", "format": "uuid", "minLength": 1, "type": [ "string", "null" ] }, "questions": { "description": "OPTIONAL. Omit this field entirely and the interview's questions are left exactly as they are — this endpoint only touches questions when you send the array. When you do send it, send the COMPLETE list you want the interview to end up with, in order, in the same format job-interview-create-from-array accepts and job-interview-get returns: there is no way to change a single question on its own, so read the interview, edit that array, and send the whole thing back. An empty array is rejected. It is applied as a DIFF, not a replace, so resending the array job-interview-get gave you changes nothing at all. Each entry is matched against what is stored — first on `external_id`, then on `id`, then on identical content — and: an entry matching an unchanged question keeps that question exactly as it is, including its answer rules and any rendered avatar video; an entry matching a question whose content differs unlinks the old question and creates a new one in its place (fields you omit are carried over from the old one); an entry matching nothing is created; and a stored question no entry matches is unlinked. `questions_diff` in the response reports exactly what was decided. Questions are shared records, so nothing is ever deleted — removing one only unlinks it from this interview, and an edit is always unlink-old + create-new so the change cannot leak into another interview reusing the same question. The welcome, thank-you and instructional-video steps are not part of this array and are left in place. Single-stage interviews only; for a multi-stage position, update its interview stages individually.", "items": { "additionalProperties": {}, "properties": { "candidate_expectations_json": { "description": "Per-question candidate expectations, bucketed by requirement level (weak/moderate/strong). Extra keys are preserved.", "properties": { "moderate": { "description": "Requirements expected of a solid, competent candidate.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "strong": { "description": "High-bar requirements only standout candidates clear.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "weak": { "description": "Baseline requirements every viable candidate should meet (table stakes).", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "type": [ "object", "null" ] }, "conditional_question_main_id": { "description": "For a conditional question, the id (the \"id\" field above) of the parent question in this same array that triggers it. The parent must appear earlier in the array than the conditional question referencing it.", "type": [ "string", "null" ] }, "duration": { "description": "Answer duration in seconds for this question.", "type": [ "number", "null" ] }, "external_data": { "additionalProperties": {}, "description": "Arbitrary JSON metadata stored on the question.", "type": [ "object", "null" ] }, "external_id": { "description": "External identifier stored on the question. job-interview-update matches on this first, so an ATS that owns stable ids can send its own array and have the diff line up without round-tripping our ids.", "type": [ "string", "null" ] }, "id": { "description": "Identifier for this question. job-interview-get returns the question's real id here; send it back to job-interview-update so an unchanged question keeps its existing record (and with it its answer rules and any rendered avatar video). Also the handle another question references via conditional_question_main_id. On job-interview-create-from-array it is a caller-local value, only needed for those references.", "type": [ "string", "null" ] }, "is_candidate_asking_recruiter": { "description": "Candidate-asks-recruiter prompt (view 'candidate asking recruiter').", "type": [ "boolean", "null" ] }, "is_conditional": { "description": "Conditional follow-up question (view 'with listening conditional'). Use with conditional_question_main_id.", "type": [ "boolean", "null" ] }, "is_expert": { "description": "Expert listening question (view 'with listening expert').", "type": [ "boolean", "null" ] }, "is_multiple_choice": { "description": "Multiple-choice question (view 'multiple choice').", "type": [ "boolean", "null" ] }, "is_without_scoring": { "description": "Question is asked but not scored (view 'without scoring').", "type": [ "boolean", "null" ] }, "knowledge_base_id": { "description": "Knowledge-base store id (uuid) the question draws context from.", "type": [ "string", "null" ] }, "label": { "description": "Optional label/tag stored on the question.", "type": [ "string", "null" ] }, "mojito_language_code": { "description": "Per-question language override (one of the platform-languages.json codes). Inherits the interview language when omitted.", "enum": [ "ar", "bg", "zh", "hr", "cs", "da", "nl", "en", "fil", "fi", "fr", "de", "el", "hi", "hu", "id", "it", "ja", "ko", "ms", "no", "pl", "pt", "br", "ro", "ru", "sk", "es", "sv", "ta", "th", "tr", "uk", "vi", null ], "example": "en", "type": [ "string", "null" ] }, "question": { "description": "The question text shown to the candidate.", "type": [ "string", "null" ] }, "question_alternatives": { "description": "Alternative phrasings for the question.", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "required": [ "question" ], "type": "object" }, "minItems": 1, "type": [ "array", "null" ] }, "questions_random_subset": { "description": "Ask only a random subset of the questions, as a fraction between 0.01 and 0.9. null asks all questions.", "example": 0.5, "maximum": 0.9, "minimum": 0.01, "type": [ "number", "null" ] }, "recording": { "description": "Cheating/proctoring detection mode for candidate answers — this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options — `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..", "enum": [ "audio_first_5_answers", "audio_all", "video_all", "video_first_5_answers", null ], "example": "video_all", "type": [ "string", "null" ] }, "recording_full_session": { "description": "Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options — `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..", "enum": [ "audio_all", "video_all", null ], "example": "video_all", "type": [ "string", "null" ] }, "recruiter_profile_id": { "description": "Profile id of the recruiter owning this interview. Must be a merchant/merchant_owner/admin profile of the same merchant. null clears it.", "type": [ "string", "null" ] }, "regenerate_candidate_expectations": { "description": "Re-derive the interview-level `candidate_expectations_json` scoring rubric from the resulting question list, the way job-interview-create-from-array derives it at creation time. Only applies when `questions` is sent, the interview type is `interview`, and `candidate_expectations_json` is not also being set explicitly (an explicit value wins).", "example": false, "type": [ "boolean", "null" ] }, "required_pronunciation": { "description": "Require pronunciation assessment (restricts to pronunciation-capable languages).", "type": [ "boolean", "null" ] }, "result_enable_edit_transcript": { "description": "Allow editing the transcript on the result view.", "type": [ "boolean", "null" ] }, "result_view": { "description": "Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options — `none`: No results screen at all — the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..", "enum": [ "none", "minimal", "minimal_with_score", "advanced", "full", "full_expand_scores", null ], "example": "full", "type": [ "string", "null" ] }, "seniority_level": { "description": "Target seniority level for the role; auto-detected from the job description when omitted. Options — `entry-level`: Early-career or graduate roles. | `intermediate`: Some experience required. | `senior`: Experienced professional. | `managerial`: Team or department lead. | `director`: Director-level responsibility. | `executive`: C-suite or executive role..", "enum": [ "entry-level", "intermediate", "senior", "managerial", "director", "executive", null ], "example": "senior", "type": [ "string", "null" ] }, "status": { "description": "New lifecycle status. Applied through the same interview_set_status routine as job-interview-set-state (which is also where you manage the iframe embed key).", "enum": [ "draft", "active", "archived", "deleted", "preparing", "completed", null ], "example": "active", "type": [ "string", "null" ] }, "tags": { "description": "Free-form tags stored on the interview. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed.", "example": [ "interview-practice", "sales" ], "items": { "type": "string" }, "type": [ "array", "null" ] }, "type": { "description": "Product type of the interview. Changing it also re-derives `type_credit` (null for interview/assessment, otherwise interview_coach_manager) unless you send `type_credit` explicitly. Single-stage interviews only.", "enum": [ "interview", "coaching", "assessment", null ], "example": "interview", "type": [ "string", "null" ] }, "type_credit": { "description": "Credit bucket the session draws from. Only meaningful for candidate-paid coaching/persona sessions; hiring interviews and assessments are merchant-billed and carry null. Options — `resume_check`: Resume-check credits. | `interview_coach_starter`: Coaching credits — starter tier. | `interview_coach_contributor`: Coaching credits — contributor tier. | `interview_coach_manager`: Coaching credits — manager tier. | `cover_letter`: Cover-letter credits..", "enum": [ "resume_check", "interview_coach_starter", "interview_coach_contributor", "interview_coach_manager", "cover_letter", null ], "example": "interview_coach_manager", "type": [ "string", "null" ] }, "visibility": { "description": "Who can discover and access the interview. Options — `merchant_public`: Listed on the merchant's public interview list — anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only — only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link — not listed anywhere; share the link manually..", "enum": [ "merchant_public", "merchant_invite", "merchant_unlisted", null ], "example": "merchant_public", "type": [ "string", "null" ] } }, "required": [ "position_id" ], "type": "object" }, "name": "update_interview", "outputSchema": { "description": "Confirmation of what was updated.", "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "is_multistage": { "description": "True when the id resolved to a multi-stage position (position_def_set) rather than a single interview.", "type": [ "boolean", "null" ] }, "position_id": { "description": "The id that was updated.", "type": [ "string", "null" ] }, "questions_diff": { "description": "What the question diff decided, question by question. Absent when `questions` was not sent.", "properties": { "added": { "description": "Ids of the questions created for entries that matched nothing stored.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "kept": { "description": "Questions left exactly as they were, record and all.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "question_ids": { "description": "The interview's full ordered step list after the update, including the welcome / thank-you / instructional steps this endpoint does not manage.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "reactivated": { "description": "True when the interview was already active and was re-published so the new questions go live.", "type": [ "boolean", "null" ] }, "removed": { "description": "Ids unlinked because no entry in the request matched them. The question records themselves still exist.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "replaced": { "description": "Edited questions: the old record was unlinked and a new one created, so the change cannot leak into other interviews reusing it.", "items": { "properties": { "from": { "description": "The id that was unlinked.", "type": [ "string", "null" ] }, "to": { "description": "The id of the question created in its place.", "type": [ "string", "null" ] } }, "required": [ "from", "to" ], "type": "object" }, "type": [ "array", "null" ] } }, "required": [ "kept", "added", "removed", "replaced", "question_ids", "reactivated" ], "type": "object" }, "updated_fields": { "description": "Names of the stored columns that were written, plus `status` when the lifecycle status was changed and `questions` when the question list was diffed.", "example": [ "name", "tags" ], "items": { "type": "string" }, "type": [ "array", "null" ] } }, "required": [ "position_id", "is_multistage", "updated_fields" ], "type": "object", "x-fastmcp-top-level-schema": "JobInterviewUpdateResponse" } }, { "description": "[Knowledge base] Upload and process a knowledge base document (multipart form-data).\n\nUploads a document to a knowledge base store and queues it for processing. Accepts the file either as multipart/form-data (binary `file`) or as application/json (base64 `file`).", "inputSchema": { "properties": { "conversation_id": { "description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.", "type": "string" }, "file": { "description": "The document file (binary).", "format": "binary", "type": [ "string", "null" ] }, "knowledge_base_store_id": { "description": "The knowledge base store to add the document to.", "example": "d9d6f121-1230-48fd-b3a7-8b5a1e8db052", "minLength": 1, "type": [ "string", "null" ] }, "merchant_id": { "description": "Override merchant id (admin / sub-merchant only).", "type": [ "string", "null" ] }, "name": { "description": "Document name (with extension). Falls back to the uploaded file name for multipart.", "type": [ "string", "null" ] } }, "required": [ "knowledge_base_store_id", "file" ], "type": "object" }, "name": "upload_knowledge_base_document", "outputSchema": { "properties": { "_mcp_instructions": { "description": "Server-issued metadata for this conversation.", "properties": { "conversation_id": { "description": "The server-issued conversation identifier.", "type": "string" } }, "type": "object" }, "knowledge_base_id": { "description": "Id of the created knowledge_base record.", "type": [ "string", "null" ] } }, "required": [ "knowledge_base_id" ], "type": "object", "x-fastmcp-top-level-schema": "KnowledgeBaseDocumentUploadResponse" } } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:c69477b7e3c3633a755a498019b78bc5a61d7ff35b1909d864cc2b06f2688e02 | sha256sum