Documentation Index
Fetch the complete documentation index at: https://docs.appeeky.com/llms.txt
Use this file to discover all available pages before exploring further.
An intent is a user goal that an AI assistant might be asked to recommend an app for. Each intent powers one row in the dashboard table — visibility %, sentiment, average position, top apps shown for it.
Intents are generated for you when you call bootstrap, but you can also add, rename, pause, or archive them at any time. Adding your own intents (e.g. “Help me journal in Turkish”) is the way to expand AI Visibility coverage beyond what the LLM proposed.
This page covers all intent endpoints:
| Endpoint | Purpose |
|---|
GET /v1/ai-visibility/:appId/intents | List with metrics — drives the dashboard table |
GET /v1/ai-visibility/:appId/intents/:intentId | Drill-down: prompts + latest AI answers |
POST /v1/ai-visibility/:appId/intents | Manually add an intent |
PATCH /v1/ai-visibility/:appId/intents/:intentId | Rename / pause / archive |
DELETE /v1/ai-visibility/:appId/intents/:intentId | Archive (soft delete) |
List intents with metrics
GET /v1/ai-visibility/:appId/intents
The data shown in the Intent Performance table on the dashboard.
Query parameters
| Name | Type | Default | Description |
|---|
| country | string | us | ISO country code |
| model | string | chatgpt | One of chatgpt, claude, gemini, perplexity — metrics are scored per model |
Response
{
"data": [
{
"intentId": "9c1f...",
"label": "Build a regular meditation practice",
"description": "User wants an app that helps them meditate consistently every day.",
"status": "active",
"source": "llm",
"visibilityPct": 78,
"sentimentPct": 71,
"positionAvg": 2,
"promptsTotal": 6,
"topApps": [
{ "trackId": "571800810", "name": "Calm", "isOwnerApp": false },
{ "trackId": "493145008", "name": "Headspace", "isOwnerApp": false },
{ "trackId": "1234567890","name": "Sleepwell", "isOwnerApp": true }
]
},
{
"intentId": "a7b2...",
"label": "Fall asleep faster and unwind",
"description": "...",
"status": "active",
"source": "user",
"visibilityPct": 75,
"sentimentPct": 84,
"positionAvg": 2,
"promptsTotal": 6,
"topApps": [ /* ... */ ]
}
]
}
| Field | Description |
|---|
intentId | UUID — use this for drill-down or update calls. |
label | Display text, sentence-case. |
description | One-sentence explanation of the user goal. May be null for legacy or manually-added intents. |
status | active (scanned daily), paused (kept around but not scanned), archived (hidden from list endpoints). |
source | llm (generated by the bootstrap), user (you added it manually). |
visibilityPct | % of this intent’s prompts where your app appeared, position-weighted. |
sentimentPct | Average tone of the assistant when it mentioned your app, on a 0–100% scale. null if you weren’t mentioned at all. |
positionAvg | Average rank in the assistant’s list when your app was mentioned. null if you weren’t mentioned. |
promptsTotal | Number of active prompts under this intent (those used in the most recent scan). |
topApps | Up to 3 apps most frequently surfaced for this intent in the latest scan. isOwnerApp: true marks your own app. |
Drill into one intent
GET /v1/ai-visibility/:appId/intents/:intentId
Returns the same fields as the row above plus the prompts under that intent and the most recent AI answers for each prompt.
Query parameters
| Name | Type | Default | Description |
|---|
| country | string | us | ISO country code |
| model | string | chatgpt | Filters the latest answers to this model |
Response (truncated)
{
"data": {
"intentId": "9c1f...",
"label": "Reduce stress and anxiety to feel calm",
"description": "...",
"status": "active",
"source": "llm",
"visibilityPct": 73,
"sentimentPct": 71,
"positionAvg": 1,
"promptsTotal": 6,
"topApps": [ /* ... */ ],
"prompts": [
{
"promptId": "p123...",
"text": "Which app offers quick calming exercises for panic or high stress?",
"style": "problem",
"status": "active",
"source": "llm",
"latestAnswers": [
{
"answerId": "a789...",
"modelSlug": "chatgpt",
"fetchedAt": "2026-05-12T08:14:02.000Z",
"apps": [
{ "position": 1, "name": "Calm", "trackId": "571800810", "isOwnerApp": false },
{ "position": 2, "name": "Headspace", "trackId": "493145008", "isOwnerApp": false },
{ "position": 3, "name": "Sleepwell", "trackId": "1234567890", "isOwnerApp": true }
]
}
]
}
]
}
}
The prompts[].latestAnswers[].apps list is ordered by position. apps[].trackId is null when the assistant mentioned an app we couldn’t confidently match against the App Store (very rare brands or a misspelling).
For the raw model output and parsed sentiment per app, use GET /answers/:answerId with the answerId returned here.
Add an intent manually
POST /v1/ai-visibility/:appId/intents
Useful when:
- The LLM bootstrap missed something (e.g. a niche use case).
- You’re launching a new feature and want to start tracking visibility for it before the first scan.
- You want to track a specific competitor angle (“Apps similar to Calm”).
After insertion, generate prompts for it via POST /intents/:intentId/prompts — until at least one active prompt exists, the intent won’t be scanned.
Body
{
"label": "Help me journal in Turkish",
"description": "Turkish-speaking user wants an app to keep a daily journal."
}
| Field | Type | Required | Description |
|---|
label | string | Yes | Sentence-case user goal, 8–80 chars |
description | string | No | One-sentence explanation, ≤ 200 chars |
Response
{
"data": {
"id": "f8a7...",
"label": "Help me journal in Turkish",
"description": "Turkish-speaking user wants an app to keep a daily journal.",
"status": "active",
"source": "user",
"fingerprint": "ab12cd34..."
}
}
fingerprint is a content hash. Re-posting the same label is safe — it returns the existing intent rather than creating a duplicate.
Update / pause / archive
PATCH /v1/ai-visibility/:appId/intents/:intentId
{
"label": "Build a daily meditation habit",
"description": "Optional new description.",
"status": "active"
}
All three fields are optional. Use status: "paused" to keep the intent and its prompts visible but stop sending them to the AI models in the next scan. Use status: "archived" (or DELETE) to hide it everywhere.
Delete (archive)
DELETE /v1/ai-visibility/:appId/intents/:intentId
Soft-archive — the intent and its prompts/answers remain in the database but won’t show up in list endpoints or be sent in future scans. Equivalent to PATCH { status: "archived" }.
Code examples
# Dashboard table
curl "https://api.appeeky.com/v1/ai-visibility/1234567890/intents?model=chatgpt" \
-H "X-API-Key: YOUR_API_KEY"
# Drill into one intent
curl "https://api.appeeky.com/v1/ai-visibility/1234567890/intents/9c1f...?model=chatgpt" \
-H "X-API-Key: YOUR_API_KEY"
# Manually add an intent
curl -X POST "https://api.appeeky.com/v1/ai-visibility/1234567890/intents" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "label": "Help me journal in Turkish" }'
# Pause an intent
curl -X PATCH "https://api.appeeky.com/v1/ai-visibility/1234567890/intents/9c1f..." \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "paused" }'
Credits
| Endpoint | Cost |
|---|
GET /intents | 2 credits |
GET /intents/:intentId | 2 credits |
POST /intents | 1 credit |
PATCH /intents/:intentId | Free |
DELETE /intents/:intentId | Free |
Errors
| Status | Code | When |
|---|
| 400 | INVALID_INPUT | label shorter than 8 characters or status is not one of the allowed values |
| 404 | NOT_FOUND | Intent doesn’t exist or doesn’t belong to this app |
| 401 | — | Missing or invalid API key / JWT |
| 429 | — | Insufficient monthly credits |
See also
- Prompts — manage the queries each intent sends to the assistants
- Answers — drill into a single AI response
- Bootstrap — initial intent generation