> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rankraft.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Response format and pagination

> The info/data envelope, cursors, dates and rounding.

## The envelope

List and report endpoints return `info` and `data`:

```json theme={"system"}
{
  "info": {
    "site_id": "3f2c9a10-…",
    "start_date": "2026-09-01",
    "end_date": "2026-09-30",
    "count": 50,
    "total_results": 132,
    "next_cursor": "eyJvIjo1MCwicSI6Ij…"
  },
  "data": [ { … }, { … } ]
}
```

Rows use **named fields**, never positional arrays. A report row carries the `group_by` dimensions you asked for plus the metrics you asked for, and nothing else.

## Pagination

Pass `limit` for the page size and, for the next page, `cursor` set to the previous response's `info.next_cursor`. `next_cursor` is `null` on the last page.

A cursor belongs to the query that produced it. Changing anything except `limit` — dates, filters, grouping — and reusing the cursor returns `400 invalid_cursor` rather than a silently wrong page.

```python theme={"system"}
cursor = None
while True:
    body = {**query, **({"cursor": cursor} if cursor else {})}
    page = requests.post(f"{BASE}/v1/reports/citations", json=body, headers=HEADERS).json()
    rows.extend(page["data"])
    cursor = page["info"]["next_cursor"]
    if not cursor:
        break
```

## Dates

* `start_date` and `end_date` are **inclusive** calendar days, `YYYY-MM-DD`.
* Answer reports use **UTC days**, the days RankRaft's daily scans are filed under. Answers exist once a day, so finer time slices do not exist.
* Traffic reports (`/v1/reports/bots`, `/v1/reports/referrals`) take an optional IANA `timezone` (default `UTC`) for day boundaries and for `date` and `hour` buckets.
* Answer reports span at most **92 days**; traffic reports at most **400 days**.
* Timestamps in responses are ISO 8601 in UTC (`2026-10-16T09:00:00.000Z`).

## Numbers

* `visibility_score` is **0–100**, as on the dashboard.
* Rates and shares (`mention_rate`, `citation_rate`, `prompt_coverage`, `share_of_voice`, `citation_share`, sentiment shares, `verified_share`) are **fractions from 0 to 1**.
* `average_position` is 1-based (1 = named first) and `null` when the brand was never named.
* To compare two periods, make two requests and subtract. Never average daily rows to get a period figure; ask for the period directly.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.