Agency plan
API Reference
Access all your brand data programmatically. Available on the Agency plan.
Authentication
Generate API keys in your dashboard under Settings → API. Keys follow the format mtv_live_<32hex>. Pass the key in every request:
X-API-Key: mtv_live_your_key_here # or Authorization: Bearer mtv_live_your_key_here
Rate Limiting
60 requests per minute per API key. Exceeding this returns 429 Too Many Requests with a Retry-After: 60 header. Redis failure is handled gracefully — rate limiting fails open.
Response format
Success
{ "data": <T> }Paginated list
{ "data": [...],
"total": 42,
"limit": 50,
"offset": 0 }Error
{ "error": "Human-readable message",
"code": "MACHINE_CODE" }Endpoints
Base URL: https://mentova.ai/api/v1
Brands
| Method | Endpoint | Description |
|---|---|---|
| GET | /brands | List all brands |
| POST | /brands | Create a brand |
| GET | /brands/:id | Get brand details |
| PATCH | /brands/:id | Update brand |
| DELETE | /brands/:id | Delete brand |
Topics
| Method | Endpoint | Description |
|---|---|---|
| GET | /brands/:id/topics | List topics |
| POST | /brands/:id/topics | Create topic |
| DELETE | /brands/:id/topics/:topicId | Delete topic |
Campaigns & Prompts
| Method | Endpoint | Description |
|---|---|---|
| GET | /brands/:id/campaigns | List campaigns |
| POST | /brands/:id/campaigns | Launch campaign |
| GET | /brands/:id/campaigns/:campaignId | Campaign status + results |
| GET | /brands/:id/prompts | List prompts (?model= ?status= ?page= ?limit=) |
Visibility & Analytics
| Method | Endpoint | Description |
|---|---|---|
| GET | /brands/:id/visibility | SOV, mention rate + timeline (?days=30) |
| GET | /brands/:id/competitors | Competitor leaderboard |
| GET | /brands/:id/sources | Influential sources list |
Opportunities
| Method | Endpoint | Description |
|---|---|---|
| GET | /brands/:id/opportunities | List opportunities (?status=open|in_progress|done) |
| PATCH | /brands/:id/opportunities/:oppId | Update opportunity status |
Avatars
| Method | Endpoint | Description |
|---|---|---|
| GET | /brands/:id/avatars | List audience avatars (max 5) |
| POST | /brands/:id/avatars | Create avatar (PRO_PLUS+ — name, sector, role, objectives) |
| PATCH | /brands/:id/avatars/:avatarId | Update avatar fields |
| DELETE | /brands/:id/avatars/:avatarId | Delete avatar |
POST /brands/:id/avatars
Create an audience avatar for a brand. Requires PRO_PLUS or Agency plan. Max 5 avatars per brand.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Avatar display name (max 100 chars) |
| sector | string | Yes | Industry or sector (max 100 chars) |
| role | string | Yes | Job role or persona type (max 100 chars) |
| objectives | string | Yes | Goals and context for this persona (max 500 chars) |
| description | string | No | Optional longer description (max 1000 chars) |
| isDefault | boolean | No | Set as default avatar for new campaigns (default: false) |
curl
curl -X POST https://mentova.ai/api/v1/brands/BRAND_ID/avatars \
-H "X-API-Key: mtv_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Sarah, CMO",
"sector": "SaaS B2B",
"role": "Chief Marketing Officer",
"objectives": "Grow brand share of voice in AI search results",
"isDefault": true
}'JavaScript
const { data: avatar } = await fetch(
`https://mentova.ai/api/v1/brands/${brandId}/avatars`,
{
method: "POST",
headers: {
"X-API-Key": "mtv_live_your_key",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Sarah, CMO",
sector: "SaaS B2B",
role: "Chief Marketing Officer",
objectives: "Grow brand share of voice in AI search results",
isDefault: true,
}),
}
).then(r => r.json());
console.log(avatar.id); // "clx..."Response 201 Created
{
"data": {
"id": "clxabc123",
"brandId": "clxbrand456",
"name": "Sarah, CMO",
"sector": "SaaS B2B",
"role": "Chief Marketing Officer",
"objectives": "Grow brand share of voice in AI search results",
"description": null,
"isDefault": true,
"createdAt": "2026-04-17T10:00:00.000Z",
"updatedAt": "2026-04-17T10:00:00.000Z"
}
}Examples
Fetch visibility data
const API_KEY = "mtv_live_your_key";
const BASE = "https://mentova.ai/api/v1";
const get = (path) =>
fetch(`${BASE}${path}`, { headers: { "X-API-Key": API_KEY } }).then(r => r.json());
// List brands
const { data: brands } = await get("/brands");
const brandId = brands[0].id;
// Visibility — last 30 days
const { data: visibility } = await get(`/brands/${brandId}/visibility?days=30`);
console.log(visibility.mentionRate, visibility.shareOfVoice);
// Competitors leaderboard
const { data: competitors } = await get(`/brands/${brandId}/competitors`);
// Open opportunities
const { data: opps } = await get(`/brands/${brandId}/opportunities?status=open`);Manage audience avatars
// Create an audience avatar
const { data: avatar } = await fetch(`${BASE}/brands/${brandId}/avatars`, {
method: "POST",
headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
name: "Sarah, CMO",
sector: "SaaS B2B",
role: "Chief Marketing Officer",
objectives: "Grow brand share of voice in AI search results",
isDefault: true,
}),
}).then(r => r.json());
// List avatars
const { data: avatars } = await fetch(`${BASE}/brands/${brandId}/avatars`, {
headers: { "X-API-Key": API_KEY },
}).then(r => r.json());Launch a campaign
// Get topics first
const { data: topics } = await get(`/brands/${brandId}/topics`);
// Launch campaign on first topic
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: topics[0].id }),
}).then(r => r.json());
// Poll status
let status = campaign.status;
while (status === "running") {
await new Promise(r => setTimeout(r, 5000));
const { data } = await get(`/brands/${brandId}/campaigns/${campaign.id}`);
status = data.status;
}
// Fetch prompts when done
const { data: prompts } = await get(`/brands/${brandId}/prompts?status=mentioned`);Error codes
| HTTP | code | Meaning |
|---|---|---|
| 401 | MISSING_API_KEY | No key provided |
| 401 | INVALID_API_KEY | Key not found or revoked |
| 403 | PLAN_REQUIRED | Agency plan required |
| 403 | FORBIDDEN | Resource belongs to another account |
| 404 | NOT_FOUND | Resource not found |
| 422 | VALIDATION_ERROR | Invalid request body |
| 422 | LIMIT_REACHED | Plan limit reached (brands, keys…) |
| 429 | RATE_LIMITED | 60 req/min exceeded |