Keys
Send your key on every call as Authorization: Bearer ck_live_… (the key itself starts ck_live_). It is shown once, when you create it, and never sent by email.
read scope- Every GET endpoint.
ask scope- POST /ask, cited answers. Pro keys only.
Apply for a free key, then create, revoke and watch it on your keys page. A revoked key answers 401 invalid_key within a minute.
Limits and headers
Limits are per account (every key on it, REST and MCP together), per minute and per 24 hours from the account’s first call of the window; the numbers per tier are on . A blocked request does not use up quota. Every answer carries:
X-RateLimit-Limit- Requests allowed in the window (the day window unless a minute limit was hit).
X-RateLimit-Remaining- Requests left in the window.
X-RateLimit-Reset- Unix time (seconds, UTC) when the window resets.
X-Request-ID- Quote it when you write to us.
Retry-After- On a 429: seconds until the window that blocked you resets.
Errors
An error is JSON: { "error": "<code>", "message": "…" }. A 429 adds limit, retry_after and how_to_get_more.
Error codes| Status | Code and meaning |
|---|
| 400 | invalid_request A parameter or the body is missing or malformed; the message names it. |
| 401 | auth_required No key was sent. |
| 401 | invalid_key The key was revoked, expired or never issued. |
| 403 | insufficient_scope The key lacks the scope the endpoint needs (read or ask). |
| 403 | pro_required The endpoint, or an option such as a longer Watch window, comes with Pro. |
| 404 | not_found No public signal or brand has that slug. |
| 410 | not_offered A surface we no longer offer (webhooks): poll /signals with since= or a cursor. |
| 429 | rate_limited The minute window is full: retry after Retry-After seconds. |
| 429 | quota_exhausted The day is spent: stop until X-RateLimit-Reset. |
| 429 | ask_quota The account has used its questions for the day, site and API together. |
| 500 | server_error Our side failed. Retry in a moment; quote X-Request-ID if you write to us. |
Endpoints
GET /api/v1/signals
Latest moves in Indian retail, newest first.
Public signals, 20 per page (max 50). Resurfaced old news is left out. Pass next_cursor back as cursor for the next page; with kind set a page can hold fewer items than limit, so keep going until next_cursor is null.
Example GET /api/v1/signals?brand=zepto&limit=3
Parameters| Name | What it does |
|---|
brandstring | Brand slug (as in /brand/<slug>). Stories ABOUT the brand unless mentions=true. |
|---|
mentionsboolean | Also include stories that only mention the brand |
|---|
themestring | Theme slug (as in /theme/<slug>), e.g. store-opening |
|---|
kindMove | Kind of move |
|---|
sincestring (ISO 8601) | ISO 8601 date or time; only moves published at or after it |
|---|
limitinteger | 1–50 Default 20. |
|---|
cursorstring | next_cursor from the previous page |
|---|
Also answers 400, 401, 403, 429 (errors).
GET /api/v1/signals/{slug}
One move: what happened, why it matters, what to watch.
Parameters| Name | What it does |
|---|
slugrequiredpath segment, string | Signal slug (as in /signal/<slug>) |
|---|
Also answers 301, 401, 403, 404, 429 (errors).
GET /api/v1/brands/{slug}
A brand: its coverage, last 30 days by kind of move, and its 10 latest moves.
Example GET /api/v1/brands/dmart
Parameters| Name | What it does |
|---|
slugrequiredpath segment, string | Brand slug (as in /brand/<slug>) |
|---|
Returns| Field | What it holds |
|---|
brandobject | — |
|---|
brand.namestring | — |
|---|
brand.slugstring | — |
|---|
brand.urlstring | — |
|---|
brand.storiesinteger | Distinct stories that name it |
|---|
brand.stories_aboutinteger | Stories about it |
|---|
brand.first_seen_atstring or null | — |
|---|
brand.last_seen_atstring or null | — |
|---|
brand.last_30_daysobject or null | — |
|---|
brand.themesobject[] | — |
|---|
brand.related_brandsobject[] | — |
|---|
brand.top_outletsobject[] | — |
|---|
latestSignalItem[] | See SignalItem[]. |
|---|
Also answers 301, 401, 403, 404, 429 (errors).
GET /api/v1/search
Find brands, themes and moves.
Example GET /api/v1/search?q=quick+commerce
Parameters| Name | What it does |
|---|
qrequiredstring | 2–100 characters; moves match words in the headline, deck and summary |
|---|
Returns| Field | What it holds |
|---|
querystring | — |
|---|
brandsobject[] | — |
|---|
brands[].namestring | — |
|---|
brands[].slugstring | — |
|---|
brands[].urlstring | — |
|---|
brands[].storiesinteger | — |
|---|
brands[].last_seen_atstring or null | — |
|---|
themesobject[] | — |
|---|
themes[].slugstring | — |
|---|
themes[].urlstring | — |
|---|
themes[].storiesinteger | — |
|---|
signalsSignalItem[] | See SignalItem[]. |
|---|
Also answers 400, 401, 403, 429 (errors).
GET /api/v1/watch
Competitor Watch: what a set of brands did, side by side, by kind of move.
Counts of public, dated, source-cited stories about each brand (one event counts once), against the equal window before. Free keys: up to 5 brands over 7 days. Pro: up to 25 brands over 7, 30, 90 days.
Example GET /api/v1/watch?b=blinkit,zepto&days=7
Parameters| Name | What it does |
|---|
brequiredstring | Comma-separated brand slugs, e.g. blinkit,zepto,instamart (a retired slug resolves to the brand it now redirects to) |
|---|
daysinteger: 7 | 30 | 90 | Window: 7 | 30 | 90 Default 7. |
|---|
Returns| Field | What it holds |
|---|
window_daysinteger | — |
|---|
sincestring | — |
|---|
untilstring | — |
|---|
brandsobject[] | — |
|---|
brands[].namestring | — |
|---|
brands[].slugstring | — |
|---|
brands[].urlstring | — |
|---|
brands[].totalinteger | — |
|---|
brands[].prior_totalinteger | — |
|---|
brands[].by_moveobject | — |
|---|
brands[].prior_by_moveobject | — |
|---|
brands[].citiesstring[] | — |
|---|
brands[].latestobject[] | — |
|---|
quietstring[] | Brands with no story about them in twice the window |
|---|
Also answers 400, 401, 403, 429 (errors).
GET /api/v1/brief
Today's brief: the most widely reported moves, each with why it matters and what to watch.
The same read as the 07:30 IST email brief, optionally narrowed to stories about the given brands and/or to themes.
Example GET /api/v1/brief?brands=dmart,zepto
Parameters| Name | What it does |
|---|
brandsstring | Comma-separated brand slugs |
|---|
themesstring | Comma-separated theme slugs |
|---|
hoursinteger | Look-back window, 1–72 Default 24. |
|---|
Returns| Field | What it holds |
|---|
datestring | IST date, YYYY-MM-DD |
|---|
labelstring | — |
|---|
window_hoursinteger | — |
|---|
filtersobject | — |
|---|
filters.brandsstring[] | — |
|---|
filters.themesstring[] | — |
|---|
itemsBriefItem[] | See BriefItem[]. |
|---|
Also answers 400, 401, 403, 429 (errors).
POST /api/v1/ask
A cited answer over Indian retail moves (Pro). Pro keys only.
Pro keys with the ask scope. Counts against the account's 200 questions a day (site and API together). Set stream=true for server-sent events.
Body (JSON)| Field | What it holds |
|---|
messagesobject[] | The last message is the question |
|---|
messages[].rolestring: user | — |
|---|
messages[].contentstring | 1–500 characters |
|---|
streamboolean | — |
|---|
Returns| Field | What it holds |
|---|
contentstring | Markdown answer; [sig_…] marks a cited signal |
|---|
citationsobject[] | — |
|---|
confidencenumber | — |
|---|
request_idstring | — |
|---|
Also answers 400, 401, 403, 429 (errors).
Fields
Move
What kind of move: stores, deals (funding, M&A, listings), people, results (and outlook), launches (and pricing), strategy, rules (regulation, legal), other.
One of stores, deals, people, results, launches, strategy, rules, other.
BrandRef
BrandRef fields| Field | What it holds |
|---|
namestring | — |
|---|
slugstring | — |
|---|
urlstring | Brand page on retailintel.in |
|---|
rolestring: primary | secondary | primary = the story is about the brand; secondary = a mention |
|---|
Source
Source fields| Field | What it holds |
|---|
outletstring or null | Publisher name |
|---|
urlstring or null | Link to the original report |
|---|
SignalItem
SignalItem fields| Field | What it holds |
|---|
idstring | Stable id |
|---|
slugstring | Stable slug |
|---|
urlstring | Canonical page on retailintel.in — cite this |
|---|
headlinestring | — |
|---|
deltastring or null | The move in one figure, e.g. "+₹425 cr Series D" |
|---|
summarystring or null | One-sentence answer |
|---|
moveMove | See Move. |
|---|
kindstring or null | Editorial kind, e.g. "EXPANSION · E-COMMERCE" |
|---|
themeobject or null | — |
|---|
theme.slugstring | — |
|---|
theme.urlstring | — |
|---|
brandsBrandRef[] | See BrandRef[]. |
|---|
citiesstring[] | — |
|---|
published_atstring (ISO 8601) | ISO 8601, when RetailIntel published it |
|---|
event_atstring or null | ISO 8601, when it happened, when known |
|---|
sourceSource | See Source. |
|---|
outletsinteger | Publishers that reported it |
|---|
SignalDetail
Everything in SignalItem, plus:
SignalDetail fields| Field | What it holds |
|---|
deckstring or null | — |
|---|
why_it_mattersstring or null | Why it matters, from the stored analysis |
|---|
what_to_watchstring or null | What to watch next |
|---|
key_factsstring[] | — |
|---|
BriefItem
BriefItem fields| Field | What it holds |
|---|
headlinestring | — |
|---|
urlstring | — |
|---|
deltastring or null | — |
|---|
why_it_mattersstring or null | — |
|---|
what_to_watchstring or null | — |
|---|
brandstring or null | — |
|---|
sourceSource | See Source. |
|---|
other_outletsinteger | — |
|---|
published_atstring (ISO 8601) | — |
|---|
Error
Error fields| Field | What it holds |
|---|
errorstring | Machine-readable code |
|---|
messagestring | What happened and what to do |
|---|
RateLimited
Everything in Error, plus:
RateLimited fields| Field | What it holds |
|---|
errorstring: rate_limited | quota_exhausted | ask_quota | rate_limited (the minute window; retry after Retry-After) or quota_exhausted (the day is spent) |
|---|
limitobject | — |
|---|
limit.windowstring: minute | day | — |
|---|
limit.maxinteger | — |
|---|
limit.planstring: free | pro | — |
|---|
retry_afterinteger | Seconds |
|---|
how_to_get_morestring | — |
|---|
upgradestring | — |
|---|
MCP server
/mcp speaks MCP over Streamable HTTP, read-only. Without a key it allows 50 tool calls a day and 30 a minute per caller; from Claude, ChatGPT, Perplexity or Muse’s own servers each connector session counts on its own, inside a shared 2,000 a day per assistant. With a key (Authorization: Bearer or X-API-Key) calls count against the key’s account, as REST calls do.
Over a limit, the tool answers isError: true with a sentence that names the reset time in IST; it never answers 401 for a limit. A key that is not active gets 401 and a JSON-RPC error.
Tools| Tool | What it answers |
|---|
latest_moves | What moved in Indian retail, newest first; by brand, theme or kind of move. |
|---|
get_signal | One move in full: why it matters, what to watch, key facts, source; MCP Apps hosts show it as a card with its chart. |
|---|
brand_profile | One brand's last 30 days against the 30 before, by kind, with its latest moves; MCP Apps hosts show our read, key numbers, its chart and rivals as a card. |
|---|
compare_brands | Competitors side by side (Competitor Watch); MCP Apps hosts show the table and a chart. |
|---|
daily_brief | This morning's most widely reported moves, as the 07:30 IST email carries them; MCP Apps hosts show each move with its chart. |
|---|
get_expansion_map | Who is opening where: one city or mall — openings by category and mall, who to pitch, and every opening with its report. |
|---|
get_group | One group (Tata, Reliance, Aditya Birla, DMart's Avenue…): its businesses' season so far, the revenue-growth chart as HTML, key numbers, moves and what to watch. |
|---|
get_leadership_moves | Who joined, left or was promoted at Indian retail and consumer companies: the week's count, our read for your role, the seats to watch, and every move with its report; by company, sector or lens. |
|---|
search | Find brands, themes and moves. |
|---|
fetch | The full text of one search result. |
|---|
Each tool’s arguments come with tools/list. Discovery: server card and manifest.
get_signal is also an MCP App: it links the card ui://retailintel/signal-card.html (text/html;profile=mcp-app) and returns structuredContent for it, so a host that shows MCP Apps draws the move with its chart. Any other client reads the same text. Reading the card spends no tool call.