Send Marketing Agent message
Changed on<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>
Sends a message to the app's Marketing Agent and starts the turn that answers it. During setup the message answers or revises the step the agent is on. After setup it's an ordinary conversation about the app's marketing.
A message sent before setup has started opens it, the same way Start Marketing Agent setup does.
The work runs in the background after the call returns. Poll Get Marketing Agent state until status is ready or error. If competitor_scan_status is running, keep polling until it is no longer running. The reply appears in the app's chat, which you read with Read conversation messages.
The agent takes one turn at a time, so a message sent while it's working is rejected. Send it again once status is ready or error. If writing the strategy failed partway, a message starts writing it again and is itself rejected until that finishes.
Set message_id to a UUID of your own, or send an Idempotency-Key header instead. A retry that carries the same message_id or key returns the current state without starting or charging a second turn.
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. Send only the fields documented here. Other request fields are not supported and their behavior can change.</Warning>
Request
- Base URLhttps://app.base44.com
- URLhttps://app.base44.com/api/apps/{app_id}/cmo/messages
- AuthHTTP bearer
Path parameters
ID of the app.
Headers
Your key for this message, as an alternative to message_id. A retry with the same key doesn't start a second turn. Ignored when the body carries message_id.
Language to return generated text in, as a standard Accept-Language value. An unsupported language falls back to English.
Request body
Example request
{
"message_id": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
"content": "Focus on LinkedIn instead of Reddit."
}Response
Successful Response
Example response
{
"status": "ready",
"run_id": "68a1c9b7f0b3d9001a7e5d04",
"last_error": "The scan did not complete. Retry the setup.",
"setup_stage": "channels",
"channels": [
{
"name": "Reddit communities",
"why": "Freelancers already trade CRM tips in r/freelance.",
"tactics": [
"Share a build-in-public thread",
"Answer lead-tracking questions"
],
"priority": 5
}
],
"channels_revision_suggestion": "Swap LinkedIn for Product Hunt",
"kpis": [
{
"name": "Weekly signups",
"why": "Signups are the first sign the Reddit threads convert.",
"baseline": "About 10 a week",
"target": "50 a week in 90 days",
"targets": {
"mid": "50 a week in 90 days",
"none": "20 a week in 90 days"
},
"target_values": {
"mid": 50,
"none": 20
},
"metric": {
"template": "event_count",
"event_name": "lead_created",
"window_days": 7,
"n": 7
},
"instrument": {
"chat_prompt": "Track a lead_created event when a lead is saved on the Leads page.",
"where": "src/pages/Leads.jsx:42",
"requested_at": "2026-08-24T09:20:00+00:00"
}
}
],
"kpis_revision_suggestion": "Track paid conversions instead of signups",
"strategy": {
"summary": "Win early freelancers in the communities they already use, then turn them into referrals.",
"positioning": "The CRM for freelancers who never wanted a CRM.",
"channel_plan": [
{
"name": "Reddit communities",
"why": "Freelancers already trade CRM tips in r/freelance.",
"tactics": [
"Share a build-in-public thread",
"Answer lead-tracking questions"
],
"priority": 5
}
],
"key_metrics": [
"Weekly signups",
"Week-one retention"
],
"budget_fit": "Organic first, with $100 a month for Reddit promoted posts."
},
"suggestions": [
{
"id": "68a1d0c2f0b3d9001a7e5e10",
"title": "Add a referral link to the dashboard",
"chat_prompt": "Add a Refer a friend card to the dashboard with a copyable invite link.",
"category": "Referral",
"rationale": "Freelancers recommend tools to each other.",
"impact": "high",
"effort": "low"
}
],
"budget": {
"description": "$500 a month",
"band": "mid"
},
"competitor_research_opt_in": true,
"competitor_research_answer": true,
"competitors": [
{
"name": "HubSpot",
"url": "https://www.hubspot.com",
"angle": "A full CRM suite for sales teams.",
"gap": "Too heavy for a solo freelancer."
}
],
"competitor_scan_status": "done",
"cmo_agent_app_id": "68a1c2e4f0b3d9001a7e5c21"
}Changes
- breaking
headerrequest parameterAccept-Languagelist-of-types was narrowed by removing typesnull - breaking
headerrequest parameterIdempotency-Keylist-of-types was narrowed by removing typesnull - breaking
for the
headerrequest parameterIdempotency-Key, the minLength was increased from0to1 - warning
for the
headerrequest parameterIdempotency-Key, the maxLength was set to100 - info
for the
headerrequest parameterAccept-Language, the type was generalized from no type tostring - info
for the
headerrequest parameterIdempotency-Key, the type was generalized from no type tostring
- breaking
- breaking
removed the required property
////from the response with the status - breaking
removed the required property
//from the response with the status - info
added the required property
////to the response with the status - info
added the required property
//to the response with the status
- breaking