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

# Create a role-play — coaching persona or interview-portal role-play (choose with `portal`)

> FIRST DECIDE `portal`. This endpoint creates two different products and the default is NOT the recruiter one:
- `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.
- `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.
The conversation itself behaves identically in both.

The 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. Provisions the default conversational steps and optionally an embed key.



## OpenAPI

````yaml https://cool.jobmojito.com/functions/v1/openapi post /persona-create
openapi: 3.1.0
info:
  title: JobMojito API
  version: 1.0.0
  description: >-
    Public API for JobMojito, served by Supabase Edge Functions. Authenticate
    with a Supabase JWT access token via the Authorization header.
servers:
  - url: https://cool.jobmojito.com/functions/v1
    description: Production
security: []
tags:
  - name: Interviews
    description: >-
      Create, configure and manage interview / coaching / assessment
      definitions.
  - name: Results
    description: >-
      Interview results, transcripts, reports, re-attempt requests and
      analytics.
  - name: Candidates
    description: List and manage candidates.
  - name: Knowledge base
    description: Upload documents used to generate knowledge-base interviews.
  - name: Resume & Form verification
    description: Pre-screen candidates from resumes and forms.
  - name: Admin
    description: >-
      Account administration — invite team/coaching users, manage sub-merchants
      and avatar templates.
paths:
  /persona-create:
    post:
      tags:
        - Interviews
      summary: >-
        Create a role-play — coaching persona or interview-portal role-play
        (choose with `portal`)
      description: >-
        FIRST DECIDE `portal`. This endpoint creates two different products and
        the default is NOT the recruiter one:

        - `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.

        - `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.

        The conversation itself behaves identically in both.


        The 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. Provisions the default
        conversational steps and optionally an embed key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PersonaCreateRequest'
      responses:
        '200':
          description: Persona created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonaCreateResponse'
        '401':
          description: Missing, expired or invalid access token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: >-
            Validation error (missing required field, invalid enum value,
            out-of-range number, or unresolved template/language id).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: >-
            Server error (includes authorization failures and unhandled
            exceptions).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - bearerAuth: []
components:
  schemas:
    PersonaCreateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          description: Persona / session name.
          example: Difficult customer role-play
        interview_template_id:
          type: string
          minLength: 1
          format: uuid
          description: Id of the interview template (avatar) the persona uses.
          example: baa3bf7c-6926-46fd-9005-16738a31f72d
        mojito_language_code:
          type: string
          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
          description: >-
            Platform language code used for the conversation. Must be one of the
            platform-languages.json codes.
          example: en
        status:
          type: string
          enum:
            - draft
            - active
          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..
          example: active
        visibility:
          type: string
          enum:
            - merchant_public
            - merchant_invite
            - merchant_unlisted
          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..
          example: merchant_public
        persona_role_avatar:
          type: string
          minLength: 1
          description: >-
            The role the AI avatar plays. Example: 'is to act as a happy
            customer responding to questions'.
          example: is to act as a happy customer responding to questions
        persona_role_user:
          type: string
          minLength: 1
          description: >-
            The role the candidate (mentee) plays. 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
        persona_avatar_who_is:
          type: string
          nullable: true
          description: Who the avatar represents (background/identity of the persona).
        persona_avatar_knowledge:
          type: string
          nullable: true
          description: >-
            What the avatar knows — facts/context the avatar can draw on during
            the conversation.
        persona_avatar_end_conditions:
          type: string
          nullable: true
          description: Conditions under which the avatar should end the session.
        opening_line:
          type: string
          nullable: true
          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?
        candidate_expectations:
          type: string
          nullable: true
          maxLength: 2100
          description: >-
            Mentee assessment goals — free-text describing what the candidate is
            expected to achieve (max 2100 chars).
        recording:
          type: string
          nullable: true
          enum:
            - audio_first_5_answers
            - audio_all
            - video_all
            - video_first_5_answers
          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..
          example: video_all
        recording_full_session:
          type: string
          nullable: true
          enum:
            - audio_all
            - video_all
          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..
          example: video_all
        result_view:
          type: string
          nullable: true
          enum:
            - none
            - minimal
            - minimal_with_score
            - advanced
            - full
            - full_expand_scores
          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..
          example: full
        interview_conversation_speed:
          type: string
          nullable: true
          enum:
            - slower
            - normal
            - faster
          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..
          example: normal
        candidate_video_introduction:
          type: string
          nullable: true
          enum:
            - optional
            - required
          description: Whether a candidate video introduction is optional or required.
          example: optional
        max_duration:
          type: number
          nullable: true
          description: >-
            Maximum conversation duration in seconds. Defaults to 1200 (20 min)
            when omitted.
          example: 1200
        code:
          type: string
          nullable: true
          description: Optional external code/reference for the persona.
          example: my code
        cover_image_url:
          type: string
          nullable: true
          description: Cover image URL.
          example: https://example.com/cover.png
        interview_location:
          type: string
          nullable: true
          description: Optional location label shown for the session.
          example: remote
        merchant_id:
          type: string
          nullable: true
          description: >-
            Merchant id. Admin / sub-merchant callers only; otherwise taken from
            your token.
          example: 28106cba-1c27-4e53-b149-32113e5e8e31
        recruiter_profile_id:
          type: string
          nullable: true
          description: >-
            Profile id of the recruiter owning this persona. Must be a
            merchant/merchant_owner/admin profile of the same merchant.
        welcome_message:
          type: string
          nullable: true
          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.
        thank_you_message:
          type: string
          nullable: true
          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.
        tags:
          type: array
          nullable: true
          items:
            type: string
          description: Free-form tags stored on the persona.
          example:
            - sales
            - role-play
        portal:
          type: string
          nullable: true
          enum:
            - coaching
            - interview
          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.
          example: interview
        interview_attempts:
          type: number
          nullable: true
          minimum: 1
          maximum: 20
          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
        is_embedded:
          type: boolean
          nullable: true
          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
      required:
        - name
        - interview_template_id
        - mojito_language_code
        - status
        - visibility
        - persona_role_avatar
        - persona_role_user
    PersonaCreateResponse:
      type: object
      properties:
        interview_def_set_id:
          type: string
          description: Id of the newly created persona definition set.
          example: 00000000-0000-0000-0000-000000000000
        embed_id:
          type: string
          description: Embed id, present only when is_embedded=true.
        embed_signing_key:
          type: string
          description: Embed signing key, present only when is_embedded=true.
      required:
        - interview_def_set_id
      description: >-
        Id of the created persona. Includes embed_id/embed_signing_key when
        is_embedded=true.
    Error:
      type: object
      properties:
        error:
          type: string
          example: Field is required.
        name:
          type: string
          example: interview_result_id
      required:
        - error
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Supabase JWT — `Authorization: Bearer <token>`.'

````