categoryId; existing paths and JSON field names are unchanged.| Interface | Production URL | Authentication |
|---|---|---|
| Public API | https://api.dageno.ai/llm-data-service/api/v1/llm-data/public | Authorization: Bearer API_KEY |
| MCP (Streamable HTTP) | https://api.dageno.ai/llm-data-mcp/mcp | Same key and header |
dg_live_ key in the console. Each key currently authorizes one project and accesses real data in its service environment. Do not send a login JWT, x-team-id or x-project-id to data endpoints.mcpEnabled: true). The subscription must be non-Free, active or canceling, and unexpired. This is checked on every data request. Starter access is not assumed: it requires the entitlement to be explicitly enabled. Disabling access, expiry or a downgrade to Free also blocks existing keys.GET /projects, then GET /projects/{projectId} to obtain authorized markets, brands, platforms, regions and effective limits.{
"mcpServers": {
"dagenoai-llm-data": {
"url": "https://api.dageno.ai/llm-data-mcp/mcp",
"headers": { "Authorization": "Bearer API_KEY" }
}
}
}| Parameter | Meaning |
|---|---|
| projectId | Authorized project UUID; an API path parameter or MCP argument |
| entityId | Public entity UUID returned by the service |
| responseId | Tracking response ID returned by the response list |
| startDate, endDate | Inclusive business dates in YYYY-MM-DD format; required for statistical queries |
| categoryId | Authorized L3 market UUID from market.categories; identifies a market |
| platforms, regions | Platform/region codes; Tracking accepts up to 20/50 values, Market accepts one of each. Regions use uppercase two-letter codes |
| topicIds, promptIds | Tracking topic/prompt UUIDs; up to 50/100 values |
| brands | Tracking brand domains from the configured comparison set; up to 51 |
| brandIds | Public brand UUIDs in the market comparison set; up to 100 |
| brandId | Single brand for market citations; valid only with population=brand |
| intentIds | L2 intent codes returned by an intent grouping; up to 20 |
| sourceDomain | Exact source domain, without a protocol or path |
| population | Market citations: market (default, whole market) or brand (responses mentioning the selected brand) |
| collectedAfter | Exclusive Tracking ingestion timestamp in ISO 8601 with timezone; not the annotation update time |
| pageSize, cursor | Cursor pagination; pageSize defaults to 20. Omit cursor on the first page |
| limit | Aggregate/ranking row limit; defaults to 50, or 20 for co-mentions |
platforms=chatgpt,gemini, and JSON arrays in MCP, such as "platforms":["chatgpt","gemini"]. MCP metric groupBy uses an array; citation/source groupBy is a single string.| Metric endpoint | Supported groupBy combinations |
|---|---|
| Tracking | brand, date, prompt, platform, region, topic; brand+date, brand+platform, brand+region, brand+topic, brand+prompt, platform+date |
| Market | brand, date, platform, region, intent; brand+date |
groupBy=brand,date. Grouping order may be reversed. Without a brand grouping, select at most one brand; the default is the own brand. With a brand grouping, Tracking defaults to configured brands, while Market defaults to Top N plus the own brand and configured competitors.P means /projects/{projectId} and E means P/market/entities/{entityId}. MCP path parameters are included in arguments.| Path | MCP tool | Parameters | data |
|---|---|---|---|
/projects | list_projects | Optional pageSize≤100, cursor | Project[] |
P | get_project | No query parameters | ProjectDetail |
P/tracking/topics | list_tracking_topics | Optional pageSize≤100, cursor | Topic[] |
P/tracking/prompts | list_tracking_prompts | Optional topicIds, pageSize≤100, cursor | Prompt[] |
P/tracking/metrics | get_tracking_metrics | Required dates, groupBy; optional Tracking filters, brands, limit≤10000 | MetricRow<TrackingMetrics>[] |
P/tracking/citations | get_tracking_citations | Required dates, groupBy; optional Tracking filters, sourceDomain, limit≤100 | Citation[] |
P/tracking/responses | list_tracking_responses | Required dates; optional Tracking filters, collectedAfter, pageSize≤50, cursor | TrackingResponse[] |
P/tracking/responses/{responseId} | get_tracking_response | No query parameters | TrackingResponse |
P/market/categories | list_market_categories | Required dates | MarketScope |
P/market/metrics | get_market_metrics | Required dates, categoryId, groupBy; optional Market filters, brandIds, intentIds, limit≤10000 | MetricRow<MarketMetrics>[] |
P/market/citations | get_market_citations | Required dates, categoryId, groupBy; optional Market filters, population, brandId, sourceDomain, limit≤100 | Citation[] |
P/market/responses | list_market_responses | Required dates, categoryId; optional Market filters, brandIds, intentIds, pageSize≤20, cursor | MarketResponse[] |
E | get_market_entity | Required dates | EntityDetail |
E/relations | get_market_entity_relations | Required dates; optional limit≤50 | Relation[] |
E/co-mentions | get_market_entity_co_mentions | Required dates; optional limit≤20 | CoMention[] |
E/sources | get_market_entity_sources | Required dates, groupBy; optional limit≤50 | EntitySource[] |
data and meta. Lists return a data array; details return a data object. The following TypeScript describes the JSON fields. ? means an optional field. Timestamps are ISO 8601 strings; dates are YYYY-MM-DD.type Result<T> = { data: T; meta: Meta };
type Meta = {
requestId: string; generatedAt: string;
hasMore?: boolean; nextCursor?: string | null;
truncated?: boolean; limit?: number; maxRecords?: number;
timezone?: string;
requestedRange?: { startDate: string; endDate: string };
effectiveRange?: { startDate: string; endDate: string } | null;
validDays?: number; dataAsOf?: string | null;
population?: string; aggregation?: string;
aggregations?: Record<string, string>;
metricVersion?: string; scopeVersion?: string; quality?: string;
sample?: { mode: string; size: number | null; limit: number | null };
syncLookbackDays?: number;
segmentSelection?: string;
};
type NamedCode = { code: string; name: string };
type Market = { categoryId: string; name: string };
type TrackingBrand = { domain: string; name: string; isOwn: boolean };
type MarketBrand = { entityId: string; name: string; isOwn: boolean; isConfigured: boolean };
type Budget = { used: number; limit: number; remaining: number; resetAt: string };
type Project = {
projectId: string; name: string; brand: { name: string; domain: string };
modules: { tracking: boolean; market: boolean }; capabilities: string[];
};
type ProjectDetail = Project & {
tracking: { brands: TrackingBrand[]; platforms: NamedCode[]; regions: NamedCode[];
timezone: string; dataAsOf: string | null } | null;
market: { ownBrand: MarketBrand; competitors: MarketBrand[]; categories: Market[];
platforms: NamedCode[]; regions: NamedCode[]; timezone: string; dataAsOf: string | null } | null;
limits: Record<string, number>;
budgets: { evidenceDaily: Budget; requestsDaily: Budget };
};
type Topic = { topicId: string; name: string; promptCount: number };
type Prompt = {
promptId: string; text: string; topicId: string | null;
platforms: string[]; regions: string[]; status: 'active' | 'paused';
collectionStatus: string; createdAt: string;
};type MetricRow<T> = { dimensions: Record<string, unknown>; metrics: T };
type TrackingMetrics = {
visibility: number | null; aiMention: number | null; shareOfVoice: number | null;
avgPosition: number | null; ownDomainCitationRate: number | null;
responseCount: number; mentionResponseCount: number; visibleResponseCount: number;
citedResponseCount: number; ownDomainCitedResponseCount: number;
mentionCount: number; comparisonMentionCount: number; validDays: number;
};
type MarketMetrics = {
visibility: number | null; mentionResponseCount: number; responseCount: number;
avgPosition: number | null; rankedResponseCount: number; validDays: number;
};
type Citation = {
domain: string; url: string | null; title: string | null; domainType: string;
citedResponseCount: number; citationCount: number; citationRate: number | null;
denominator: { kind: string; count: number };
};
type TrackingResponse = {
responseId: string; promptId: string; promptText: string; topicId: string | null;
platform: string; region: string; date: string; respondedAt: string; collectedAt: string;
ownBrand: { mentioned: boolean; visible: boolean; position: number | null };
answerMarkdown: string; citations: { url: string; domain: string }[];
};
type MarketResponse = {
responseId: string; question: string | null; platform: string; region: string; date: string;
excerpt: string; citationUrls: string[];
mentionedBrands: { brand: MarketBrand; position: number | null }[];
};
type MarketScope = {
authorized: Market[];
ownBrandSegments: (Market & { authorized: boolean; visibility: number | null;
mentionResponseCount: number; responseCount: number; rank: number | null })[];
};type EntityRef = { entityId: string; name: string; type: string; detailAccessible: boolean };
type EntityDetail = {
entity: EntityRef; displayAlias: string | null; domain: string | null;
parent: EntityRef | null; childCount: number;
metrics: { directResponseCount: number; rollupResponseCount: number; totalResponseCount: number;
visibility: number | null; top1Rate: number | null; avgPosition: number | null;
rankedResponseCount: number };
};
type Relation = { entity: EntityRef; relationType: 'child'; responseCount: number;
shareOfParent: number | null; avgPosition: number | null };
type CoMention = { entity: EntityRef; coMentionResponseCount: number; coMentionIndex: null };
type EntitySource = { domain: string; url: string | null; citedResponseCount: number;
citationRate: number | null; denominator: { kind: string; count: number } };{promptId,text}; topic is {topicId,name}; platform, region and intent are {code,name}.answerMarkdown and Market excerpt contain full Markdown. The existing excerpt field name is retained; it is not limited to 300 characters. Market citationUrls contains at most five URLs; links within the full response are preserved. Unmatched source types return Other.result.structuredContent, with the same JSON in result.content[].text. Backend failures have isError=true and preserve the API error fields, adding HTTP status and, when available, retryAfter. MCP does not recalculate statistics, automatically paginate or retry.| Rule | Behavior |
|---|---|
| Dates | Maximum inclusive span: 90 days. Tracking supports retained history. Market/graph start dates must be within the latest 40 UTC dates, including today; end dates allow two days of timezone grace |
| Business day | Tracking uses fixed UTC-4; Market and graph statistics use UTC |
| Pagination | Follow nextCursor with unchanged filters and pageSize; stop when null. Default cursor lifetime: 24 hours. Do not reuse across keys, projects or operations |
| Market responses | At most the first 500 responses per cursor chain, at most 20 per page. This is 25 pages at size 20 or 500 at size 1. The final page returns only the remaining records; truncated=true means more matching data exists beyond the cap |
| Lists | Default pageSize: 20. Maximum: 100 for projects/topics/prompts, 50 for Tracking responses, 20 for market responses |
| Aggregates | limit is not a page size. Citation limit: 100; child/source limit: 50; co-mention limit: 20. Date groupings return the complete series; results above 10000 rows require a smaller query |
| Market scope | Use only configured, authorized L3 markets. ownBrandSegments summarizes the own brand within configured markets; it does not query unconfigured markets. No additional monthly market-access budget applies |
| Entity scope | Limited to the own brand plus two descendant levels and configured competitors plus one level, with at most 50 entities per root/level. A listed UUID does not grant detail access: check detailAccessible. Unauthorized details return 404 |
| Relationships | Direct children only; no recursive pagination. Co-mention does not imply competition |
| Ratios | Values are 0-1; multiply by 100 for percentages. null is unavailable, not zero. Do not sum or re-average row ratios |
| Aggregation | Tracking visibility and related metrics use valid-day means; share of voice is a period ratio. Market visibility deduplicates responses over the period. Follow meta.aggregation/aggregations and denominator |
| Citations | citedResponseCount counts distinct citing responses; citationCount counts occurrences. Tracking domain rates use cited responses as denominator, while URL rates use all responses. Market citation rates use cited responses in the selected population. Graph sources may be sampled; inspect meta.sample |
| Empty data | Lists can be empty and effectiveRange can be null. Check validDays. A null dataAsOf does not imply freshness through today |
GET /projects/{projectId}.| Limit | Default / scope |
|---|---|
| Backend frequency | 60 requests/minute per key; 120/minute per team |
| Backend concurrency | 2 requests per key; 4 per team |
| Daily requests | 5000 per team |
| Daily market evidence | 500 returned responses per team; repeated reads also count |
| Entity detail access | Effective per-project daily distinct-entity allowance in limits.entityAccessDailyLimit; shared with console and Preview access. The own brand also counts; revisiting an entity on the same day does not consume another slot |
| MCP entry frequency | 60 HTTP requests/minute per key per instance; 600 total per instance, including protocol requests and invalid-key attempts |
| MCP entry concurrency | 2 per key per instance; 8 total per instance, held until the response stream ends or is canceled |
{
"error": {
"code": "INVALID_PARAMETER",
"message": "Invalid endDate",
"requestId": "44444444-4444-4444-8444-444444444444",
"details": [{ "field": "endDate", "reason": "out_of_range" }]
}
}| HTTP / code | Action |
|---|---|
| 400 INVALID_PARAMETER | Check parameters, dates, groupings or cursor |
| 401 INVALID_API_KEY | Check the key's environment, validity, expiry and revocation status |
| 403 MODULE_NOT_ENABLED / CAPABILITY_REQUIRED | Check subscription entitlement, subscription validity, module availability and key authorization |
| 404 NOT_FOUND | Resource is missing or outside the authorized scope |
| 409 PROJECT_NOT_READY | The project's data context is not ready |
| 429 RATE_LIMITED | Respect Retry-After; reduce frequency/concurrency |
| 429 QUOTA_EXCEEDED | Daily request or evidence allowance exhausted; follow resetAt |
| 429 ENTITY_ACCESS_DAILY_LIMIT_EXCEEDED | Shared project daily entity-access allowance exhausted; follow resetAt |
| 503 DEPENDENCY_UNAVAILABLE / 504 QUERY_TIMEOUT | Retry later or narrow the query |
| 500 INTERNAL_ERROR | Retain requestId for support |