Exec Scenarios API

The Scenarios API from Exec — 6 operation(s) for scenarios.

OpenAPI Specification

exec-scenarios-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: Exec Collections Scenarios API
  version: '1.0'
  description: 'REST API for programmatic access to your Exec workspace.


    Use the Exec API to read workspace data, list members, retrieve group information,

    and create interactive scenario creation sessions.


    ## Authentication

    All requests require a valid API key passed in the Authorization header:

    ```

    Authorization: Bearer exec_live_...

    ```


    Create API keys in your workspace settings under **Settings > API**.

    '
servers:
- url: https://api.exec.com/rest/v1
  description: Production
security:
- bearerAuth: []
tags:
- name: Scenarios
paths:
  /scenarios/assignments:
    get:
      operationId: listAssignments
      summary: List scenario assignments
      description: 'Returns a paginated list of scenario assignments in the workspace.


        Assignments represent tasks given to users to practice specific scenarios. Each

        assignment tracks status (not_started, in_progress, completed, past_due, did_not_pass),

        best score, attempt count, and completion requirements.


        Filter by user, scenario, program, or status to find specific assignments.

        '
      tags:
      - Scenarios
      parameters:
      - name: user_ids
        in: query
        description: Comma-separated user IDs to filter by. When combined with user_emails, results are unioned (all matching users from either list are included).
        schema:
          type: string
      - name: user_emails
        in: query
        description: Comma-separated user email addresses to filter by. When combined with user_ids, results are unioned (all matching users from either list are included).
        schema:
          type: string
      - name: scenario_ids
        in: query
        description: Comma-separated scenario IDs to filter by
        schema:
          type: string
      - name: program_ids
        in: query
        description: Comma-separated program IDs to filter by
        schema:
          type: string
      - name: status
        in: query
        description: Filter by one or more assignment statuses
        style: form
        explode: false
        schema:
          type: array
          items:
            type: string
            enum:
            - not_started
            - in_progress
            - completed
            - past_due
            - did_not_pass
          example:
          - completed
          - past_due
      - name: page
        in: query
        description: Page number (1-indexed)
        schema:
          type: integer
          default: 1
          minimum: 1
      - name: page_size
        in: query
        description: Number of results per page (max 100)
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: Paginated list of assignments
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Assignment'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
              example:
                data:
                - id: a1b2c3d4e5f6
                  user:
                    id: u1a2b3c4d5e6
                    email: jane@acme.com
                    first_name: Jane
                    last_name: Smith
                  scenario:
                    id: s1a2b3c4d5e6
                    name: Procurement Discovery
                    slug: procurement-discovery
                  status: completed
                  due_date: '2026-04-15T00:00:00Z'
                  best_score: 88
                  best_rank: gold
                  attempt_count: 3
                  attempt_min: 1
                  attempt_max: null
                  rank_min: silver
                  program: null
                  created_at: '2026-03-01T10:00:00Z'
                pagination:
                  page: 1
                  page_size: 50
                  total_count: 1
                  total_pages: 1
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /scenarios/{scenario_id}/analytics/summary:
    get:
      operationId: getScenarioAnalyticsSummary
      summary: Get scenario analytics summary
      description: 'Returns aggregate metrics for a scenario: participant count, total sessions,

        average best score and rank, average lift, total practice minutes, and average

        session duration. Accepts both UUID and slug for the scenario identifier.

        '
      tags:
      - Scenarios
      parameters:
      - name: scenario_id
        in: path
        required: true
        description: Scenario identifier (UUID or slug)
        schema:
          type: string
      - name: user_ids
        in: query
        description: Comma-separated user IDs to filter by. When combined with user_emails, results are unioned (all matching users from either list are included).
        schema:
          type: string
      - name: user_emails
        in: query
        description: Comma-separated user email addresses to filter by. When combined with user_ids, results are unioned (all matching users from either list are included).
        schema:
          type: string
      - name: group_ids
        in: query
        description: Comma-separated workspace group IDs to filter by
        schema:
          type: string
      - name: start_date
        in: query
        description: ISO 8601 datetime — only include sessions on or after this date
        schema:
          type: string
          format: date-time
      - name: end_date
        in: query
        description: ISO 8601 datetime — only include sessions on or before this date
        schema:
          type: string
          format: date-time
      - name: exclude_system_users
        in: query
        description: Exclude sessions from system users (emails ending in @exec.com). Default false.
        schema:
          type: boolean
          default: false
      responses:
        '200':
          description: Scenario analytics summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScenarioAnalyticsSummary'
              example:
                participant_count: 45
                total_sessions: 128
                average_best_score: 74.2
                average_best_rank: silver
                average_lift_percentage: 18.5
                total_practice_minutes: 742
                average_session_duration_seconds: 348
                score_distribution:
                - rank: gold
                  count: 12
                  percentage: 26.7
                - rank: silver
                  count: 18
                  percentage: 40
                - rank: bronze
                  count: 10
                  percentage: 22.2
                - rank: unranked
                  count: 5
                  percentage: 11.1
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /scenarios/{scenario_id}/analytics/participants:
    get:
      operationId: getScenarioAnalyticsParticipants
      summary: Get scenario participant analytics
      description: 'Returns a per-user performance table for a scenario with pagination and sorting.

        Shows each participant''s first score, best score, lift, rank, session count,

        and total practice duration.

        '
      tags:
      - Scenarios
      parameters:
      - name: scenario_id
        in: path
        required: true
        description: Scenario identifier (UUID or slug)
        schema:
          type: string
      - name: user_ids
        in: query
        description: Comma-separated user IDs to filter by. When combined with user_emails, results are unioned (all matching users from either list are included).
        schema:
          type: string
      - name: user_emails
        in: query
        description: Comma-separated user email addresses to filter by. When combined with user_ids, results are unioned (all matching users from either list are included).
        schema:
          type: string
      - name: group_ids
        in: query
        description: Comma-separated workspace group IDs to filter by
        schema:
          type: string
      - name: start_date
        in: query
        description: ISO 8601 datetime — only include sessions on or after this date
        schema:
          type: string
          format: date-time
      - name: end_date
        in: query
        description: ISO 8601 datetime — only include sessions on or before this date
        schema:
          type: string
          format: date-time
      - name: exclude_system_users
        in: query
        description: Exclude sessions from system users (emails ending in @exec.com). Default false.
        schema:
          type: boolean
          default: false
      - name: sorting
        in: query
        description: Sort field. Prefix with `-` for descending order.
        schema:
          type: string
          default: -best_score
          enum:
          - best_score
          - -best_score
          - first_score
          - -first_score
          - lift_percentage
          - -lift_percentage
          - total_duration_seconds
          - -total_duration_seconds
          - session_count
          - -session_count
      - name: page
        in: query
        description: Page number (1-indexed)
        schema:
          type: integer
          default: 1
          minimum: 1
      - name: page_size
        in: query
        description: Number of results per page (max 100)
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: Per-user participant analytics
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ScenarioParticipantEntry'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
              example:
                data:
                - user:
                    id: u1a2b3c4d5e6
                    email: jane@acme.com
                    first_name: Jane
                    last_name: Smith
                  session_count: 4
                  first_score: 55
                  first_rank: bronze
                  best_score: 88
                  best_rank: gold
                  lift_percentage: 33
                  total_duration_seconds: 1240
                pagination:
                  page: 1
                  page_size: 50
                  total_count: 1
                  total_pages: 1
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /scenarios:
    get:
      operationId: listScenarios
      summary: List scenarios
      description: 'Returns a paginated list of scenarios in the workspace.


        By default, returns all scenarios in the workspace (admin view).

        Use filters to narrow down results by owner, visibility, or access.

        '
      tags:
      - Scenarios
      parameters:
      - name: page
        in: query
        description: Page number (1-indexed)
        schema:
          type: integer
          default: 1
          minimum: 1
      - name: page_size
        in: query
        description: Number of results per page (max 100)
        schema:
          type: integer
          default: 50
          minimum: 1
          maximum: 100
      - name: owner_email
        in: query
        description: Filter by scenario owner's email address
        schema:
          type: string
          format: email
      - name: visible_to_email
        in: query
        description: Filter by who can access the scenario (checks owner, user shares, group shares, workspace shares)
        schema:
          type: string
          format: email
      - name: visibility
        in: query
        description: Filter by visibility scope
        schema:
          type: string
          enum:
          - private
          - workspace
      - name: include_archived
        in: query
        description: Include archived scenarios in results
        schema:
          type: boolean
          default: false
      - name: skill_ids
        in: query
        description: Comma-separated skill IDs to filter by
        schema:
          type: string
      - name: collection_ids
        in: query
        description: Comma-separated collection IDs to filter by
        schema:
          type: string
      - name: include
        in: query
        description: 'Comma-separated list of optional data to include.

          Available values: `skills` (list of skills evaluated by each scenario).

          '
        schema:
          type: string
          example: skills
      responses:
        '200':
          description: List of scenarios
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Scenario'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
              example:
                data:
                - id: s1c2e3n4a5r6
                  name: Discovery Call with IT Director
                  description: Practice handling objections from skeptical IT buyers
                  slug: discovery-call-it-director
                  url: https://acme-corp.app.exec.com/scenarios/discovery-call-it-director
                  difficulty: medium
                  context: The buyer is the VP of Engineering at a Series B fintech. They have an active RFP out for an observability tool and your competitor presented yesterday.
                  objective: 'Qualify the opportunity and book a follow-up meeting with the economic buyer.

                    ##### Outcomes to Avoid:

                    - Discounting before discovery

                    - Skipping the budget conversation

                    - Committing to a custom integration without scoping'
                  language: English
                  visibility: workspace
                  owner:
                    id: u7v8w9x0y1z2
                    email: jane@acme.com
                    first_name: Jane
                    last_name: Smith
                  created_at: '2024-01-15T10:30:00Z'
                  updated_at: '2024-02-01T14:20:00Z'
                pagination:
                  page: 1
                  page_size: 50
                  total_count: 125
                  total_pages: 3
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /scenarios/{scenario_id}/access:
    get:
      operationId: checkScenarioAccess
      summary: Check scenario access
      description: 'Check if a user has access to a specific scenario and what permission level they have.

        '
      tags:
      - Scenarios
      parameters:
      - name: scenario_id
        in: path
        required: true
        description: Scenario identifier
        schema:
          type: string
      - name: user_email
        in: query
        required: true
        description: Email of the user to check access for
        schema:
          type: string
          format: email
          example: jane@acme.com
      responses:
        '200':
          description: User's permission levels for the scenario
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScenarioAccessResponse'
              example:
                user_email: jane@acme.com
                scenario_id: s1c2e3n4a5r6
                permissions:
                  can_view: true
                  can_share: true
                  can_monitor: false
                  can_edit: false
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: grantScenarioAccess
      summary: Grant scenario access
      description: 'Grant a user access to a specific scenario with a specified permission level.

        '
      tags:
      - Scenarios
      parameters:
      - name: scenario_id
        in: path
        required: true
        description: Scenario identifier
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - user_email
              - permission_level
              properties:
                user_email:
                  type: string
                  format: email
                  description: Email of the user to grant access to
                permission_level:
                  type: string
                  enum:
                  - view
                  - share
                  - monitor
                  - edit
                  description: Permission level to grant
            example:
              user_email: jane@acme.com
              permission_level: edit
      responses:
        '200':
          description: Access granted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GrantAccessResponse'
              example:
                user_email: jane@acme.com
                scenario_id: s1c2e3n4a5r6
                permission_level: edit
                granted: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /scenarios/{scenario_id}/assignments:
    post:
      operationId: assignScenario
      summary: Assign scenario to user
      description: 'Assign a scenario to a user as a task or homework assignment.

        The user will receive notification of the assignment and can track their progress.

        '
      tags:
      - Scenarios
      parameters:
      - name: scenario_id
        in: path
        required: true
        description: Scenario identifier
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - user_email
              - due_date
              properties:
                user_email:
                  type: string
                  format: email
                  description: Email of the user to assign the scenario to
                due_date:
                  type: string
                  format: date-time
                  description: When the assignment is due (ISO 8601 format)
                assigner_email:
                  type: string
                  format: email
                  description: Email of the user creating the assignment (optional, used in notification emails)
                attempt_min:
                  type: integer
                  minimum: 1
                  description: Minimum number of attempts required
                attempt_max:
                  type: integer
                  minimum: 1
                  description: Maximum number of attempts allowed
                rank_min:
                  type: string
                  enum:
                  - gold
                  - silver
                  - bronze
                  description: Minimum rank required to complete
                custom_message:
                  type: string
                  description: Custom message to include with the assignment
            example:
              user_email: jane@acme.com
              due_date: '2024-03-15T17:00:00Z'
              assigner_email: manager@acme.com
              attempt_min: 1
              attempt_max: 5
              rank_min: silver
              custom_message: Please complete this discovery call practice by Friday
      responses:
        '200':
          description: Assignment created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Assignment'
              example:
                id: a1s2s3i4g5n6
                user:
                  id: u1a2b3c4d5e6
                  email: jane@acme.com
                  first_name: Jane
                  last_name: Smith
                scenario:
                  id: s1c2e3n4a5r6
                  name: Discovery Call
                  slug: discovery-call
                status: not_started
                due_date: '2024-03-15T17:00:00Z'
                best_score: null
                best_rank: null
                attempt_count: 0
                attempt_min: 1
                attempt_max: 5
                rank_min: silver
                program: null
                created_at: '2024-03-01T10:00:00Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
          description: Unique user identifier
        email:
          type: string
          format: email
          description: User's email address
        first_name:
          type: string
          description: User's first name
        last_name:
          type: string
          description: User's last name
    ValidationErrorDetail:
      type: object
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              description: Error category (e.g., "invalid_request")
            code:
              type: string
              description: Specific error code (e.g., "user_not_found")
            message:
              type: string
              description: Human-readable error message
    ScenarioParticipantEntry:
      type: object
      description: Per-user performance data for a scenario.
      properties:
        user:
          $ref: '#/components/schemas/User'
        session_count:
          type: integer
          description: Number of sessions the user completed
        first_score:
          type: number
          nullable: true
          description: Score from the user's first attempt
        first_rank:
          type: string
          nullable: true
          enum:
          - gold
          - silver
          - bronze
          - unranked
          description: Rank from the first attempt
        best_score:
          type: number
          nullable: true
          description: User's highest score
        best_rank:
          type: string
          nullable: true
          enum:
          - gold
          - silver
          - bronze
          - unranked
          description: Rank from the best score
        lift_percentage:
          type: number
          nullable: true
          description: Improvement from first to best score
        total_duration_seconds:
          type: number
          description: Total practice time in seconds
    Assignment:
      type: object
      description: A scenario assignment given to a user as a practice task.
      properties:
        id:
          type: string
          description: Unique assignment identifier
        user:
          $ref: '#/components/schemas/User'
        scenario:
          $ref: '#/components/schemas/ScenarioRef'
        status:
          type: string
          enum:
          - not_started
          - in_progress
          - completed
          - past_due
          - did_not_pass
          description: Current assignment status
        due_date:
          type: string
          format: date-time
          nullable: true
          description: When the assignment is due
        best_score:
          type: number
          nullable: true
          description: Highest score achieved on this assignment
        best_rank:
          type: string
          nullable: true
          enum:
          - gold
          - silver
          - bronze
          - unranked
          description: Rank from the best scoring attempt
        attempt_count:
          type: integer
          description: Number of completed attempts
        attempt_min:
          type: integer
          nullable: true
          description: Minimum attempts required
        attempt_max:
          type: integer
          nullable: true
          description: Maximum attempts allowed
        rank_min:
          type: string
          nullable: true
          enum:
          - gold
          - silver
          - bronze
          - unranked
          description: Minimum rank required to pass
        program:
          type: object
          nullable: true
          description: Program this assignment belongs to (null if standalone)
          properties:
            id:
              type: string
            name:
              type: string
        created_at:
          type: string
          format: date-time
    ScenarioAccessResponse:
      type: object
      properties:
        user_email:
          type: string
          format: email
          description: Email of the user checked
        scenario_id:
          type: string
          description: Scenario identifier
        permissions:
          type: object
          properties:
            can_view:
              type: boolean
              description: Whether the user can view the scenario
            can_share:
              type: boolean
              description: Whether the user can share the scenario
            can_monitor:
              type: boolean
              description: Whether the user can monitor sessions on this scenario
            can_edit:
              type: boolean
              description: Whether the user can edit the scenario
    SkillRef:
      type: object
      description: A compact skill reference for embedding in other responses.
      properties:
        id:
          type: string
          description: Unique skill identifier
        name:
          type: string
          description: Skill name
        slug:
          type: string
          description: URL-friendly skill identifier
    ScenarioAnalyticsSummary:
      type: object
      description: Aggregate analytics metrics for a scenario.
      properties:
        participant_count:
          type: integer
          description: Number of unique participants with graded sessions
        total_sessions:
          type: integer
          description: Total number of graded sessions
        average_best_score:
          type: number
          description: Average of each participant's best score (0-100)
        average_best_rank:
          type: string
          enum:
          - gold
          - silver
          - bronze
          - unranked
          description: Rank corresponding to the average best score
        average_lift_percentage:
          type: number
          description: Average improvement (best - first score) across participants
        total_practice_minutes:
          type: integer
          description: Total practice time across all sessions in minutes
        average_session_duration_seconds:
          type: number
          description: Average duration per session in seconds
        score_distribution:
          $ref: '#/components/schemas/ScenarioScoreDistribution'
    GrantAccessResponse:
      type: object
      properties:
        user_email:
          type: string
          format: email
          description: Email of the user granted access
        scenario_id:
          type: string
          description: Scenario identifier
        permission_level:
          type: string
          enum:
          - view
          - share
          - monitor
          - edit
          description: Permission level granted
        granted:
          type: boolean
          description: Whether the access was successfully granted
    Scenario:
      type: object
      properties:
        id:
          type: string
          description: Unique scenario identifier
        name:
          type: string
          description: Scenario name
        description:
          type: string
          nullable: true
          description: Short description of the scenario
        slug:
          type: string
          description: URL-friendly scenario identifier
        url:
          type: string
          format: uri
          description: Direct link to the scenario
        difficulty:
          type: string
          description: Scenario difficulty level
          enum:
          - easy
          - medium
          - hard
          - very_hard
          - custom
        context:
          type: string
          nullable: true
          description: 'The scenario''s context - background and setup information that frames

            the roleplay (e.g., the buyer''s company, current situation, recent

            events). Plain text, may contain newlines. May be null for scenarios

            that haven''t filled in this section.

            '
          example: The buyer is the VP of Engineering at a Series B fintech. They have an active RFP out for an observability tool and your competitor presented yesterday.
        objective:
          type: string
          nullable: true
          description: 'The learner''s objective for the scenario. The value is markdown and

            includes an embedded "Outcomes to Avoid" subsection separated by the

            delimiter `##### Outcomes to Avoid:`, followed by a bulleted list.

            Consumers who want the two pieces separately can split on that

            delimiter.

            '
          example: 'Qualify the opportunity and book a follow-up meeting with the economic buyer.

            ##### Outcomes to Avoid:

            - Discounting before discovery

            - Skipping the budget conversation

            - Committing to a custom integration without scoping

            '
        language:
          type: string
          description: Scenario language
        visibility:
          type: string
          description: Sharing scope of the scenario
          enum:
          - private
          - workspace
        owner:
          $ref: '#/components/schemas/User'
          nullable: true
          description: User who owns the scenario
        created_at:
          type: string
          format: date-time
          description: When the scenario was created
        updated_at:
          type: string
          format: date-time
          description: When the scenario was last updated
        skills:
          type: array
          nullable: true
          description: Skills evaluated by this scenario (only included when requested via `?include=skills`)
          items:
            $ref: '#/components/schemas/SkillRef'
    ScenarioScoreDistribution:
      type: array
      description: Rank distribution across participants based on best scores (Gold ≥90, Silver ≥75, Bronze ≥50, Unranked <50).
      items:
        type: object
        properties:
          rank:
            type: string
            enum:
            - gold
            - silver
            - bronze
            - unranked
            description: Performance rank
          count:
            type: integer
            description: Number of participants at this rank
          percentage:
            type: number
            description: Percentage of participants at this rank
    Pagination:
      type: object
      properties:
        page:
          type: integer
          description: Current page number
        page_size:
          type: integer
          description: Number of items per page
        total_count:
          type: integer
          description: Total number of items
        total_pages:
          type: integer
      

# --- truncated at 32 KB (33 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/exec/refs/heads/main/openapi/exec-scenarios-api-openapi.yml