Client report
Read the weekly client report for a website, built from search clicks, rank moves and the work your agent did.
/v1/client-reportFreeAPI keyThe client report is a one-week summary of a website that you can show to a client or stakeholder: how many search clicks the site got, how many tracked keywords moved up or down, and a short list of the work that was done (IndexNow submissions, outreach emails sent, notes your team chose to share).
The same data powers the Report page in the dashboard, including its client preview and PDF download. This endpoint returns the data as JSON. It is a stored-data read, not a live check, and it is not an MCP tool.
Request
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
site_id | string | Yes | none | A website id from GET /v1/websites. |
week_start | string | No | the current week | The Monday that starts the week, as YYYY-MM-DD in UTC. It must be a real Monday and not in the future. |
Weeks run Monday 00:00 UTC to the following Monday 00:00 UTC.
Example
curl "https://api.rankparse.com/v1/client-report?site_id=site_abc123&week_start=2026-09-28" \
-H "X-API-Key: rp_your_key"import requests
res = requests.get(
"https://api.rankparse.com/v1/client-report",
headers={"X-API-Key": "rp_your_key"},
params={"site_id": "site_abc123", "week_start": "2026-09-28"},
)
data = res.json()
print(data["frozen"], data["report"]["kpis"])const params = new URLSearchParams({
site_id: "site_abc123",
week_start: "2026-09-28",
});
const res = await fetch(`https://api.rankparse.com/v1/client-report?${params}`, {
headers: { "X-API-Key": "rp_your_key" },
});
const { report, frozen } = await res.json();
console.log(frozen, report.kpis);Response
{
"report": {
"week_start": "2026-09-28",
"kpis": {
"clicks_28d": 4210,
"clicks_prev_28d": 3874,
"queries_up": 18,
"queries_down": 7,
"window_end": "2026-10-01"
},
"events": [
{
"id": "act_Qm3N8vLp2Xw5Zt9RbYk1C",
"verb": "indexnow.submitted",
"occurred_at": 1790596800000,
"params": { "url_count": 12, "host": "example.com" },
"agent_text": null
},
{
"id": "act_Zr7Tn4Kc9Ve2Ls6HdWq8M",
"verb": "rank.moves_detected",
"occurred_at": 1790683200000,
"params": { "up": 5, "down": 2, "date": "2026-09-29" },
"agent_text": null
},
{
"id": "act_Bp1Yw5Mj3Ux8Gf2NaCt6E",
"verb": "outreach.sent_daily",
"occurred_at": 1790769600000,
"params": { "count": 20, "date": "2026-09-30" },
"agent_text": null
}
]
},
"frozen": true
}Response fields
| Field | Type | Description |
|---|---|---|
report.week_start | string | The Monday the report covers. |
report.kpis.clicks_28d | integer or null | Google clicks in the 28 days ending on window_end. null when the website has no active primary Google Search Console property. |
report.kpis.clicks_prev_28d | integer or null | Google clicks in the 28 days before that window, for comparison. null in the same case. |
report.kpis.queries_up | integer | Tracked-keyword moves up detected during the week (entering the top 3 or top 10, moving up, new rankings). |
report.kpis.queries_down | integer | Tracked-keyword moves down detected during the week (leaving the top 3 or top 10, moving down, lost rankings). |
report.kpis.window_end | string | Last day of the current 28-day window, YYYY-MM-DD. Always present. |
report.events | object[] | The week's client-visible activity, oldest first, at most 500. |
report.events[].id | string | Activity id (act_...). |
report.events[].verb | string | What happened. See the table below. |
report.events[].occurred_at | integer | Unix time in milliseconds. |
report.events[].params | object | A small set of fields per verb. Anything else is stripped. |
report.events[].agent_text | string or null | Text written by an agent, present only when a team member shared it with the client. |
frozen | boolean | true when the week was published and is served from its saved snapshot; false when it was computed just now. |
Events a client can see
| Verb | params | Meaning |
|---|---|---|
indexnow.submitted | url_count, host | URLs were submitted to IndexNow. |
outreach.sent_daily | count, date | Outreach emails were sent that day. |
rank.moves_detected | up, down, date | Tracked keywords moved up or down that day. |
agent.note, task.completed | none | A note or task summary a team member chose to share. The text is in agent_text. |
Internal activity (approvals, policy changes, call counts, credits, team and client changes) is never part of a client report. An agent note or task summary stays private to the team until someone shares it.
How a week is produced
- Current or open week: computed from live data on every request (
frozen: false). Numbers can change as the week goes on. - Published week: every Monday from 07:00 UTC, an hourly job saves the previous week for each website that had client-visible activity in it. Once saved, that week never changes, even if an event is added to it later, and requests for it return
frozen: true. - No activity that week: a website with search data but no client-visible events is not saved, so it is computed live each time and is always
frozen: false. - Search data lag: both 28-day windows end 3 days before the last day of the week, so the click numbers are complete and do not shift after the report is published.
- Saved weeks are kept for 400 days.
Behavior and limits
- Cost: 0 credits.
- Rate limit: 60 requests per minute per key.
- Dates:
week_startmust be a Monday.2026-09-29(a Tuesday) is rejected. - Rank moves need alerts on.
queries_up,queries_downand therank.moves_detectedevents come from the daily rank-change detection, which runs only for websites with rank-change alerts enabled. Without that, they stay at0. See the alert settings. - No data: a new website returns a valid report with
queries_upandqueries_downat0, an emptyeventsarray and, without Search Console,nullclicks. - Scope: only your own workspace's websites. A
site_idfrom another workspace returns the same404as a site that does not exist.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_client_report_input | site_id is missing, or week_start is not a Monday in YYYY-MM-DD form or is in the future. |
| 401 | invalid_api_key | Missing, invalid or revoked API key. |
| 404 | site_not_found | The website does not exist in your account. |
| 429 | rate_limited | More than 60 requests in a minute. |
See Error codes.