Documentation Index
Fetch the complete documentation index at: https://docs.topify.ai/llms.txt
Use this file to discover all available pages before exploring further.
Prompts are the AI search queries Topify.ai tracks daily across all AI providers. Each prompt generates responses that are analyzed for brand visibility, sentiment, citations, and competitor mentions.
The API supports full CRUD operations on prompts. Read endpoints are available to all API keys. Write endpoints (create, update, delete) require an admin-scoped API key.
List prompts
GET /projects/{project_id}/prompts
Returns all prompts in a project, ordered by creation date.
Path parameters
| Param | Type | Description |
|---|
project_id | string (UUID) | The project ID |
curl "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts" \
-H "X-API-Key: tk_live_..."
resp = client.get(f"/projects/{project_id}/prompts")
const resp = await fetch(`${BASE}/projects/${projectId}/prompts`, { headers });
Response
{
"success": true,
"data": {
"project_id": "a1b2c3d4-...",
"total": 25,
"prompts": [
{
"id": "e5f6a7b8-...",
"project_id": "a1b2c3d4-...",
"content": "What is the best project management tool?",
"prompt_type": "active",
"topic_id": "t1u2v3w4-...",
"country": "US",
"visibility": 85.0,
"sentiment": 72,
"position": 2.3,
"volume": 150,
"cvr": 45.0,
"intent": "commercial",
"trend": "up",
"created_at": "2026-01-15T10:30:00+00:00"
}
]
}
}
Prompt fields
| Field | Type | Nullable | Description |
|---|
id | string (UUID) | No | Prompt ID |
project_id | string (UUID) | No | Parent project ID |
content | string | No | The AI search query text |
prompt_type | string | No | active, suggested, pending, inactive, or url_recommended |
topic_id | string (UUID) | Yes | Topic this prompt belongs to |
country | string | Yes | Target country for localized responses |
visibility | float | Yes | Brand visibility percentage (0—100) |
sentiment | integer | Yes | Brand sentiment score |
position | float | Yes | Average brand position in responses |
volume | integer | Yes | Number of responses collected |
cvr | float | Yes | Content visibility rate |
intent | string | Yes | Query intent: informational, commercial, navigational, transactional |
trend | string | Yes | Trend direction: up, down, or stable |
created_at | string (ISO 8601) | No | Creation timestamp |
Get prompt
GET /projects/{project_id}/prompts/{prompt_id}
Returns a single prompt. Same fields as list.
Path parameters
| Param | Type | Description |
|---|
project_id | string (UUID) | The project ID |
prompt_id | string (UUID) | The prompt ID |
curl "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts/{prompt_id}" \
-H "X-API-Key: tk_live_..."
resp = client.get(f"/projects/{project_id}/prompts/{prompt_id}")
const resp = await fetch(`${BASE}/projects/${projectId}/prompts/${promptId}`, { headers });
Create prompts
POST /projects/{project_id}/prompts
Add one or more prompts to a project. Each prompt begins tracking immediately — Topify.ai will start collecting AI responses and calculating metrics in the background.
Requires an admin-scoped API key. Viewer keys receive a 403 response.
Path parameters
| Param | Type | Description |
|---|
project_id | string (UUID) | The project to add prompts to |
Request body
| Field | Type | Required | Description |
|---|
prompts | string[] | Yes | Array of prompt texts to track (1—50 per request) |
topicId | string (UUID) | Yes | Topic to assign the prompts to |
country | string | No | ISO country code for localized responses |
curl -X POST "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts" \
-H "X-API-Key: tk_live_..." \
-H "Content-Type: application/json" \
-d '{
"prompts": ["What is the best project management tool?", "Top PM software for teams"],
"topicId": "t1u2v3w4-...",
"country": "US"
}'
resp = client.post(f"/projects/{project_id}/prompts", json={
"prompts": ["What is the best project management tool?"],
"topicId": topic_id,
"country": "US",
})
const resp = await fetch(`${BASE}/projects/${projectId}/prompts`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({
prompts: ["What is the best project management tool?"],
topicId: topicId,
country: "US",
}),
});
Response
{
"code": 200,
"message": "200 OK",
"data": {
"projectId": "a1b2c3d4-...",
"created": 2,
"prompts": [
{
"id": "e5f6a7b8-...",
"projectId": "a1b2c3d4-...",
"content": "What is the best project management tool?",
"promptType": "Active",
"topicId": "t1u2v3w4-...",
"country": "US",
"createdAt": "2026-03-30T10:30:00+00:00"
}
]
}
}
Error responses
| Status | Cause |
|---|
400 | Empty prompts array, whitespace-only content, or missing topicId |
403 | API key has read-only (viewer) access |
409 | A prompt with the same content already exists in this project |
429 | Prompt quota exceeded for your plan tier |
Update prompt
PATCH /projects/{project_id}/prompts/{prompt_id}
Update the content, country, topic, or type of an existing prompt.
Requires an admin-scoped API key.
Path parameters
| Param | Type | Description |
|---|
project_id | string (UUID) | The project ID |
prompt_id | string (UUID) | The prompt to update |
Request body
All fields are optional. Include only the fields you want to change.
| Field | Type | Description |
|---|
content | string | New prompt text (cannot be empty) |
country | string | ISO country code |
topicId | string (UUID) | Reassign to a different topic |
promptType | string | Change prompt type (Active, Inactive, Suggested) |
curl -X PATCH "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts/{prompt_id}" \
-H "X-API-Key: tk_live_..." \
-H "Content-Type: application/json" \
-d '{"content": "Best project management tools for remote teams"}'
resp = client.patch(f"/projects/{project_id}/prompts/{prompt_id}", json={
"content": "Best project management tools for remote teams",
})
const resp = await fetch(`${BASE}/projects/${projectId}/prompts/${promptId}`, {
method: "PATCH",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({ content: "Best project management tools for remote teams" }),
});
Response
Returns the updated prompt with all fields (same shape as get prompt).
Error responses
| Status | Cause |
|---|
400 | Empty request body, whitespace-only content, or no fields changed |
403 | API key has read-only access |
404 | Prompt not found in this project |
Delete prompt
DELETE /projects/{project_id}/prompts/{prompt_id}
Permanently delete a prompt and stop tracking it. Historical analytics data for this prompt is also removed.
This action cannot be undone. Requires an admin-scoped API key.
Path parameters
| Param | Type | Description |
|---|
project_id | string (UUID) | The project ID |
prompt_id | string (UUID) | The prompt to delete |
curl -X DELETE "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts/{prompt_id}" \
-H "X-API-Key: tk_live_..."
resp = client.delete(f"/projects/{project_id}/prompts/{prompt_id}")
const resp = await fetch(`${BASE}/projects/${projectId}/prompts/${promptId}`, {
method: "DELETE",
headers,
});
Response
{
"code": 200,
"message": "200 OK",
"data": {
"promptId": "e5f6a7b8-...",
"message": "Prompt deleted successfully"
}
}
Error responses
| Status | Cause |
|---|
403 | API key has read-only access |
404 | Prompt not found in this project |
Prompt analytics
GET /projects/{project_id}/prompts/{prompt_id}/analytics
Returns time-series visibility, position, and sentiment data grouped by date and AI provider.
Query parameters
| Param | Type | Default | Description |
|---|
duration_days | integer | 7 | Days to look back |
date_from | string | — | Start date (YYYY-MM-DD) |
date_to | string | — | End date (YYYY-MM-DD) |
providers | string | — | Comma-separated provider filter |
curl "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts/{prompt_id}/analytics?duration_days=7" \
-H "X-API-Key: tk_live_..."
resp = client.get(f"/projects/{project_id}/prompts/{prompt_id}/analytics", params={"duration_days": 7})
const resp = await fetch(`${BASE}/projects/${projectId}/prompts/${promptId}/analytics?duration_days=7`, { headers });
Response
{
"success": true,
"data": {
"prompt_id": "e5f6a7b8-...",
"prompt_content": "What is the best project management tool?",
"volume": 42,
"sentiment": 72,
"visibility_chart": {
"2026-03-01": [
{ "provider": "chatgpt", "value": 85.0 },
{ "provider": "perplexity", "value": 90.0 }
],
"2026-03-02": [
{ "provider": "chatgpt", "value": 80.0 }
]
},
"position_chart": {
"2026-03-01": [
{ "provider": "chatgpt", "value": 2.0 }
]
},
"sentiment_chart": {
"2026-03-01": [
{ "provider": "chatgpt", "value": 75.0 }
]
}
}
}
Response fields
| Field | Type | Nullable | Description |
|---|
prompt_id | string (UUID) | No | Prompt ID |
prompt_content | string | No | The AI search query text |
volume | integer | Yes | Total responses collected |
sentiment | integer | Yes | Overall brand sentiment across the period |
visibility_chart | object | No | Date-keyed map of ProviderMetric[] (visibility %) |
position_chart | object | No | Date-keyed map of ProviderMetric[] (avg position) |
sentiment_chart | object | No | Date-keyed map of ProviderMetric[] (avg sentiment) |
ProviderMetric:
| Field | Type | Description |
|---|
provider | string | AI provider name (e.g., chatgpt) |
value | float | Metric value for that provider on that date |
AI responses (chats)
GET /projects/{project_id}/prompts/{prompt_id}/chats
Returns raw AI responses with brand mentions, sentiment, position, and citation references.
Query parameters
Same as analytics.
curl "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts/{prompt_id}/chats?duration_days=7" \
-H "X-API-Key: tk_live_..."
resp = client.get(f"/projects/{project_id}/prompts/{prompt_id}/chats", params={"duration_days": 7})
const resp = await fetch(`${BASE}/projects/${projectId}/prompts/${promptId}/chats?duration_days=7`, { headers });
Response
{
"success": true,
"data": {
"items": [
{
"id": "c1d2e3f4-...",
"date": "2026-03-01T12:00:00+00:00",
"mentioned": true,
"position": 2,
"all_mentions": [
{
"name": "Acme Corp",
"icon_url": "https://logo.clearbit.com/acme.com",
"icon_urls": ["https://logo.clearbit.com/acme.com", "https://www.google.com/s2/favicons?domain=acme.com&sz=64"]
}
],
"chat_preview": "When it comes to project management tools...",
"platform": "chatgpt",
"model": "gpt-4o",
"full_content": "When it comes to project management tools, Acme Corp stands out for...",
"prompt_content": "What is the best project management tool?",
"references": [
{
"title": "Best PM Tools 2026",
"link": "https://techcrunch.com/best-pm-tools",
"snippet": "Acme Corp ranked #1...",
"reference_index": 1
}
],
"brands_mentioned": {
"Acme Corp": { "position": 1, "count": 3 },
"Competitor A": { "position": 2, "count": 1 }
},
"sentiment": 80,
"sentiment_by_brands": {
"Acme Corp": 80,
"Competitor A": 60
}
}
]
}
}
ChatItem fields
| Field | Type | Nullable | Description |
|---|
id | string (UUID) | No | LLM output ID |
date | string (ISO 8601) | No | When the response was generated |
mentioned | boolean | No | Whether your brand was mentioned |
position | integer | Yes | Your brand’s rank position in this response |
all_mentions | BrandMention[] | No | All brands mentioned in the response |
chat_preview | string | No | First sentence of the response (max 150 chars) |
platform | string | No | AI provider (chatgpt, perplexity, google_ai_overview, gemini, claude) |
model | string | No | Specific model used (e.g., gpt-4o) |
full_content | string | No | Complete AI response text |
prompt_content | string | No | The prompt that generated this response |
references | ReferenceItem[] | No | Citations/sources in the response |
brands_mentioned | object | Yes | Raw brand extraction data (brand name to position/count mapping) |
sentiment | integer | Yes | Your brand’s sentiment score in this response |
sentiment_by_brands | object | Yes | Sentiment scores keyed by brand name |
BrandMention:
| Field | Type | Description |
|---|
name | string | Brand name as it appeared in the response |
icon_url | string | Primary logo URL |
icon_urls | string[] | Multiple logo URL sources |
ReferenceItem:
| Field | Type | Description |
|---|
title | string | Citation title |
link | string | Citation URL |
snippet | string | Citation snippet text |
reference_index | integer | Position of the citation in the response |
Domains
GET /projects/{project_id}/prompts/{prompt_id}/domains
Returns domain-level citation breakdown, sorted by citation count descending.
Query parameters
Same as analytics.
curl "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts/{prompt_id}/domains?duration_days=7" \
-H "X-API-Key: tk_live_..."
resp = client.get(f"/projects/{project_id}/prompts/{prompt_id}/domains", params={"duration_days": 7})
const resp = await fetch(`${BASE}/projects/${projectId}/prompts/${promptId}/domains?duration_days=7`, { headers });
Response
{
"success": true,
"data": {
"items": [
{
"domain": "techcrunch.com",
"domain_type": 1,
"citation_count": 15,
"avg_citations": 2.5,
"used_percentage": 75.0,
"mentioned": true,
"brands_appeared": [
{
"name": "Acme Corp",
"icon_url": "https://logo.clearbit.com/acme.com",
"icon_urls": ["https://logo.clearbit.com/acme.com"]
}
],
"favicon_url": "https://www.google.com/s2/favicons?domain=techcrunch.com&sz=64",
"favicon_urls": [
"https://logo.clearbit.com/techcrunch.com",
"https://www.google.com/s2/favicons?domain=techcrunch.com&sz=64"
]
}
]
}
}
DomainItem fields
| Field | Type | Nullable | Description |
|---|
domain | string | No | Domain name |
domain_type | integer | No | Source category ID |
citation_count | integer | No | Total citation count across all responses |
avg_citations | float | No | Average citations per response that cited this domain |
used_percentage | float | No | How frequently this domain appears (percentage) |
mentioned | boolean | No | Whether your brand appeared alongside this domain |
brands_appeared | BrandInfo[] | No | Brands that appeared in responses citing this domain |
favicon_url | string | Yes | Primary favicon URL |
favicon_urls | string[] | No | Multiple favicon URL sources |
BrandInfo:
| Field | Type | Description |
|---|
name | string | Brand name |
icon_url | string | Primary logo URL |
icon_urls | string[] | Multiple logo URL sources |
URLs
GET /projects/{project_id}/prompts/{prompt_id}/urls
Returns URL-level citation data, sorted by mention count descending.
Query parameters
Same as analytics.
curl "https://topify-customer-api-production.up.railway.app/api/public/v1/projects/{project_id}/prompts/{prompt_id}/urls?duration_days=7" \
-H "X-API-Key: tk_live_..."
resp = client.get(f"/projects/{project_id}/prompts/{prompt_id}/urls", params={"duration_days": 7})
const resp = await fetch(`${BASE}/projects/${projectId}/prompts/${promptId}/urls?duration_days=7`, { headers });
Response
{
"success": true,
"data": {
"items": [
{
"url": "https://techcrunch.com/best-pm-tools-2026",
"title": "Best PM Tools 2026",
"domain": "techcrunch.com",
"url_type": null,
"url_type_name": "unknown",
"mentioned_count": 8,
"brands_appear": [
{
"name": "Acme Corp",
"icon_url": "https://logo.clearbit.com/acme.com",
"icon_urls": ["https://logo.clearbit.com/acme.com"]
}
],
"first_seen": "2026-02-15T00:00:00+00:00",
"last_seen": "2026-03-01T00:00:00+00:00"
}
]
}
}
UrlItem fields
| Field | Type | Nullable | Description |
|---|
url | string | No | Full URL |
title | string | No | Page title |
domain | string | No | Domain extracted from URL |
url_type | integer | Yes | URL type ID |
url_type_name | string | No | URL type label (e.g., unknown) |
mentioned_count | integer | No | Number of times this URL was cited |
brands_appear | BrandInfo[] | No | Brands appearing in responses that cited this URL |
first_seen | string (ISO 8601) | No | Earliest citation date |
last_seen | string (ISO 8601) | No | Most recent citation date |