Overview
A campaign sends a topic's prompts to one or more LLM models and extracts brand mentions from the responses. Credits are consumed at launch based on the number of prompts, models, and runs per model.
Endpoints
| Method | Path | Description |
|---|
GET | /brands/{brandId}/campaigns | List campaigns |
POST | /brands/{brandId}/campaigns | Launch a campaign |
GET | /brands/{brandId}/campaigns/{campaignId} | Get campaign status |
GET /brands//campaigns
List all campaigns for a brand, ordered by most recent first.
Query parameters
| Parameter | Type | Default | Description |
|---|
limit | integer | 50 | Max results (capped at 200) |
offset | integer | 0 | Pagination offset |
curl "https://mentova.ai/api/v1/brands/clxabc123/campaigns?limit=10" \
-H "X-API-Key: mtv_live_your_key"
Response 200
{
"data": [
{
"id": "clxcampaign1",
"status": "COMPLETED",
"createdAt": "2026-06-01T09:00:00.000Z",
"completedAt": "2026-06-01T09:08:00.000Z",
"models": ["GPT4O_MINI", "CLAUDE_HAIKU"],
"runsPerModel": 3,
"topic": {
"id": "clxtopic1",
"seed": "What is the best project management tool for remote teams?"
},
"_count": { "runs": 6 }
}
],
"total": 12,
"limit": 10,
"offset": 0
}
POST /brands//campaigns
Launch a new campaign on a topic. The campaign is processed asynchronously.
Request body
| Field | Type | Required | Description |
|---|
topicId | string | Yes | ID of the topic to run the campaign on |
models | string[] | No | LLM model enum values to use. Defaults to the brand's selected models |
runsPerModel | integer | No | Number of runs per model (1-20). Defaults to plan setting |
maxPrompts | integer | No | Cap on prompts to include. Defaults to all topic prompts |
curl -X POST https://mentova.ai/api/v1/brands/clxabc123/campaigns \
-H "X-API-Key: mtv_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"topicId": "clxtopic1",
"models": ["GPT4O_MINI", "CLAUDE_HAIKU"],
"runsPerModel": 3
}'
Response 201
{
"data": {
"id": "clxcampaign2",
"status": "PENDING",
"createdAt": "2026-06-01T10:00:00.000Z",
"completedAt": null,
"models": ["GPT4O_MINI", "CLAUDE_HAIKU"],
"runsPerModel": 3,
"topic": {
"id": "clxtopic1",
"seed": "What is the best project management tool for remote teams?"
},
"_count": { "runs": 0 }
}
}
Error responses
| HTTP | code | Cause |
|---|
404 | NOT_FOUND | Topic not found or does not belong to this brand |
422 | QUOTA_EXCEEDED | Insufficient credits to launch the campaign |
422 | VALIDATION_ERROR | Invalid request body |
GET /brands//campaigns/
Get the current status and details of a campaign. Poll this endpoint to track progress.
curl https://mentova.ai/api/v1/brands/clxabc123/campaigns/clxcampaign2 \
-H "X-API-Key: mtv_live_your_key"
Response 200
{
"data": {
"id": "clxcampaign2",
"status": "RUNNING",
"createdAt": "2026-06-01T10:00:00.000Z",
"completedAt": null,
"models": ["GPT4O_MINI", "CLAUDE_HAIKU"],
"runsPerModel": 3,
"topic": {
"id": "clxtopic1",
"seed": "What is the best project management tool for remote teams?"
},
"_count": { "runs": 4 }
}
}
Campaign status values
| Status | Description |
|---|
PENDING | Accepted, waiting to enter the processing queue |
QUEUED | Picked up by the worker, waiting for an execution slot |
RUNNING | LLM calls in progress |
COMPLETED | All runs finished, mentions extracted |
FAILED | Processing error - credits are refunded |
TIMEOUT | Worker timed out - credits are refunded |
Polling pattern
const API_KEY = "mtv_live_your_key";
const BASE = "https://mentova.ai/api/v1";
// Launch
const { data: campaign } = await fetch(`${BASE}/brands/${brandId}/campaigns`, {
method: "POST",
headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ topicId }),
}).then(r => r.json());
// Poll until done
let status = campaign.status;
while (status === "PENDING" || status === "QUEUED" || status === "RUNNING") {
await new Promise(r => setTimeout(r, 5000));
const { data } = await fetch(
`${BASE}/brands/${brandId}/campaigns/${campaign.id}`,
{ headers: { "X-API-Key": API_KEY } }
).then(r => r.json());
status = data.status;
}