Mini Audit API
Generate instant brand intelligence reports using AI
How It Works
Quick Start
Analyze Domain (Optional)
Get brand info, suggested topics, and competitors. This endpoint is asynchronous: it returns a jobId (HTTP 202), then you poll a separate endpoint for the result.
curl -X POST https://api.getmint.ai/api/domains/analyze \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"url": "https://stripe.com",
"market": "United States",
"language": "en"
}'Response (202):
{ "jobId": "5e3cc2c9-58c1-40af-886c-57ad8a8f4673" }Then poll GET /api/domains/analyze/:jobId (note: this path is different from the report poll path in step 4) until status is completed:
curl https://api.getmint.ai/api/domains/analyze/5e3cc2c9-58c1-40af-886c-57ad8a8f4673 \
-H "X-API-Key: YOUR_API_KEY"Response (completed):
{
"jobId": "5e3cc2c9-58c1-40af-886c-57ad8a8f4673",
"status": "completed",
"result": {
"name": "Stripe",
"shortDescription": "A technology company building economic infrastructure for the internet.",
"fullDescription": "Stripe is a financial infrastructure platform for businesses...",
"industry": "Financial Technology",
"keyBrandAttributes": ["innovative", "developer-friendly", "reliable", "global", "secure"],
"suggestedTopics": [
{
"name": "Payment Processing",
"description": "Online payment processing services for e-commerce businesses",
"keywords": ["payments", "checkout", "transactions"],
"competitors": [
{ "name": "PayPal", "urls": ["https://paypal.com"] },
{ "name": "Square", "urls": ["https://squareup.com"] },
{ "name": "Adyen", "urls": ["https://adyen.com"] }
],
"icon": "🎯"
}
]
},
"createdAt": "2024-01-15T10:30:00.000Z"
}The brand name is returned as result.name (not brandName), and each topic's competitors is an array of { name, urls } objects. Map these into the request bodies of the next steps as shown below.
Generate Prompts
Generate prompts for your analysis using the data from step 1. Important: Pass keyBrandAttributes from the analyze response to generate proper alignment prompts.
curl -X POST https://api.getmint.ai/api/domains/mini-audit/generate-prompts \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"domainInfo": {
"url": "https://stripe.com",
"name": "Stripe",
"market": "United States",
"primaryLanguageCode": "en",
"keyBrandAttributes": ["innovative", "developer-friendly", "reliable", "global", "secure"]
},
"topicInfo": {
"name": "Payment Processing",
"keywords": ["payments", "checkout", "transactions"],
"language": "en",
"market": "United States"
}
}'Response:
{
"visibilityPrompts": [
"What are the best payment processing solutions?",
"Which companies offer developer-friendly payment APIs?"
],
"sentimentPrompts": ["How do developers feel about Stripe?"],
"competitionPrompts": ["Compare Stripe vs PayPal vs Square"],
"alignmentPrompts": {
"global": [{ "prompt": "How is Stripe perceived in the market?" }],
"withAttributes": [
{ "attribute": "developer-friendly", "prompt": "Is Stripe developer-friendly?" }
]
}
}Generate Report
Use the prompts from step 2 to start report generation:
curl -X POST https://api.getmint.ai/api/domains/mini-audit/generate-report \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"topicName": "Payment Processing",
"name": "Stripe",
"websiteUrl": "https://stripe.com",
"market": "United States",
"projectLanguage": "en",
"prompts": {
"visibility": [
"What are the best payment processing solutions?",
"Which companies offer developer-friendly payment APIs?"
],
"sentiment": ["How do developers feel about Stripe?"],
"competition": ["Compare Stripe vs PayPal vs Square"],
"alignment": {
"global": [{ "prompt": "How is Stripe perceived in the market?" }],
"withAttributes": [
{ "attribute": "developer-friendly", "prompt": "Is Stripe developer-friendly?" }
]
}
},
"competitors": [
{ "name": "PayPal", "websiteUrl": "https://paypal.com" },
{ "name": "Square", "websiteUrl": "https://squareup.com" }
]
}'Response:
{ "jobId": "507f1f77bcf86cd799439011", "status": "pending" }Poll for Results
Poll every 3-5 seconds until status is completed:
curl https://api.getmint.ai/api/domains/mini-audit/jobs/507f1f77bcf86cd799439011 \
-H "X-API-Key: YOUR_API_KEY"Response (completed):
{
"jobId": "507f1f77bcf86cd799439011",
"status": "completed",
"result": {
"name": "Stripe",
"websiteUrl": "https://stripe.com",
"market": "United States",
"projectLanguage": "en",
"metrics": {
"visibility": { "value": 85.5 },
"sentiment": { "value": 78 },
"alignment": { "value": 72 }
},
"shareOfVoice": [
{ "brand": "Stripe", "favicon": "https://stripe.com", "share": 45 },
{ "brand": "PayPal", "favicon": "https://paypal.com", "share": 35 },
{ "brand": "Square", "favicon": "https://squareup.com", "share": 20 }
],
"topSources": [
{ "domain": "techcrunch.com", "used": 12, "percentage": 28.5 }
],
"alignmentCitations": [
{ "domain": "stripe.com", "insight": "Known for developer-first approach" }
],
"sentimentCitations": [
{ "domain": "g2.com", "insight": "Highly rated by developers" }
],
"recentChats": [
{ "topic": "Best payment APIs", "summary": "Stripe leads for developer experience", "fullResponse": "...", "mentions": 5 }
],
"competition": [
{
"competitor": "PayPal",
"brandStrengths": ["Better developer experience", "Cleaner API", "Superior documentation"],
"brandWeaknesses": ["Higher pricing for enterprise"]
},
{
"competitor": "Square",
"brandStrengths": ["More customizable checkout flow", "Faster integration time"],
"brandWeaknesses": ["Limited in-person payment support"]
}
]
},
"detailedResults": {
"alignment": [
{
"model": "ChatGPT",
"originalPrompt": "How is Stripe perceived in the market?",
"llmResponse": "Stripe is widely perceived as the leading...",
"attributeScores": [
{ "attribute": "developer-friendly", "score": 0.95, "evaluation": "Strongly aligned" }
],
"citations": [
{ "url": "https://example.com", "title": "Article Title", "text": "Relevant excerpt..." }
]
}
],
"sentiment": [
{
"model": "Gemini",
"originalPrompt": "How do developers feel about Stripe?",
"llmResponse": "Developers generally have very positive...",
"sentimentBreakdown": { "positive": 75, "neutral": 20, "negative": 5 },
"overallSentiment": "positive",
"citations": []
}
],
"visibility": [
{
"model": "Perplexity",
"prompt": "What are the best payment processing solutions?",
"response": "The best payment processing solutions include...",
"brandMentioned": true,
"topOfMind": [
{ "name": "Stripe", "type": "brand" },
{ "name": "PayPal", "type": "brand" }
],
"citations": [
{ "url": "https://example.com", "title": "Source", "text": "...", "website": "example.com" }
]
}
],
"competition": [
{
"model": "ChatGPT",
"competitor": "PayPal",
"brandStrengths": ["Better developer experience", "Cleaner API"],
"brandWeaknesses": ["Higher pricing"]
}
]
},
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:32:45.000Z",
"completedAt": "2024-01-15T10:32:45.000Z"
}API Reference
See the full API specification in the interactive documentation:
- Analyze Domain - Get AI-enriched brand info (industry, competitors, topics)
- Generate Prompts - Create prompts for analysis
- Generate Report - Start async report generation
- Get Job Status - Poll for results
Limit: Visibility prompts are limited to 15 maximum. Requests with more than 15 visibility prompts will be rejected.
Code Examples
const API_KEY = 'YOUR_API_KEY';
const API_BASE = 'https://api.getmint.ai/api';
const POLL_INTERVAL_MS = 3000;
const MAX_POLL_ATTEMPTS = 60; // ~3 minutes at a 3s interval
/**
* Poll a job endpoint until it is completed, surfacing HTTP and job errors
* and giving up after MAX_POLL_ATTEMPTS instead of looping forever.
*/
async function pollJob(url, label) {
for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {
const res = await fetch(url, { headers: { 'X-API-Key': API_KEY } });
if (!res.ok) throw new Error(`Polling ${label} failed: HTTP ${res.status}`);
const job = await res.json();
if (job.status === 'completed') return job;
if (job.status === 'failed') throw new Error(job.error || job.errorMessage || `${label} failed`);
console.log(`Status: ${job.status}...`);
await new Promise(r => setTimeout(r, POLL_INTERVAL_MS));
}
throw new Error(`Timed out waiting for ${label} to complete`);
}
/**
* Complete Mini Audit flow:
* 1. Analyze domain to get brand info and suggested topics
* 2. Generate prompts for the selected topic
* 3. Start report generation job
* 4. Poll for results
*/
async function runCompleteMiniAudit(websiteUrl, market = 'United States', language = 'en') {
// Step 1: Analyze domain (async) — returns a jobId, then poll /analyze/:jobId for the result
const analyzeStart = await fetch(`${API_BASE}/domains/analyze`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY },
body: JSON.stringify({ url: websiteUrl, market, language })
});
if (!analyzeStart.ok) throw new Error(`Analyze failed: HTTP ${analyzeStart.status}`);
const { jobId: analyzeJobId } = await analyzeStart.json();
const analyzeJob = await pollJob(`${API_BASE}/domains/analyze/${analyzeJobId}`, 'analysis');
const domainInfo = analyzeJob.result;
// Use first suggested topic (or choose one)
const topic = domainInfo.suggestedTopics[0];
console.log(`Analyzing topic: ${topic.name}`);
// Step 2: Generate prompts for the topic
const promptsRes = await fetch(`${API_BASE}/domains/mini-audit/generate-prompts`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY },
body: JSON.stringify({
domainInfo: {
url: websiteUrl,
name: domainInfo.name,
market,
primaryLanguageCode: language,
keyBrandAttributes: domainInfo.keyBrandAttributes // Pass brand attributes for alignment prompts
},
topicInfo: {
name: topic.name,
keywords: topic.keywords,
language,
market
}
})
});
if (!promptsRes.ok) throw new Error(`Generate prompts failed: HTTP ${promptsRes.status}`);
const generatedPrompts = await promptsRes.json();
// Step 3: Start report generation job
const jobRes = await fetch(`${API_BASE}/domains/mini-audit/generate-report`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY },
body: JSON.stringify({
topicName: topic.name,
name: domainInfo.name,
websiteUrl,
market,
projectLanguage: language,
prompts: {
visibility: generatedPrompts.visibilityPrompts,
sentiment: generatedPrompts.sentimentPrompts,
competition: generatedPrompts.competitionPrompts,
alignment: generatedPrompts.alignmentPrompts
},
competitors: topic.competitors.map((c) => ({
name: c.name,
websiteUrl: c.urls?.[0]
}))
})
});
if (!jobRes.ok) throw new Error(`Generate report failed: HTTP ${jobRes.status}`);
const { jobId } = await jobRes.json();
console.log(`Job started: ${jobId}`);
// Step 4: Poll until complete
const reportJob = await pollJob(`${API_BASE}/domains/mini-audit/jobs/${jobId}`, 'report');
console.log('Report complete!');
return reportJob.result;
}
// Usage
const report = await runCompleteMiniAudit('https://stripe.com', 'United States', 'en');
console.log(`Visibility: ${report.metrics.visibility.value}%`);
console.log(`Sentiment: ${report.metrics.sentiment.value}`);
console.log(`Alignment: ${report.metrics.alignment.value}`);import requests
import time
API_KEY = 'YOUR_API_KEY'
API_BASE = 'https://api.getmint.ai/api'
POLL_INTERVAL_SECONDS = 3
MAX_POLL_ATTEMPTS = 60 # ~3 minutes at a 3s interval
def poll_job(url, label):
"""Poll a job endpoint until completed, raising on HTTP/job errors and giving
up after MAX_POLL_ATTEMPTS instead of looping forever."""
for _ in range(MAX_POLL_ATTEMPTS):
res = requests.get(url, headers={'X-API-Key': API_KEY})
res.raise_for_status()
job = res.json()
status = job.get('status')
if status == 'completed':
return job
if status == 'failed':
raise Exception(job.get('error') or job.get('errorMessage') or f'{label} failed')
print(f"Status: {status}...")
time.sleep(POLL_INTERVAL_SECONDS)
raise Exception(f'Timed out waiting for {label} to complete')
def run_complete_mini_audit(website_url, market='United States', language='en'):
"""
Complete Mini Audit flow:
1. Analyze domain to get brand info and suggested topics
2. Generate prompts for the selected topic
3. Start report generation job
4. Poll for results
"""
headers = {'Content-Type': 'application/json', 'X-API-Key': API_KEY}
# Step 1: Analyze domain (async) — returns a jobId, then poll /analyze/:jobId for the result
analyze_start = requests.post(
f'{API_BASE}/domains/analyze',
headers=headers,
json={'url': website_url, 'market': market, 'language': language}
)
analyze_start.raise_for_status()
analyze_job_id = analyze_start.json()['jobId']
domain_info = poll_job(f'{API_BASE}/domains/analyze/{analyze_job_id}', 'analysis')['result']
# Use first suggested topic (or choose one)
topic = domain_info['suggestedTopics'][0]
print(f"Analyzing topic: {topic['name']}")
# Step 2: Generate prompts for the topic
prompts_res = requests.post(
f'{API_BASE}/domains/mini-audit/generate-prompts',
headers=headers,
json={
'domainInfo': {
'url': website_url,
'name': domain_info['name'],
'market': market,
'primaryLanguageCode': language,
'keyBrandAttributes': domain_info['keyBrandAttributes'] # Pass brand attributes for alignment prompts
},
'topicInfo': {
'name': topic['name'],
'keywords': topic['keywords'],
'language': language,
'market': market
}
}
)
prompts_res.raise_for_status()
generated_prompts = prompts_res.json()
# Step 3: Start report generation job
job_res = requests.post(
f'{API_BASE}/domains/mini-audit/generate-report',
headers=headers,
json={
'topicName': topic['name'],
'name': domain_info['name'],
'websiteUrl': website_url,
'market': market,
'projectLanguage': language,
'prompts': {
'visibility': generated_prompts['visibilityPrompts'],
'sentiment': generated_prompts['sentimentPrompts'],
'competition': generated_prompts['competitionPrompts'],
'alignment': generated_prompts['alignmentPrompts']
},
'competitors': [
{'name': c['name'], 'websiteUrl': (c.get('urls') or [None])[0]}
for c in topic['competitors']
]
}
)
job_res.raise_for_status()
job_id = job_res.json()['jobId']
print(f"Job started: {job_id}")
# Step 4: Poll until complete
report_job = poll_job(f'{API_BASE}/domains/mini-audit/jobs/{job_id}', 'report')
print('Report complete!')
return report_job['result']
# Usage
report = run_complete_mini_audit('https://stripe.com', 'United States', 'en')
print(f"Visibility: {report['metrics']['visibility']['value']}%")
print(f"Sentiment: {report['metrics']['sentiment']['value']}")
print(f"Alignment: {report['metrics']['alignment']['value']}")Metric Definitions
Content Gaps from Mini Audit
Inputs: detailedResults.visibility from the Mini Audit result. Each row has prompt, brandMentioned, and optional citations[{ url, title, text, website }].
Steps (mirror TopicContentGapTable):
- Group rows by trimmed
prompt. - For each group, compute
totalResponsesandmissing = rows without brandMentioned. - If
missing.length === 0, skip. OtherwisegapPercentage = Math.round((missing.length / totalResponses) * 100). - Citations: flatten
missing.citations, keep those withurl, dedupe by URL, map{ title, text -> snippet, website -> domain }. - Emit a
ContentGapobject{ prompt, gapPercentage, responseCount: missing.length, totalResponses, lastSeen: new Date(), citations, reports: [] }. - Sort gaps by
gapPercentagedesc. UI shows top 5 by default; "See All" toggles the rest.
Minimal helper:
function buildContentGaps(rows: MiniAuditVisibilityRow[]): ContentGap[] {
const byPrompt = new Map<string, MiniAuditVisibilityRow[]>();
rows.forEach((r) => { if (r.prompt) byPrompt.set(r.prompt.trim(), [...(byPrompt.get(r.prompt.trim())||[]), r]); });
return Array.from(byPrompt.entries()).flatMap(([prompt, items]) => {
const missing = items.filter((r) => !r.brandMentioned);
if (!missing.length) return [];
const dedupedCitations = Array.from(new Map(missing.flatMap((r) => r.citations || [])
.filter((c) => c.url)
.map((c) => [c.url as string, { url: c.url as string, title: c.title, snippet: c.text, domain: c.website }])
).values());
return [{
prompt,
gapPercentage: Math.round((missing.length / items.length) * 100),
responseCount: missing.length,
totalResponses: items.length,
lastSeen: new Date(),
citations: dedupedCitations,
reports: [],
} satisfies ContentGap];
}).sort((a, b) => b.gapPercentage - a.gapPercentage);
}Notes
- Job retention: 24 hours. Store results if needed.
- Polling interval: 3-5 seconds recommended.
- Processing time: Typically 30-90 seconds.