#Dashboards
Status: Available —
GET /dashboards/overviewandGET /dashboards/pulse. Planned — embedding dashboards by a signed token (stage 4). The internal fields of the "Overview" blocks may grow;availabilityanddata_as_ofin every block are stable.
Purpose: get ready-made slices of the "Overview" and "Pulse" screens in one request, so you can show them in your own system without assembling them from separate methods. The slices contain aggregates only.
#Contents
- When to use it
- Access
- GET /dashboards/overview
- GET /dashboards/pulse
- Data freshness
- Embedding by signed token
- Errors
- Examples
- Open questions
#When to use it
| You need | Method |
|---|---|
| To show Overview in your own app or BI tool | GET /dashboards/overview |
| To receive alerts about growing demand topics | GET /dashboards/pulse |
| Your own charts for specific metrics | Reading analytics |
| To show a dashboard on a third-party site with no backend | embedding (stage 4) |
#Access
| Base address | https://<cell domain>/api/public/v1 (RU https://formula-cream.pro, EN https://wfacademy.org, ID https://wfacademy.id) |
| Authentication | Authorization: Bearer <key> |
| Scope | dashboards:read (Authentication) |
| Paid | no |
| Personal data | none |
| Read limit | 600 requests per minute (Conventions) |
#GET /dashboards/overview
A slice of the "Overview" screen: the strategic summary, key indicators, the funnel, and additional blocks. The data is the same as a dashboard employee sees, without the controls.
#Query parameters
| Parameter | Type | Required | Constraints | Example |
|---|---|---|---|---|
from | string | no | a YYYY-MM-DD date; by default, 28 days before to | 2026-10-01 |
to | string | no | a date not earlier than from; by default, and for a value later than yesterday (UTC), the last complete day; the actual boundary is returned in the response to | 2026-10-28 |
blocks | string | no | a comma-separated list of blocks; by default all eleven; an unknown name gives 422 (unknown_block), as does a repeat. Blocks in the response follow the screen order, not the request order | kpi,funnel |
Block windows with a fixed period (for example, clusters is 30 days, status is the cost of articles over 30 days) do not depend on from and to. The days parameter is a dashboard detail and is absent from the public API.
#Blocks
Block (key) | What it contains | Source in the dashboard |
|---|---|---|
strategist | the strategist strip: a short conclusion of the latest report | the AI strategist report |
kpi | five tiles: impressions, clicks, sessions, people from AI assistants, revenue. Search engines in "both" mode are not summed | summary indicators |
funnel | the funnel "impressions → clicks → sessions → leads → deals → revenue" (description) | funnel |
attention | what needs attention: analyst findings, report conclusions, funnel anomalies, suspicious bots | attention list |
ads | an advertising summary for the period | ad accounts |
ai_assistants | visits from AI assistants and AI crawlers: the bot classes user_fetch, ai_search, training, people from assistants, a check for bot spoofing | the "AI assistants" block |
popular_pages | popular pages by channel: from AI and from search (8 each) | popular pages |
clusters | active query clusters: at least 100 impressions over 30 days and at least 10 keys | clusters |
data_trust | the data trust index from 0 to 100 (source reconciliation); "0" with no source pairs means "not collected", not "the data is bad" | data trust |
sitemap_health | sitemap health | sitemap |
status | the status line: infrastructure and proxies, domain authority, rich markup, the cost of articles over 30 days, reviews, external links | status line |
Each block carries its own availability and data_as_of (an object {source: date}), like the funnel and visibility sections (Reading analytics). Money in blocks is an object {"amount", "currency"}.
#Response (abridged)
{
"data": {
"from": "2026-10-01",
"to": "2026-10-28",
"blocks": {
"kpi": {
"availability": "ok",
"data_as_of": { "g:search_console": "2026-10-25", "tracker": "2026-10-28", "crm": "2026-10-28" },
"tiles": [
{ "key": "impressions", "current": 182400, "prev": 171900, "delta_pct": 6.1 },
{ "key": "clicks", "current": 4210, "prev": 3880, "delta_pct": 8.5 },
{ "key": "sessions", "current": 3920, "prev": 3601, "delta_pct": 8.9 },
{ "key": "ai_people", "current": 212, "prev": 140, "delta_pct": 51.4 },
{ "key": "revenue", "current": { "amount": "5240.00", "currency": "GBP" }, "prev": { "amount": "4100.00", "currency": "GBP" }, "delta_pct": 27.8 }
]
},
"funnel": { "availability": "ok", "data_as_of": { "g:search_console": "2026-10-25", "crm": "2026-10-28" }, "steps": [ ] },
"ai_assistants": { "availability": "ok", "data_as_of": { "tracker": "2026-10-28" } }
}
}
}
The structure inside the blocks is shown in abridged form. The standing rule is availability (ok, no_data, no_source, not_connected), an optional reason, and data_as_of in every block; other block fields may grow, and the client ignores them. kpi tiles carry their own availability. A read failure of any block gives 503 for the whole request: a block is never replaced by an empty one.
#GET /dashboards/pulse
A slice of the "Promotion → Pulse" screen (promo/insights/pulse, also called "Findings and Pulse" in the dashboard): demand topics that have started to grow. Other screens with a similar name are not part of the public API. Each finding rests on several signal sources, each with its own outcome (spike means a surge) and comparison base.
#Query parameters
| Parameter | Type | Required | Constraints | Example |
|---|---|---|---|---|
from | string | no | a YYYY-MM-DD date; by default, 28 days before to | 2026-09-13 |
to | string | no | a date not earlier than from; by default, and for a value later than yesterday (UTC), the last complete day; the actual boundary is returned in period.to | 2026-10-10 |
#Response
{
"data": {
"period": { "from": "2026-09-13", "to": "2026-10-10" },
"new_7d": 3,
"truncated": false,
"alerts": [
{
"id": "alert_EXAMPLE_01",
"topic_id": "topic_EXAMPLE_01",
"topic_name": "Ниацинамид и пористость",
"keyword": "ниацинамид для пор",
"horizon": "short",
"status": "open",
"episode_start": "2026-10-04",
"last_seen": "2026-10-10",
"score": 0.82,
"volume": 3400,
"growth": 2.4,
"sources": [
{ "code": "serp_suggest", "outcome": "spike", "value": 120, "base": 50 }
],
"strategist_topic": { "id": "tpc_EXAMPLE_01", "status": "proposed" }
}
],
"data_as_of": { "pulse": "2026-10-10" }
}
}
| Field | Type | Description |
|---|---|---|
period | object | the period boundaries: from, to |
new_7d | integer | how many findings appeared in the last 7 days |
truncated | boolean | the list was cut by size; narrow the period |
alerts[].id, topic_id | string | identifiers of the finding and the topic |
alerts[].topic_name, keyword | string | the topic and the query |
alerts[].horizon | string | the finding's horizon |
alerts[].status | string | the finding's state |
alerts[].episode_start, last_seen | string | the start of the episode and the last confirmation |
alerts[].score, volume | number | the score and the demand volume |
alerts[].growth | number | null | growth: the maximum of the "value / base" ratio among sources with the outcome spike; null if the base is zero |
alerts[].sources | array | signal sources: code, outcome, value, base |
alerts[].strategist_topic | object | null | the linked strategist queue topic (id, status) or null |
data_as_of | object | the date up to which the Pulse sources' data is complete |
The evidence text (evidence.text) is not returned. A topic cannot be accepted for work through this method: reading is separate from action; strategist queue topics are approved and rejected by separate methods of the /strategist/topics resource (Strategist). The ceo/pulse screen is not part of the public API.
The values of the horizon, status, and source code fields in the example are illustrative; the list of values will be finalized.
#Data freshness
Each block reports data_as_of, an object {source: date}: the date through which each source's data is complete. Search consoles lag by 2–3 days; do not mistake the missing days for a drop. See Reading analytics for details.
#Embedding by signed token
Status: Planned. Embedding belongs to stage 4, together with the sandbox.
The idea: instead of passing an API key to a third-party site, your server obtains a short-lived signed dashboard token and outputs an <iframe> with the ready-made slice. The token is limited to one tenant, one slice, and an expiry time; the API key never leaves your server.
What is known at this stage:
- the token is issued by your server using the API key (parameters, lifetime, and format are defined at stage 4);
- the embedded dashboard shows aggregates only;
- embedding requires a separate
frame-ancestors/CORS policy set in the tenant's settings.
Embedding is not available yet. For integrations, use server-side reading with a key for now.
#Errors
The format is application/problem+json; the shared catalog is in the Conventions.
| HTTP | Code | When |
|---|---|---|
| 422 | validation_failed | to earlier than from; an unknown block in blocks |
| 401 | invalid_api_key | the key is wrong, revoked, or expired |
| 403 | scope_missing | the dashboards:read scope is missing |
| 403 | ip_not_allowed | the request comes from an address outside the integration's IP list |
| 429 | rate_limited | the limit was exceeded |
| 5xx | n/a | a read error; a block is not replaced with an empty value |
#Examples
curl -sS 'https://formula-cream.pro/api/public/v1/dashboards/overview?from=2026-10-01&to=2026-10-28' \
-H 'Authorization: Bearer sap_ru_live_EXAMPLE0KEYI_EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLE'
const response = await fetch('https://wfacademy.org/api/public/v1/dashboards/pulse?from=2026-09-13&to=2026-10-10', {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
const { data } = await response.json();
for (const alert of data.alerts) console.log(alert.topic_name, alert.growth);
import os, requests
r = requests.get(
"https://wfacademy.id/api/public/v1/dashboards/overview",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
params={"from": "2026-10-01", "to": "2026-10-28"},
timeout=10,
)
r.raise_for_status()
print(list(r.json()["data"]["blocks"]))
#Open questions
- Technical. The embedding token format, its lifetime, the set of permitted slices, and the
frame-ancestorspolicy are defined at stage 4. - Technical. The set of blocks and the
blocksparameter. The design names "ready-made slices" as a whole; the block list is taken from the dashboard, and choosing blocks by a parameter is a proposal. - For the owner. Infrastructure blocks (proxies, domain authority, article cost): whether it is appropriate to expose them in the external API has not been decided.
- Technical. Uniform periods. Some dashboard blocks are calculated over a fixed window (30 days); how to present this when
fromandtoare set will be finalized in OpenAPI.