This section covers keyword endpoints in the Reporting API.
GET /reporting/projects/{id}/keywords
List keywords for a project with filtering, searching, and sorting.
Parameters
| Name | Type | Description |
|---|---|---|
search |
string | Search keywords by name. |
sort |
string | Sort field: name, current_position, movement, status, best_position. |
order |
string | Sort order: asc or desc (default: asc). |
location |
string | Filter by location. |
device |
string | Filter: desktop, mobile. |
search_engine |
string | Filter by search engine. |
type |
string | Filter: owner, competitor, paid. |
status |
string | Filter by keyword status. |
per_page |
integer | Items per page (default: 25). |
cursor |
string | Pagination cursor from links.next or meta.next_cursor. |
fields |
string | Comma-separated list of fields to include (unsupported fields are ignored). |
List responses include summary fields only. For positions and movement, use the keyword detail endpoint.
Sample Response
{
"data": [
{
"keyword_id": 23563544,
"name": "example keyword",
"type": "owner",
"domain": "example.com",
"language": "English",
"search_engine": "google",
"device": "desktop",
"location": "01001,Massachusetts,United States",
"status": "updated",
"position_next_update": "2026-02-05T06:00:00+00:00"
}
],
"meta": {
"per_page": [
"1",
"1"
],
"next_cursor": "eyJrZXl3b3Jkcy5jdXJyZW50X3Bvc2l0aW9uIjoxLCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9",
"prev_cursor": null,
"has_more": true,
"path": "https://v2.serpwatch.io/api/reporting/projects/33082/keywords"
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": "https://v2.serpwatch.io/api/reporting/projects/33082/keywords?cursor=eyJrZXl3b3Jkcy5jdXJyZW50X3Bvc2l0aW9uIjoxLCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9"
}
}
Sample Code
curl -X GET "https://v2.serpwatch.io/api/reporting/projects/33082/keywords?search=seo&sort=current_position&order=asc" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
const params = new URLSearchParams({
search: "seo",
sort: "current_position",
order: "asc"
});
const response = await fetch(
`https://v2.serpwatch.io/api/reporting/projects/33082/keywords?${params}`,
{
headers: {
Authorization: "Bearer YOUR_API_KEY",
Accept: "application/json"
}
}
);
const data = await response.json();
GET /reporting/keywords/{id}
Get detailed keyword information including position metrics.
Parameters
| Name | Type | Description |
|---|---|---|
fields |
string | Comma-separated list of fields to include. |
Sample Response
{
"data": {
"keyword_id": 23563544,
"name": "example keyword",
"type": "owner",
"domain": "example.com",
"location": "01001,Massachusetts,United States",
"language": "English",
"search_engine": "google",
"google_business": null,
"device": "desktop",
"status": "updated",
"position_next_update": "2026-02-05T06:00:00+00:00",
"initial_position": 18,
"current_position": 12,
"best_position": 7,
"previous_position": 13,
"movement": 1,
"local_sv": 10,
"global_sv": 20,
"cpc": 0,
"url": "https://example.com/example-page",
"update_frequency": 24
}
}
Sample Code
curl -X GET "https://v2.serpwatch.io/api/reporting/keywords/23563544" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
const response = await fetch(
"https://v2.serpwatch.io/api/reporting/keywords/23563544",
{
headers: {
Authorization: "Bearer YOUR_API_KEY",
Accept: "application/json"
}
}
);
const data = await response.json();
GET /reporting/keywords/{id}/history
Get keyword ranking history for a date range.
Parameters
| Name | Type | Description |
|---|---|---|
start_date |
string | Start date (YYYY-MM-DD). |
end_date |
string | End date (YYYY-MM-DD). |
page |
integer | Page number (default: 1). |
per_page |
integer | Items per page. |
The maximum date range per request is returned in meta.date_range.max_allowed_days (currently 180).
Sample Response
{
"data": [
{
"created_at": "2026-02-04T06:00:00+00:00",
"type": "organic",
"url": "https://example.com/example-page",
"position": 1,
"title": "-",
"snippet": "-"
}
],
"meta": {
"current_page": 1,
"per_page": "2",
"total": 10,
"last_page": 5,
"has_more": true,
"date_range": {
"start_date": "2026-02-03",
"end_date": "2026-02-05",
"max_allowed_days": 180
}
}
}
Sample Code
curl -X GET "https://v2.serpwatch.io/api/reporting/keywords/23563544/history?start_date=2026-01-20&end_date=2026-02-05&per_page=50" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
const params = new URLSearchParams({
start_date: "2026-01-20",
end_date: "2026-02-05",
per_page: "50"
});
const response = await fetch(
`https://v2.serpwatch.io/api/reporting/keywords/23563544/history?${params}`,
{
headers: {
Authorization: "Bearer YOUR_API_KEY",
Accept: "application/json"
}
}
);
const data = await response.json();
$client = new GuzzleHttp\\Client();
$response = $client->get("https://v2.serpwatch.io/api/reporting/keywords/23563544/history", [
"headers" => [
"Authorization" => "Bearer YOUR_API_KEY",
"Accept" => "application/json",
],
"query" => [
"start_date" => "2026-01-20",
"end_date" => "2026-02-05",
"per_page" => 50,
]
]);
$data = json_decode($response->getBody(), true);