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

# Start Marketing Agent setup

> <Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Starts the Marketing Agent's setup for an app. The agent reads the app and drafts marketing channels and KPIs for you to review.

The first run in a workspace also creates the workspace's Marketing Agent, a Superagent that everyone in the workspace shares.

The work runs in the background after the call returns. Poll [Get Marketing Agent state](/api-reference/get-marketing-agent-state) until `status` is `ready` or `error`. If `competitor_scan_status` is `running`, keep polling until it is no longer `running`. Setup then waits at a `setup_stage` of `channels`. Approve each step with [Answer Marketing Agent setup step](/api-reference/answer-marketing-agent-setup-step), or ask for changes with [Send Marketing Agent message](/api-reference/send-marketing-agent-message).

While the scan is running, or once setup is past it, the call returns the current state and starts nothing. After a failed scan it starts the scan again, which is a new charged run.

To retry safely, send an `Idempotency-Key` header. A retry with the same key within 24 hours returns the current state and starts nothing, even if the first scan failed.

Each run is a Superagent turn, charged to the app's workspace in message credits based on the tokens it uses. A run can take several minutes and is stopped after 15. If the workspace is out of credits the run doesn't start, and `last_error` says so.

This is limited to 120 requests a minute per app for each workspace's personal API keys, so every key in a workspace shares one allowance, across every Marketing Agent endpoint. Some workspaces have a different limit.

<Note>This endpoint accepts a personal API key belonging to a user with editor access to the app and an editor role in its workspace. Read-only keys and workspace API keys are refused.</Note>

<Warning>The response includes fields beyond the ones documented here. Don't rely on undocumented response fields, as they can change at any time.</Warning>



## OpenAPI

````yaml /developers/references/app-management/app-management-openapi.json post /api/apps/{app_id}/cmo/setup/start
openapi: 3.1.0
info:
  title: Base44 App Management API
  version: 1.0.0
servers:
  - url: https://app.base44.com
security:
  - PersonalAccessTokenAuth: []
paths:
  /api/apps/{app_id}/cmo/setup/start:
    post:
      summary: Start Marketing Agent setup
      description: >-
        <Info>This API is in beta. Endpoints, fields, and behavior may still
        change, so avoid depending on it in production.</Info>


        Starts the Marketing Agent's setup for an app. The agent reads the app
        and drafts marketing channels and KPIs for you to review.


        The first run in a workspace also creates the workspace's Marketing
        Agent, a Superagent that everyone in the workspace shares.


        The work runs in the background after the call returns. Poll [Get
        Marketing Agent state](/api-reference/get-marketing-agent-state) until
        `status` is `ready` or `error`. If `competitor_scan_status` is
        `running`, keep polling until it is no longer `running`. Setup then
        waits at a `setup_stage` of `channels`. Approve each step with [Answer
        Marketing Agent setup
        step](/api-reference/answer-marketing-agent-setup-step), or ask for
        changes with [Send Marketing Agent
        message](/api-reference/send-marketing-agent-message).


        While the scan is running, or once setup is past it, the call returns
        the current state and starts nothing. After a failed scan it starts the
        scan again, which is a new charged run.


        To retry safely, send an `Idempotency-Key` header. A retry with the same
        key within 24 hours returns the current state and starts nothing, even
        if the first scan failed.


        Each run is a Superagent turn, charged to the app's workspace in message
        credits based on the tokens it uses. A run can take several minutes and
        is stopped after 15. If the workspace is out of credits the run doesn't
        start, and `last_error` says so.


        This is limited to 120 requests a minute per app for each workspace's
        personal API keys, so every key in a workspace shares one allowance,
        across every Marketing Agent endpoint. Some workspaces have a different
        limit.


        <Note>This endpoint accepts a personal API key belonging to a user with
        editor access to the app and an editor role in its workspace. Read-only
        keys and workspace API keys are refused.</Note>


        <Warning>The response includes fields beyond the ones documented here.
        Don't rely on undocumented response fields, as they can change at any
        time.</Warning>
      operationId: start_cmo_setup_api_apps__app_id__cmo_setup_start_post
      parameters:
        - name: app_id
          in: path
          required: true
          schema:
            type: string
            description: ID of the app.
            title: App Id
          description: ID of the app.
          example: 6820f3a4e7b91d003c45a1f2
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            anyOf:
              - type: string
                maxLength: 100
                minLength: 1
              - type: 'null'
            description: >-
              Your key for this call. A retry with the same key within 24 hours
              returns the current state and starts nothing.
            title: Idempotency-Key
          description: >-
            Your key for this call. A retry with the same key within 24 hours
            returns the current state and starts nothing.
          example: weekly-plan-2026-09-29
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAgentStateResponse'
        '401':
          description: Missing or invalid credentials.
        '403':
          description: >-
            You don't have editor access to this app or an editor role in its
            workspace, the app is a mobile app, Superagent is turned off for the
            workspace, or you used a read-only or workspace API key.
        '404':
          description: App not found.
        '422':
          description: '`Idempotency-Key` is longer than 100 characters.'
        '429':
          description: Rate limit exceeded.
components:
  schemas:
    MarketingAgentStateResponse:
      properties:
        status:
          type: string
          enum:
            - idle
            - provisioning
            - analyzing
            - ready
            - error
          title: Status
          description: >-
            State of the latest run. Either `"idle"` before any run,
            `"provisioning"` while the workspace's Marketing Agent is created,
            `"analyzing"` while a run is working, `"ready"` once it finished, or
            `"error"` if it failed. A run that stops reporting for 15 minutes
            reads as `"error"`.
          example: ready
        run_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Run Id
          description: >-
            ID of the latest run, or `null` if no run has started. Compare it
            between polls to tell a new run from the one you started.
          example: 68a1c9b7f0b3d9001a7e5d04
        last_error:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Error
          description: Why the latest run failed, or `null` if it didn't.
          example: The scan did not complete. Retry the setup.
        setup_stage:
          type: string
          enum:
            - not_started
            - scanning
            - channels
            - kpis
            - budget
            - generating
            - complete
          title: Setup Stage
          description: >-
            How far setup has got. Either `"not_started"`, `"scanning"`,
            `"channels"`, `"kpis"`, `"budget"`, `"generating"`, or `"complete"`.
            At `channels`, `kpis`, and `budget` the agent is waiting for an
            answer.
          example: channels
        reset_epoch:
          type: integer
          title: Reset Epoch
          description: >-
            Number of times the plan was reset. Send it back as `reset_epoch`
            when you answer a setup step.
          example: 0
        channels:
          items:
            $ref: '#/components/schemas/MarketingChannel'
          type: array
          title: Channels
          description: >-
            The marketing channels the agent proposed. Empty until the opening
            scan finishes.
        channels_revision_suggestion:
          anyOf:
            - type: string
            - type: 'null'
          title: Channels Revision Suggestion
          description: >-
            A change to the channels the agent offers to make, or `null` if it
            offers none. Send it as a message to accept it.
          example: Swap LinkedIn for Product Hunt
        kpis:
          items:
            $ref: '#/components/schemas/MarketingKpi'
          type: array
          title: Kpis
          description: The KPIs the agent proposed. Empty until the opening scan finishes.
        kpis_revision_suggestion:
          anyOf:
            - type: string
            - type: 'null'
          title: Kpis Revision Suggestion
          description: >-
            A change to the KPIs the agent offers to make, or `null` if it
            offers none. Send it as a message to accept it.
          example: Track paid conversions instead of signups
        strategy:
          anyOf:
            - $ref: '#/components/schemas/MarketingStrategy'
            - type: 'null'
          description: The marketing strategy, or `null` until setup writes one.
        suggestions:
          items:
            $ref: '#/components/schemas/MarketingSuggestion'
          type: array
          title: Suggestions
          description: Growth ideas the agent generated for the app.
        budget:
          anyOf:
            - $ref: '#/components/schemas/MarketingBudget'
            - type: 'null'
          description: >-
            The marketing budget given during setup, or `null` if none was given
            yet.
        competitor_research_opt_in:
          type: boolean
          title: Competitor Research Opt In
          description: Whether competitor research runs alongside the strategy.
          example: true
        competitor_research_answer:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Competitor Research Answer
          description: >-
            Whether competitor research was accepted (`true`) or declined
            (`false`), or `null` if the question wasn't answered yet.
          example: true
        setup_paused:
          type: boolean
          title: Setup Paused
          description: >-
            Whether setup is paused because the user asked the agent to stop.
            Sending a message resumes it.
          example: false
        competitors:
          items:
            $ref: '#/components/schemas/MarketingCompetitor'
          type: array
          title: Competitors
          description: Competitors found by the research, with verified URLs.
        competitor_scan_status:
          anyOf:
            - type: string
              enum:
                - running
                - done
                - failed
            - type: 'null'
          title: Competitor Scan Status
          description: >-
            State of the competitor research. Either `"running"`, `"done"`, or
            `"failed"`, or `null` if it never ran.
          example: done
        cmo_agent_app_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Cmo Agent App Id
          description: >-
            ID of the workspace's Marketing Agent app your conversation runs on,
            or `null` if you haven't talked to it on this app yet.
          example: 68a1c2e4f0b3d9001a7e5c21
      type: object
      required:
        - status
        - run_id
        - last_error
        - setup_stage
        - reset_epoch
        - channels
        - channels_revision_suggestion
        - kpis
        - kpis_revision_suggestion
        - strategy
        - suggestions
        - budget
        - competitor_research_opt_in
        - competitor_research_answer
        - setup_paused
        - competitors
        - competitor_scan_status
        - cmo_agent_app_id
      title: MarketingAgentStateResponse
      description: The Marketing Agent's plan for an app and the state of its latest run.
    MarketingChannel:
      properties:
        name:
          type: string
          title: Name
          description: Name of the channel.
          example: Reddit communities
        why:
          type: string
          title: Why
          description: Why this channel fits the app.
          example: Freelancers already trade CRM tips in r/freelance.
        tactics:
          items:
            type: string
          type: array
          title: Tactics
          description: Concrete tactics for the channel. Up to 3.
          example:
            - Share a build-in-public thread
            - Answer lead-tracking questions
        priority:
          anyOf:
            - type: integer
            - type: 'null'
          title: Priority
          description: >-
            How much to invest in this channel, from `1` to `5`, where `5` means
            invest here first. Omitted when the agent didn't rank it.
          example: 5
      type: object
      required:
        - name
        - why
        - tactics
      title: MarketingChannel
    MarketingKpi:
      properties:
        name:
          type: string
          title: Name
          description: The KPI in one measurable line.
          example: Weekly signups
        why:
          type: string
          title: Why
          description: Why this KPI matters for the app.
          example: Signups are the first sign the Reddit threads convert.
        baseline:
          anyOf:
            - type: string
            - type: 'null'
          title: Baseline
          description: >-
            Current value, when the agent could tell it from the app. Omitted
            otherwise.
          example: About 10 a week
        target:
          anyOf:
            - type: string
            - type: 'null'
          title: Target
          description: Target at the recommended budget, with a time horizon.
          example: 50 a week in 90 days
        targets:
          anyOf:
            - additionalProperties:
                type: string
              type: object
            - type: 'null'
          title: Targets
          description: >-
            The target at each budget band, keyed by `none`, `low`, `mid`, and
            `high`. A band that's missing means spend at that level can't move
            this KPI.
          example:
            mid: 50 a week in 90 days
            none: 20 a week in 90 days
        target_values:
          anyOf:
            - additionalProperties:
                type: number
              type: object
            - type: 'null'
          title: Target Values
          description: The number inside each band's target, keyed like `targets`.
          example:
            mid: 50
            none: 20
        metric:
          anyOf:
            - $ref: '#/components/schemas/KpiMetric'
            - type: 'null'
          description: >-
            How the KPI is measured against the app's analytics. Omitted on KPIs
            created before measurement was added.
        instrument:
          anyOf:
            - $ref: '#/components/schemas/KpiInstrument'
            - type: 'null'
          description: >-
            How to start recording the KPI's event. Omitted when the app already
            records it.
      type: object
      required:
        - name
        - why
      title: MarketingKpi
    MarketingStrategy:
      properties:
        summary:
          type: string
          title: Summary
          description: The strategy in up to 2 sentences.
          example: >-
            Win early freelancers in the communities they already use, then turn
            them into referrals.
        positioning:
          anyOf:
            - type: string
            - type: 'null'
          title: Positioning
          description: How the app is positioned against its competitors.
          example: The CRM for freelancers who never wanted a CRM.
        channel_plan:
          items:
            $ref: '#/components/schemas/MarketingChannel'
          type: array
          title: Channel Plan
          description: The channels the strategy invests in.
        key_metrics:
          items:
            type: string
          type: array
          title: Key Metrics
          description: The metrics the strategy is judged by.
          example:
            - Weekly signups
            - Week-one retention
        budget_fit:
          anyOf:
            - type: string
            - type: 'null'
          title: Budget Fit
          description: How the strategy fits the workspace's stated budget.
          example: Organic first, with $100 a month for Reddit promoted posts.
      type: object
      required:
        - summary
        - channel_plan
        - key_metrics
      title: MarketingStrategy
    MarketingSuggestion:
      properties:
        id:
          type: string
          title: Id
          description: ID of the suggestion.
          example: 68a1d0c2f0b3d9001a7e5e10
        title:
          type: string
          title: Title
          description: Short title of the growth idea.
          example: Add a referral link to the dashboard
        builder_prompt:
          type: string
          title: Builder Prompt
          description: Prompt to send to the app builder to build the idea.
          example: >-
            Add a Refer a friend card to the dashboard with a copyable invite
            link.
        category:
          anyOf:
            - type: string
            - type: 'null'
          title: Category
          description: Kind of growth idea.
          example: Referral
        rationale:
          anyOf:
            - type: string
            - type: 'null'
          title: Rationale
          description: Why the idea should help.
          example: Freelancers recommend tools to each other.
        impact:
          anyOf:
            - type: string
            - type: 'null'
          title: Impact
          description: Expected impact. Either `"high"`, `"medium"`, or `"low"`.
          example: high
        effort:
          anyOf:
            - type: string
            - type: 'null'
          title: Effort
          description: Rough build effort. Either `"low"`, `"medium"`, or `"high"`.
          example: low
        dismissed:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Dismissed
          description: Whether someone dismissed the suggestion.
          example: false
      type: object
      required:
        - id
        - title
        - builder_prompt
      title: MarketingSuggestion
    MarketingBudget:
      properties:
        description:
          type: string
          title: Description
          description: The budget as it was stated.
          example: $500 a month
        band:
          anyOf:
            - type: string
              enum:
                - none
                - low
                - mid
                - high
            - type: 'null'
          title: Band
          description: >-
            Budget band that selects each KPI's target. Either `"none"`,
            `"low"`, `"mid"`, or `"high"`. Omitted when the budget was stated in
            free text.
          example: mid
      type: object
      required:
        - description
      title: MarketingBudget
    MarketingCompetitor:
      properties:
        name:
          type: string
          title: Name
          description: Name of the competitor.
          example: HubSpot
        url:
          type: string
          title: Url
          description: URL of the competitor's site.
          example: https://www.hubspot.com
        angle:
          type: string
          title: Angle
          description: How the competitor positions itself.
          example: A full CRM suite for sales teams.
        gap:
          type: string
          title: Gap
          description: What the competitor leaves open for this app.
          example: Too heavy for a solo freelancer.
      type: object
      required:
        - name
        - url
        - angle
        - gap
      title: MarketingCompetitor
    KpiMetric:
      properties:
        template:
          type: string
          enum:
            - event_count
            - unique_sessions
            - unique_users
            - retention_dn
          title: Template
          description: >-
            How the KPI is counted. Either `"event_count"`, `"unique_sessions"`,
            `"unique_users"`, or `"retention_dn"`.
          example: event_count
        event_name:
          type: string
          title: Event Name
          description: Analytics event the KPI is measured against.
          example: lead_created
        window_days:
          anyOf:
            - type: integer
            - type: 'null'
          title: Window Days
          description: Number of days the value is counted over. Either `7` or `30`.
          example: 7
        'n':
          anyOf:
            - type: integer
            - type: 'null'
          title: 'N'
          description: Day the return is measured at, for a `retention_dn` KPI only.
          example: 7
      type: object
      required:
        - template
        - event_name
      title: KpiMetric
    KpiInstrument:
      properties:
        builder_prompt:
          type: string
          title: Builder Prompt
          description: >-
            Prompt for the app builder that adds the missing analytics event.
            Present only while the app doesn't record `metric.event_name` yet.
          example: Track a lead_created event when a lead is saved on the Leads page.
        where:
          anyOf:
            - type: string
            - type: 'null'
          title: Where
          description: >-
            Where in the app's code the outcome already happens. Omitted when
            the agent didn't find it.
          example: src/pages/Leads.jsx:42
        requested_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Requested At
          description: >-
            When the build that adds the event was requested, as an ISO 8601
            timestamp, or `null` if it hasn't been.
          example: '2026-08-24T09:20:00+00:00'
      type: object
      required:
        - builder_prompt
      title: KpiInstrument
  securitySchemes:
    PersonalAccessTokenAuth:
      type: http
      scheme: bearer
      description: 'Personal access token, sent as `Authorization: Bearer <token>`.'

````