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

# Invoke an athlete-scoped AI Assistant tool

> Invokes one of six Laravel-owned tools. Athlete identity is derived only from the signed X-Mogl-Turn-Token and is never accepted in the request body. Both gateway credentials are required. A valid invocation returns HTTP 200 for either a successful tool result or an expected typed domain error. get_portfolio supports bounded overview, count, list, and guidance actions, default, recent-hire, or pending-invitation ordering, and page sizes from 1 to 20; omitted actions retain legacy list behavior, while positive offsets require list. The newest pending invitation uses segment=invited, lifecycle=all, actions=[list], sort=invited_at_desc, and page_size=1. Proposal tools are review-only. propose_brand_draft accepts only natural brand-facing text; known internal reason, telemetry, tool, or routing namespaces return the HTTP-200 invalid_params domain envelope without persistence. propose_support accepts the underlying issue rather than a contact instruction; its optional deal ID is host-bound and reauthorized, and Laravel renders trusted athlete, Brand, Deal, and Deal ID text.



## OpenAPI

````yaml /storage/api-docs/api-docs.json post /internal/ai-assistant/tools/{tool}
openapi: 3.0.0
info:
  title: MOGL Core API
  description: >-
    MOGL Platform Core API — powering athlete NIL deals, brand partnerships,
    agent management, payments, messaging, and more.
     *
     * ## Authentication
     * - **JWT Bearer Token**: Most endpoints require a Bearer token obtained via `/api/login`.
     * - **Server-to-Server API Key**: Internal/lambda/cron endpoints use an `X-API-KEY` header.
     *
     * ## Rate Limiting
     * - Registration & login endpoints: 4–15 requests per minute
     * - Public/influencer endpoints: 200 requests per minute
     * - Authenticated endpoints: standard Laravel throttle
  version: 1.0.0
servers:
  - url: http://localhost/mogl/mogl-backend/api
    description: Local
  - url: https://dev-api.mogl.online/api
    description: Dev
  - url: https://staging-api.mogl.online/api
    description: Staging
  - url: https://api.mogl.online/api
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Authentication
    description: Login, registration, password reset
  - name: User Registration - Common
    description: Common user registration & email check
  - name: User Registration - Athlete
    description: Athlete registration & onboarding steps
  - name: User Registration - Partner
    description: Partner/Brand registration & onboarding steps
  - name: User Registration - Agent
    description: Agent registration & onboarding steps
  - name: User Registration - Fan
    description: Fan registration & onboarding steps
  - name: User Profile
    description: User profile management, settings, social media
  - name: Athlete
    description: 'Athlete-specific endpoints: search, details, availability'
  - name: Athlete - Availability Confirmation
    description: Post-hiring availability confirmation workflow
  - name: Athlete - NIL Feed
    description: Athlete NIL feed and partner search
  - name: Athlete - AI Assistant
    description: >-
      AI-powered job assistant for athletes — chat, conversation history, read
      state, and clarification drafts
  - name: Athlete - AI Waitlist
    description: AI Athlete Assistant waitlist status, social proof, and joining
  - name: Partner
    description: Partner/Brand-specific endpoints
  - name: Partner - External Job
    description: External job link & applicant management
  - name: Partner - Deliverable Report
    description: Deliverable detail reports for brands
  - name: Partner - Screening Questions
    description: Screening question reports
  - name: Partner - Contract Management
    description: Brand contract management with athletes
  - name: Partner - Content Library
    description: Brand content library for deliverable assets
  - name: Agent
    description: Agent profile, athlete management, contracts
  - name: Agent - Athletes
    description: Agent-athlete relationship management
  - name: Agent - Stripe
    description: Agent payment methods & billing via Stripe
  - name: Agent - Contracts
    description: Agent athlete contract management
  - name: Agent - Availability Confirmation
    description: Agent managing athlete job availability
  - name: Jobs
    description: Job/deal CRUD, search, invitations, hiring, deliverables
  - name: Deals
    description: Deal listing, my deals, bulk operations
  - name: Deal Folder
    description: >-
      Deal folder file workflow — uploads, replacements, approvals, revisions,
      comments. Accessible by athlete, partner/brand, agent, and iOS clients
      (per-action authorisation enforced server-side).
  - name: Deal Folder iOS API
    description: >-
      iOS-only direct-to-S3 multipart upload endpoints for deal folder files
      (initiate/complete for new uploads and replacements). Web clients should
      use the standard `Deal Folder` upload/replace endpoints instead.
  - name: Chat
    description: Messaging, chat contacts, notifications
  - name: Notifications
    description: Notification preferences, in-app notifications
  - name: Payments
    description: Stripe payments, payment history, cards, bulk pay
  - name: Subscription
    description: Brand subscription plans & management
  - name: Public Pages
    description: Public content endpoints (no auth required)
  - name: Public - Influencer/SEO
    description: Public influencer discovery, sitemaps, directories
  - name: Services
    description: Athlete service marketplace
  - name: iOS Device
    description: iOS device tokens, live activities
  - name: Onboarding Tutorial
    description: Onboarding tutorial progress
  - name: MOGL Rosters
    description: Roster management & display
  - name: Internal / Cron
    description: Server-to-server and cron job endpoints
  - name: Internal - AI Athlete Assistant Tools
    description: >-
      Dual-authenticated, athlete-scoped tool gateway used only by the AI
      service
  - name: Affiliate
    description: Athlete affiliate links & tracking
paths:
  /internal/ai-assistant/tools/{tool}:
    post:
      tags:
        - Internal - AI Athlete Assistant Tools
      summary: Invoke an athlete-scoped AI Assistant tool
      description: >-
        Invokes one of six Laravel-owned tools. Athlete identity is derived only
        from the signed X-Mogl-Turn-Token and is never accepted in the request
        body. Both gateway credentials are required. A valid invocation returns
        HTTP 200 for either a successful tool result or an expected typed domain
        error. get_portfolio supports bounded overview, count, list, and
        guidance actions, default, recent-hire, or pending-invitation ordering,
        and page sizes from 1 to 20; omitted actions retain legacy list
        behavior, while positive offsets require list. The newest pending
        invitation uses segment=invited, lifecycle=all, actions=[list],
        sort=invited_at_desc, and page_size=1. Proposal tools are review-only.
        propose_brand_draft accepts only natural brand-facing text; known
        internal reason, telemetry, tool, or routing namespaces return the
        HTTP-200 invalid_params domain envelope without persistence.
        propose_support accepts the underlying issue rather than a contact
        instruction; its optional deal ID is host-bound and reauthorized, and
        Laravel renders trusted athlete, Brand, Deal, and Deal ID text.
      operationId: aiAssistantToolInvoke
      parameters:
        - name: tool
          in: path
          description: >-
            Closed Laravel tool name. search_kb is Python-local and is not
            available through this route.
          required: true
          schema:
            type: string
            enum:
              - get_portfolio
              - search_deals
              - get_deal
              - get_timeline
              - propose_brand_draft
              - propose_support
            example: get_portfolio
      requestBody:
        description: >-
          Input must match the schema for the selected path tool. Unknown
          properties are rejected; athlete identity is transport-owned.
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/AthleteAiToolGetPortfolioInput'
                - $ref: '#/components/schemas/AthleteAiToolSearchDealsInput'
                - $ref: '#/components/schemas/AthleteAiToolDealLookupInput'
                - $ref: '#/components/schemas/AthleteAiToolProposeBrandDraftInput'
                - $ref: '#/components/schemas/AthleteAiToolProposeSupportInput'
            examples:
              getPortfolio:
                summary: Action-aware portfolio query
                value:
                  segment: awaiting_payment
                  lifecycle: all
                  actions:
                    - count
                    - list
                  sort: default
                  page_size: 3
                  referenced_count: 3
                  offset: 0
              searchDeals:
                summary: Authorized deal search
                value:
                  query: summer campaign
              getDealOrTimeline:
                summary: Deal or timeline lookup
                value:
                  deal_id: 2833
                  deal_type: job
              proposeBrandDraft:
                summary: Natural approval-required brand draft
                value:
                  deal_id: 2760
                  draft_text: >-
                    Hey Wonolo, I don't see any instructions about footwear for
                    the Instagram Reel. Is it okay if I wear sandals in the
                    video?
              proposeSupportSelectedDeal:
                summary: Review-only selected-deal support action
                value:
                  summary: >-
                    The athlete wants to know whether a crop top is acceptable
                    for the video and reports that there has been no response
                    yet.
                  deal_id: 2833
              proposeSupportNoDeal:
                summary: Review-only true no-deal support action
                value:
                  summary: The athlete cannot access Deal Studio.
      responses:
        '200':
          description: >-
            Tool success or expected typed domain error. Inspect the ok
            discriminator.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: >-
                      #/components/schemas/AthleteAiToolGetPortfolioSuccessEnvelope
                  - $ref: >-
                      #/components/schemas/AthleteAiToolSearchDealsSuccessEnvelope
                  - $ref: '#/components/schemas/AthleteAiToolGetDealSuccessEnvelope'
                  - $ref: >-
                      #/components/schemas/AthleteAiToolGetTimelineSuccessEnvelope
                  - $ref: >-
                      #/components/schemas/AthleteAiToolProposeBrandDraftSuccessEnvelope
                  - $ref: >-
                      #/components/schemas/AthleteAiToolProposeSupportSuccessEnvelope
                  - $ref: '#/components/schemas/AthleteAiToolErrorEnvelope'
              examples:
                toolSuccess:
                  summary: Successful portfolio result
                  value:
                    ok: true
                    result:
                      lifecycle_mode: all
                      requested_segment: awaiting_payment
                      requested_actions:
                        - list
                      response_mode: detail
                      offset: 0
                      requested_sort: default
                      page_size: 20
                      ordering: summary_priority_then_due_date_then_hired_at_then_job_id
                      referenced_count: null
                      summary_counts:
                        all: 1
                        active: 0
                        in_progress: 0
                        submitted: 0
                        resubmit_needed: 0
                        awaiting_payment: 1
                        applied: 0
                        invited: 0
                        paid: 0
                        voided: 0
                        cancelled: 0
                        rejected: 0
                      deals:
                        - job_id: 2833
                          deal_type: job
                          title: Summer Hydration Campaign
                          brand_name: Acme Athletics
                          lifecycle_state: current
                          summary_state: awaiting_payment
                          next_due_at_display: Aug 28, 2026
                          next_due_deliverable: Instagram Reel
                          next_action: Submit the Instagram Reel for brand review.
                          compensation_summary: $500.00
                          source_ids:
                            - job:2833
                            - timeline:9121
                      total_count: 1
                      returned_count: 1
                      truncated: false
                      count_mismatch: false
                      continuation_cursor: null
                      source_ids:
                        - portfolio:all:awaiting_payment
                        - job:2833
                        - timeline:9121
                selectedDealSupportSuccess:
                  summary: Successful selected-deal support proposal
                  value:
                    ok: true
                    result:
                      support_action:
                        type: mailto
                        label: Review email to MOGL Support
                        url: >-
                          mailto:athlete-support@mogl.online?subject=Help%20from%20the%20AI%20Athlete%20Assistant%20needed
                      source_ids:
                        - job:2833
                noDealSupportSuccess:
                  summary: Successful true no-deal support proposal
                  value:
                    ok: true
                    result:
                      support_action:
                        type: mailto
                        label: Review email to MOGL Support
                        url: >-
                          mailto:athlete-support@mogl.online?subject=Help%20from%20the%20AI%20Athlete%20Assistant%20needed
                      source_ids:
                        - athlete_profile:42
                domainError:
                  summary: Expected tool-domain error
                  value:
                    ok: false
                    error:
                      code: not_found
                      message: The requested deal was not found.
                      suggestion: >-
                        Use search_deals to find an authorized deal, then retry
                        with its job_id.
        '401':
          description: Missing or invalid X-API-KEY or X-Mogl-Turn-Token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AthleteAiToolHttpError'
              example:
                message: Unauthenticated.
        '422':
          description: Unknown tool name or input that cannot be normalized and validated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AthleteAiToolErrorEnvelope'
              example:
                ok: false
                error:
                  code: invalid_params
                  message: The tool input is invalid.
                  suggestion: Correct the tool name or parameters and retry.
        '503':
          description: Unexpected gateway failure.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AthleteAiToolErrorEnvelope'
              example:
                ok: false
                error:
                  code: unavailable
                  message: The tool gateway is temporarily unavailable.
                  suggestion: >-
                    Retry the tool call once, then answer from already gathered
                    evidence.
      security:
        - serverToServerApiKey: []
          aiAssistantTurnToken: []
components:
  schemas:
    AthleteAiToolGetPortfolioInput:
      description: >-
        Normalized portfolio request. Omitted actions preserve the legacy
        effective default [list]. A positive offset is valid only when the
        effective action set includes list.
      properties:
        segment:
          type: string
          default: all
          enum:
            - all
            - active
            - work_remaining
            - in_progress
            - submitted
            - resubmit_needed
            - awaiting_payment
            - applied
            - invited
            - paid
            - voided
            - cancelled
            - rejected
          example: work_remaining
        lifecycle:
          type: string
          default: all
          enum:
            - all
            - current
            - historical
          example: all
        sort:
          description: >-
            Bounded row sort. hired_at_desc is reserved for explicit recent-hire
            intent with lifecycle=current, segment=all, and page_size=1.
            invited_at_desc is reserved for the newest pending invitation
            (segment=invited, lifecycle=all, page_size=1).
          type: string
          default: default
          enum:
            - default
            - hired_at_desc
            - invited_at_desc
          example: hired_at_desc
        page_size:
          description: Maximum number of authorized rows returned for a list action.
          type: integer
          default: 20
          maximum: 20
          minimum: 1
          example: 1
        offset:
          description: >-
            Backend-order offset. Positive offsets are continuation pages and
            require the effective list action.
          type: integer
          default: 0
          maximum: 10000
          minimum: 0
          example: 0
        actions:
          description: >-
            Requested deterministic output actions. The bounded loop sends these
            explicitly; omission retains legacy list behavior.
          type: array
          items:
            type: string
            enum:
              - overview
              - count
              - list
              - guidance
          default:
            - list
          maxItems: 4
          minItems: 1
          uniqueItems: true
          example:
            - overview
            - count
        referenced_count:
          description: >-
            Optional trusted prior count used only for drift detection; it never
            limits current rows.
          type: integer
          maximum: 10000
          minimum: 0
          example: 3
      type: object
      additionalProperties: false
    AthleteAiToolSearchDealsInput:
      required:
        - query
      properties:
        query:
          type: string
          maxLength: 200
          minLength: 1
          example: summer campaign
      type: object
      additionalProperties: false
    AthleteAiToolDealLookupInput:
      required:
        - deal_id
      properties:
        deal_id:
          type: integer
          minimum: 1
          example: 2833
        deal_type:
          type: string
          default: job
          enum:
            - job
            - fan_req
          example: job
      type: object
      additionalProperties: false
    AthleteAiToolProposeBrandDraftInput:
      required:
        - deal_id
        - draft_text
      properties:
        deal_id:
          type: integer
          minimum: 1
          example: 2833
        draft_text:
          description: >-
            Natural brand-facing text written for athlete review. Internal
            reason codes, telemetry keys, tool names, and routing labels such as
            permission:, missing:, context:, and reason: are invalid.
          type: string
          maxLength: 1000
          minLength: 1
          example: >-
            Hey Wonolo, I don't see any instructions about footwear for the
            Instagram Reel. Is it okay if I wear sandals in the video?
      type: object
      additionalProperties: false
    AthleteAiToolProposeSupportInput:
      description: >-
        Review-only MOGL Support proposal input. The Assistant supplies the
        unresolved issue; Laravel owns authorization and final mailto metadata.
      required:
        - summary
      properties:
        summary:
          description: >-
            One or two concise issue sentences for a human support
            representative. Excludes contact-support instructions, links,
            contact information, internal AI terms, and untrusted IDs.
          type: string
          maxLength: 500
          minLength: 1
          example: >-
            The athlete wants to know whether a crop top is acceptable for the
            video and reports that there has been no response yet.
        deal_id:
          description: >-
            Optional standard job ID bound by trusted host routing and
            reauthorized by Laravel; never sourced from athlete or model prose.
          type: integer
          minimum: 1
          example: 2833
      type: object
      additionalProperties: false
    AthleteAiToolGetPortfolioSuccessEnvelope:
      required:
        - ok
        - result
      properties:
        ok:
          type: boolean
          enum:
            - true
          example: true
        result:
          $ref: '#/components/schemas/AthleteAiToolGetPortfolioResult'
      type: object
      additionalProperties: false
    AthleteAiToolSearchDealsSuccessEnvelope:
      required:
        - ok
        - result
      properties:
        ok:
          type: boolean
          enum:
            - true
          example: true
        result:
          $ref: '#/components/schemas/AthleteAiToolSearchDealsResult'
      type: object
      additionalProperties: false
    AthleteAiToolGetDealSuccessEnvelope:
      required:
        - ok
        - result
      properties:
        ok:
          type: boolean
          enum:
            - true
          example: true
        result:
          $ref: '#/components/schemas/AthleteAiToolGetDealResult'
      type: object
      additionalProperties: false
    AthleteAiToolGetTimelineSuccessEnvelope:
      required:
        - ok
        - result
      properties:
        ok:
          type: boolean
          enum:
            - true
          example: true
        result:
          $ref: '#/components/schemas/AthleteAiToolGetTimelineResult'
      type: object
      additionalProperties: false
    AthleteAiToolProposeBrandDraftSuccessEnvelope:
      required:
        - ok
        - result
      properties:
        ok:
          type: boolean
          enum:
            - true
          example: true
        result:
          $ref: '#/components/schemas/AthleteAiToolProposeBrandDraftResult'
      type: object
      additionalProperties: false
    AthleteAiToolProposeSupportSuccessEnvelope:
      required:
        - ok
        - result
      properties:
        ok:
          type: boolean
          enum:
            - true
          example: true
        result:
          $ref: '#/components/schemas/AthleteAiToolProposeSupportResult'
      type: object
      additionalProperties: false
    AthleteAiToolErrorEnvelope:
      required:
        - ok
        - error
      properties:
        ok:
          type: boolean
          enum:
            - false
          example: false
        error:
          $ref: '#/components/schemas/AthleteAiToolError'
      type: object
      additionalProperties: false
    AthleteAiToolHttpError:
      required:
        - message
      properties:
        message:
          type: string
          example: Service unavailable.
      type: object
      additionalProperties: false
    AthleteAiToolGetPortfolioResult:
      description: >-
        Strict normalized result. The expanded required metadata is an in-place
        v1 coordinated producer/consumer cutover.
      required:
        - lifecycle_mode
        - requested_segment
        - requested_actions
        - response_mode
        - offset
        - ordering
        - referenced_count
        - summary_counts
        - deals
        - total_count
        - returned_count
        - truncated
        - count_mismatch
        - continuation_cursor
        - source_ids
      properties:
        lifecycle_mode:
          description: Backend-normalized lifecycle scope.
          type: string
          enum:
            - all
            - current
            - historical
          example: all
        requested_segment:
          description: >-
            Backend-normalized segment. work_remaining is athlete work. active
            is deprecated compatibility.
          type: string
          enum:
            - all
            - active
            - work_remaining
            - in_progress
            - submitted
            - resubmit_needed
            - awaiting_payment
            - applied
            - invited
            - paid
            - voided
            - cancelled
            - rejected
          example: work_remaining
        requested_actions:
          description: >-
            Normalized actions in deterministic overview, count, list, guidance
            composition order.
          type: array
          items:
            type: string
            enum:
              - overview
              - count
              - list
              - guidance
          maxItems: 4
          minItems: 1
          uniqueItems: true
          example:
            - list
        response_mode:
          description: >-
            Detail exactly when requested_actions contains list; otherwise
            summary.
          type: string
          enum:
            - summary
            - detail
          example: detail
        offset:
          description: Applied backend-order offset. Positive values require list.
          type: integer
          maximum: 10000
          minimum: 0
          example: 0
        requested_sort:
          description: >-
            Applied bounded sort. Optional during rolling compatibility;
            omission means default.
          type: string
          default: default
          enum:
            - default
            - hired_at_desc
            - invited_at_desc
          example: hired_at_desc
        page_size:
          description: >-
            Applied page size. Optional during rolling compatibility; omission
            means 20.
          type: integer
          default: 20
          maximum: 20
          minimum: 1
          example: 1
        has_invite_dates:
          description: >-
            True when at least one pending invitation in the requested
            invite-recency result has a usable invitation instant. Returned only
            for requested_sort=invited_at_desc.
          type: boolean
          example: true
        ordering:
          type: string
          enum:
            - summary_priority_then_due_date_then_hired_at_then_job_id
            - hired_at_desc_then_job_id
            - invited_at_desc_then_job_id
          example: hired_at_desc_then_job_id
        referenced_count:
          description: Trusted prior count for an anchored follow-up, or null.
          type: integer
          maximum: 10000
          minimum: 0
          example: null
          nullable: true
        summary_counts:
          $ref: '#/components/schemas/AthleteAiToolPortfolioSummaryCounts'
        deals:
          description: >-
            Backend-ordered rows for list; empty for action sets without list.
            Lists with total_count at most three may include due-date,
            next-deliverable, and next-action detail; lists with total_count
            four or greater omit those fields. hired_at_display is limited to
            hired_at_desc results. invited_at_display is limited to
            invited_at_desc results.
          type: array
          items:
            $ref: '#/components/schemas/AthleteAiToolStandardDealRow'
          maxItems: 20
        total_count:
          description: Current canonical count for requested_segment, never page length.
          type: integer
          minimum: 0
          example: 1
        returned_count:
          description: Number of returned deal rows.
          type: integer
          maximum: 20
          minimum: 0
          example: 1
        truncated:
          description: Whether more backend-ordered list rows remain.
          type: boolean
          example: false
        count_mismatch:
          description: >-
            True exactly when non-null referenced_count differs from
            total_count.
          type: boolean
          example: false
        continuation_cursor:
          description: Opaque cursor only for a truncated list result; otherwise null.
          type: string
          maxLength: 512
          example: null
          nullable: true
        source_ids:
          description: >-
            Authorized grounding sources. Summary-only actions retain an
            aggregate portfolio source.
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
          example:
            - portfolio:all:awaiting_payment
            - job:2833
            - timeline:9121
      type: object
      additionalProperties: false
    AthleteAiToolSearchDealsResult:
      required:
        - matches
        - total_matches
        - multiple_matches
        - source_ids
      properties:
        matches:
          type: array
          items:
            $ref: '#/components/schemas/AthleteAiToolStandardDealRow'
          maxItems: 20
        total_matches:
          type: integer
          minimum: 0
          example: 2
        multiple_matches:
          type: boolean
          example: true
        source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
          example:
            - job:2833
            - job:3014
      type: object
      additionalProperties: false
    AthleteAiToolGetDealResult:
      required:
        - deal_id
        - deal_type
        - title
        - brand
        - status
        - deliverables
        - compensation
        - deadline
        - criteria
        - documents
        - milestones_metadata
        - source_ids
      properties:
        deal_id:
          type: integer
          minimum: 1
          example: 2833
        deal_type:
          type: string
          enum:
            - job
            - fan_req
          example: job
        title:
          type: string
          maxLength: 200
          example: Summer Hydration Campaign
        brand:
          type: string
          maxLength: 200
          example: Acme Athletics
        status:
          type: string
          maxLength: 80
          example: Payment Processing
        athlete_relationship_state:
          description: >-
            Trusted mapping application status. Invited is not applied. Neither
            invited nor applied is active. Omitted for fan requests and unknown
            statuses.
          type: string
          enum:
            - hired
            - applied
            - invited
            - rejected
            - cancelled
          example: hired
        job_description:
          description: >-
            Optional sanitized plain-text job brief; omitted when absent.
            Literal comparison text such as <24 hours remains intact while
            actual markup is removed.
          type: string
          maxLength: 4000
          example: >-
            Create authentic training content featuring the hydration product
            and follow the approved campaign requirements.
        deliverables:
          type: array
          items:
            type: string
            maxLength: 1000
          maxItems: 20
        compensation:
          type: string
          maxLength: 500
          example: $500.00
        deadline:
          type: string
          maxLength: 120
          example: '2026-08-28'
        criteria:
          properties:
            sports:
              type: string
              maxLength: 500
              example: Women's Soccer
            universities:
              type: string
              maxLength: 500
              example: Columbia University
            gender:
              type: string
              maxLength: 64
              example: Female
            division:
              type: string
              maxLength: 64
            conference:
              type: string
              maxLength: 200
            location:
              type: string
              maxLength: 255
            follower_ranges:
              properties:
                instagram:
                  $ref: '#/components/schemas/AthleteAiToolFollowerRange'
                tiktok:
                  $ref: '#/components/schemas/AthleteAiToolFollowerRange'
                x:
                  $ref: '#/components/schemas/AthleteAiToolFollowerRange'
              type: object
              additionalProperties: false
          type: object
          nullable: true
          additionalProperties: false
        documents:
          type: array
          items:
            $ref: '#/components/schemas/AthleteAiToolDocument'
          maxItems: 20
        milestones_metadata:
          type: array
          items:
            $ref: '#/components/schemas/AthleteAiToolMilestoneMetadata'
          maxItems: 20
        source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
      type: object
      additionalProperties: false
    AthleteAiToolGetTimelineResult:
      required:
        - deal_id
        - deal_type
        - title
        - brand
        - status
        - deliverables
        - milestones_metadata
        - source_ids
      properties:
        deal_id:
          type: integer
          minimum: 1
          example: 2833
        deal_type:
          type: string
          enum:
            - job
            - fan_req
          example: job
        title:
          type: string
          maxLength: 200
          example: Summer Hydration Campaign
        brand:
          type: string
          maxLength: 200
          example: Acme Athletics
        status:
          type: string
          maxLength: 80
          example: Hired
        athlete_relationship_state:
          description: >-
            Trusted mapping application status. Invited is not applied. Neither
            invited nor applied is active. Omitted for fan requests and unknown
            statuses.
          type: string
          enum:
            - hired
            - applied
            - invited
            - rejected
            - cancelled
          example: hired
        deliverables:
          type: array
          items:
            $ref: '#/components/schemas/AthleteAiToolTimelineDeliverable'
          maxItems: 20
        milestones_metadata:
          type: array
          items:
            $ref: '#/components/schemas/AthleteAiToolMilestoneMetadata'
          maxItems: 20
        source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
      type: object
      additionalProperties: false
    AthleteAiToolProposeBrandDraftResult:
      required:
        - draft_id
        - athlete_snippet
        - brand_id
        - connection_id
        - approval_required
        - draft_only
        - source_ids
      properties:
        draft_id:
          type: integer
          minimum: 1
          example: 81
        athlete_snippet:
          type: string
          maxLength: 120
          minLength: 1
          example: >-
            Could you confirm whether the Instagram Reel should include a spoken
            product mention?
        brand_id:
          type: integer
          minimum: 1
          example: 404
        connection_id:
          type: integer
          minimum: 1
          example: 912
        approval_required:
          type: boolean
          enum:
            - true
          example: true
        draft_only:
          type: boolean
          enum:
            - true
          example: true
        source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
      type: object
      additionalProperties: false
    AthleteAiToolProposeSupportResult:
      description: >-
        Review-only action. Selected-deal success has exact job:{id} provenance;
        true no-deal success has athlete-profile provenance. Brand, Deal, Deal
        ID, and athlete identity are rendered inside the mailto from trusted
        Laravel records.
      required:
        - support_action
        - source_ids
      properties:
        support_action:
          $ref: '#/components/schemas/AthleteAiToolSupportAction'
        source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
          example:
            - job:2833
      type: object
      additionalProperties: false
    AthleteAiToolError:
      required:
        - code
        - message
        - suggestion
      properties:
        code:
          type: string
          enum:
            - not_found
            - invalid_params
            - fan_deal_not_allowed
            - draft_not_allowed
            - unavailable
            - budget_exceeded
          example: not_found
        message:
          type: string
          maxLength: 500
          minLength: 1
          example: The requested deal was not found.
        suggestion:
          type: string
          maxLength: 500
          minLength: 1
          example: >-
            Use search_deals to find an authorized deal, then retry with its
            job_id.
      type: object
      additionalProperties: false
    AthleteAiToolPortfolioSummaryCounts:
      required:
        - all
        - active
        - work_remaining
        - in_progress
        - submitted
        - resubmit_needed
        - awaiting_payment
        - applied
        - invited
        - paid
        - voided
        - cancelled
        - rejected
      properties:
        all:
          type: integer
          minimum: 0
          example: 6
        active:
          description: >-
            Deprecated compatibility count. Still in_progress + submitted +
            resubmit_needed.
          type: integer
          minimum: 0
          example: 3
        work_remaining:
          description: Athlete work remaining. Equals in_progress + resubmit_needed.
          type: integer
          minimum: 0
          example: 2
        in_progress:
          type: integer
          minimum: 0
          example: 1
        submitted:
          type: integer
          minimum: 0
          example: 1
        resubmit_needed:
          type: integer
          minimum: 0
          example: 1
        awaiting_payment:
          type: integer
          minimum: 0
          example: 1
        applied:
          type: integer
          minimum: 0
          example: 0
        invited:
          type: integer
          minimum: 0
          example: 0
        paid:
          type: integer
          minimum: 0
          example: 1
        voided:
          description: >-
            Exclusive count of fully voided deals. Partial-void deals keep their
            live primary state.
          type: integer
          minimum: 0
          example: 1
        cancelled:
          type: integer
          minimum: 0
          example: 0
        rejected:
          type: integer
          minimum: 0
          example: 0
      type: object
      additionalProperties: false
    AthleteAiToolStandardDealRow:
      required:
        - job_id
        - deal_type
        - title
        - brand_name
        - lifecycle_state
        - summary_state
        - source_ids
      properties:
        job_id:
          type: integer
          minimum: 1
          example: 2833
        deal_type:
          type: string
          enum:
            - job
          example: job
        title:
          type: string
          maxLength: 200
          example: Summer Hydration Campaign
        brand_name:
          type: string
          maxLength: 200
          example: Acme Athletics
        lifecycle_state:
          type: string
          maxLength: 64
          example: current
        summary_state:
          type: string
          enum:
            - in_progress
            - submitted
            - resubmit_needed
            - awaiting_payment
            - applied
            - invited
            - paid
            - voided
            - voided_deliverable
            - cancelled
            - rejected
          example: awaiting_payment
        athlete_relationship_state:
          description: >-
            Trusted mapping application status. Invited is not applied. Neither
            invited nor applied is active. Omitted for fan requests and unknown
            statuses.
          type: string
          enum:
            - hired
            - applied
            - invited
            - rejected
            - cancelled
          example: hired
        next_due_at_display:
          type: string
          maxLength: 120
          example: Aug 28, 2026
        next_due_deliverable:
          description: >-
            Optional athlete-facing next-deliverable name for small expanded
            portfolio lists; the display due date remains in
            next_due_at_display.
          type: string
          maxLength: 300
          example: Instagram Reel
        next_action:
          description: >-
            Optional athlete-facing next step for small expanded portfolio
            lists.
          type: string
          maxLength: 240
          example: Submit the Instagram Reel for brand review.
        hired_at_display:
          description: >-
            Optional athlete-facing hire date, returned only for rows ordered by
            hired_at_desc. The backend uses the athlete's validated IANA
            timezone name and ignores an optional stored abbreviation suffix.
          type: string
          maxLength: 120
          example: Aug 24, 2026
        invited_at_display:
          description: >-
            Optional athlete-facing invitation date, returned only for rows
            ordered by invited_at_desc.
          type: string
          maxLength: 120
          example: Aug 25, 2026
        compensation_summary:
          type: string
          maxLength: 240
          example: $500.00
        void_state:
          description: >-
            Secondary void condition. none has no voided deliverables. partial
            keeps the live primary state. total is used only with
            summary_state=voided.
          type: string
          enum:
            - none
            - partial
            - total
          example: none
        voided_deliverable_count:
          type: integer
          minimum: 0
          example: 0
        voided_source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
          example: []
        status_inconsistent:
          description: >-
            True when a parent Voided mapping conflicts with a live child
            deliverable.
          type: boolean
          example: false
        source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
          example:
            - job:2833
            - timeline:9121
      type: object
      additionalProperties: false
    AthleteAiToolFollowerRange:
      minProperties: 1
      properties:
        min:
          type: integer
          minimum: 0
          example: 5000
        max:
          type: integer
          minimum: 0
          example: 250000
      type: object
      additionalProperties: false
    AthleteAiToolDocument:
      oneOf:
        - $ref: '#/components/schemas/AthleteAiToolJobDocument'
        - $ref: '#/components/schemas/AthleteAiToolFanDocument'
    AthleteAiToolMilestoneMetadata:
      required:
        - deliverable_index
        - milestone_id
        - name
        - timeline_rel_id
        - timeline_source_id
        - deliverable_status
        - is_paid
        - resubmit_needed
        - is_voided
        - voided_date
      properties:
        deliverable_index:
          type: integer
          minimum: 0
          example: 0
        milestone_id:
          type: integer
          minimum: 1
          example: 7310
        name:
          type: string
          maxLength: 300
          example: Product demo
          nullable: true
        description:
          description: >-
            Optional sanitized plain-text milestone instructions; omitted when
            absent.
          type: string
          maxLength: 1000
          example: Show the product during training.
        timeline_rel_id:
          type: integer
          minimum: 1
          example: 9121
          nullable: true
        timeline_source_id:
          type: string
          example: timeline:9121
          nullable: true
        deliverable_status:
          type: string
          maxLength: 80
          example: In-Progress
          nullable: true
        is_paid:
          description: Null when no athlete timeline row exists.
          type: string
          maxLength: 32
          example: '0'
          nullable: true
        resubmit_needed:
          description: Null when no athlete timeline row exists.
          type: boolean
          example: false
          nullable: true
        is_voided:
          description: Null when no athlete timeline row exists.
          type: boolean
          example: false
          nullable: true
        voided_date:
          type: string
          maxLength: 64
          example: null
          nullable: true
      type: object
      additionalProperties: false
    AthleteAiToolTimelineDeliverable:
      required:
        - deliverable_index
        - milestone_id
        - name
        - status
        - due_at_display
        - is_voided
        - source_ids
      properties:
        deliverable_index:
          type: integer
          minimum: 0
          example: 0
        milestone_id:
          type: integer
          minimum: 1
          example: 7310
          nullable: true
        timeline_rel_id:
          type: integer
          minimum: 1
          example: 9121
          nullable: true
        name:
          type: string
          maxLength: 300
          example: Product demo
        description:
          description: >-
            Optional sanitized plain-text milestone instructions; omitted when
            absent.
          type: string
          maxLength: 1000
          example: Show the product during training.
        deliverable_type:
          type: string
          maxLength: 120
          example: Instagram Reel
          nullable: true
        platform:
          type: string
          maxLength: 80
          example: Instagram
          nullable: true
        status:
          type: string
          maxLength: 80
          example: In-Progress
        due_at_display:
          type: string
          maxLength: 120
          example: Aug 28, 2026
        is_voided:
          type: boolean
          example: false
        voided_at_display:
          type: string
          maxLength: 120
          example: null
          nullable: true
        voiding_note:
          type: string
          maxLength: 500
          example: null
          nullable: true
        source_ids:
          type: array
          items:
            type: string
          maxItems: 500
          uniqueItems: true
          example:
            - milestone:7310
            - timeline:9121
      type: object
      additionalProperties: false
    AthleteAiToolSupportAction:
      required:
        - type
        - label
        - url
      properties:
        type:
          type: string
          enum:
            - mailto
          example: mailto
        label:
          type: string
          maxLength: 120
          minLength: 1
          example: Review email to MOGL Support
        url:
          type: string
          format: uri
          maxLength: 4096
          pattern: '^mailto:'
          example: >-
            mailto:athlete-support@mogl.online?subject=AI%20Athlete%20Assistant%20help
      type: object
      additionalProperties: false
    AthleteAiToolJobDocument:
      required:
        - id
        - type
        - file
      properties:
        id:
          type: integer
          minimum: 1
          example: 441
        type:
          type: string
          enum:
            - title
            - details
            - deal_folder_file
          example: details
        file:
          type: string
          maxLength: 2048
          example: storage/images/documents/summer-hydration-brief.pdf
        file_name:
          type: string
          maxLength: 255
        mime_type:
          type: string
          maxLength: 127
      type: object
      additionalProperties: false
    AthleteAiToolFanDocument:
      required:
        - type
        - name
      properties:
        type:
          type: string
          enum:
            - fan_submitted_content
          example: fan_submitted_content
        name:
          type: string
          maxLength: 255
          example: Signed football video
      type: object
      additionalProperties: false
  securitySchemes:
    bearerAuth:
      type: http
      description: >-
        JWT Bearer token authentication. Use the /api/login endpoint to obtain a
        token.
      scheme: bearer
      bearerFormat: JWT
    serverToServerApiKey:
      type: apiKey
      description: Server-to-Server API Key for internal/lambda/cron calls
      name: X-API-KEY
      in: header
    aiAssistantTurnToken:
      type: apiKey
      description: >-
        Signed, short-lived Athlete Assistant turn token. Required together with
        X-API-KEY; athlete identity is derived from this token and never from
        tool input.
      name: X-Mogl-Turn-Token
      in: header

````