How the data model nests
Organization, domains, topics, prompts, and where each analysis attaches — the mental model behind every recipe
Most "why is this field empty?" questions come down to reading a value at the wrong level of the hierarchy — this page maps what nests inside what, and which analysis hangs off which node.
The hierarchy
Everything your API key reaches nests in one chain:
- Organization owns everything the key can reach.
- Domain — one brand you track.
- Topic — holds prompts, market, language, and competitors.
- Prompt — a question asked of the models; each run produces a report.
Most recipes resolve a domainId, then a topicId, then query an analysis endpoint scoped to one of those. Identifiers are opaque strings — always read the id field, never parse or build it. Resolve them once with Find your domain id and List topics & competitors, then reuse them.
What lives on the domain
The domain object (GET /domains, GET /domains/{domainId}) carries brand-wide config:
ownedSources[]— domains you own (site plus properties); citation recipes intersect this with cited domains for owned-citation share.aliases[]— alternative brand names for matching mentions, so "Nike" and "Nike Inc." count as one.marketLanguageCodePairs[]— the market/language combos analysed, each{ id, market, languageCode }. Filter aggregated endpoints withmarketLanguageCodePairId= the pair'sid, formatted<marketCode>-<languageCode>(e.g.US-en,FR-fr).
There are no competitors at the domain level — the most common wrong assumption.
What lives on the topic
Competitors are configured per topic (GET /domains/{domainId}/topics); each topic carries its own competitors[], keywords[], market, and language.
- Market and language sit on the topic, so a domain tracked in several markets has parallel topics — one set per market — not one topic with many locales.
- The competitor names are load-bearing: they key the
competitorsmap in visibility responses (chartData[].competitors), so a comparison chart shows only competitors configured here first.
Prompts and tags
Prompts are the questions asked of the models; their runs produce the reports every analysis endpoint reads. Tags label prompts and are the only segmentation the API exposes — there is no persona query parameter.
List them with GET /tags (a bare array of { id, name, ... }, empty when none exist), then pass their id values as tagIds (comma-separated, OR semantics) to scope a visibility query. See Segment Visibility.
Where each analysis attaches
- visibility and competition — topic-scoped:
GET /domains/{domainId}/topics/{topicId}/visibility/aggregated,.../competition/aggregated. - sentiment, alignment, and Shopping — domain-scoped:
.../sentiment/aggregated,.../alignment/aggregated,.../shopping/analytics/*. - Citations and sources — domain-scoped:
.../explorer/citations,.../sources/visibility.
A topicId in the path means a per-topic view; stopping at domainId aggregates across the brand.