Introduction
Ride the wave of search success with our gnarly SERP tracking API! 🏄
Welcome to the SERPs Up API! 🏄 This documentation will help you ride the waves of SERP data like a total pro.
Our API lets you programmatically access all your keyword rankings, project data, and team information. Perfect for building custom dashboards, automating reports, or integrating with your existing SEO tools.
<aside>As you scroll, you'll see gnarly code examples in different programming languages. Switch between languages using the tabs - it's totally tubular! 🌊</aside>
Authenticating requests
To authenticate requests, include an Authorization
header with the value "Bearer {your_api_token}"
.
All authenticated endpoints are marked with a requires authentication
badge in the documentation below.
You can retrieve your API token by visiting your Settings page and clicking Generate API Token. 🌊
API Tokens
Manage your API access tokens. Generate tokens to access the SERPs Up API programmatically! 🔑
List API tokens
requires authentication
Get all your API tokens with usage information. Tokens are never shown again after creation!
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/tokens" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/tokens"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/tokens';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/tokens'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"data": [
{
"id": 1,
"name": "My Dashboard Integration",
"abilities": [
"projects:read",
"keywords:read"
],
"last_used_at": "2024-01-20T08:00:00Z",
"expires_at": "2024-12-31T23:59:59Z",
"created_at": "2024-01-15T10:00:00Z"
}
],
"status": "success",
"message": "API tokens retrieved successfully.",
"code": 200
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create API token
requires authentication
Generate a new API token for programmatic access. Save the token - it won't be shown again!
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/tokens" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"\\\"My Dashboard Integration\\\"\",
\"team_id\": 1,
\"abilities\": [
\"projects:read\",
\"keywords:write\"
],
\"expires_at\": \"\\\"2024-12-31T23:59:59Z\\\"\"
}"
const url = new URL(
"http://rank-tracker.test/api/v1/tokens"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "\"My Dashboard Integration\"",
"team_id": 1,
"abilities": [
"projects:read",
"keywords:write"
],
"expires_at": "\"2024-12-31T23:59:59Z\""
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/tokens';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => '"My Dashboard Integration"',
'team_id' => 1,
'abilities' => [
'projects:read',
'keywords:write',
],
'expires_at' => '"2024-12-31T23:59:59Z"',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/tokens'
payload = {
"name": "\"My Dashboard Integration\"",
"team_id": 1,
"abilities": [
"projects:read",
"keywords:write"
],
"expires_at": "\"2024-12-31T23:59:59Z\""
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (201):
{
"data": {
"id": 1,
"name": "My Dashboard Integration",
"token": "1|abcdef123456789...",
"abilities": [
"projects:read",
"keywords:write"
],
"expires_at": "2024-12-31T23:59:59Z",
"created_at": "2024-01-20T10:00:00Z"
},
"status": "success",
"message": "API token created successfully.",
"code": 201
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to create tokens for this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete API token
requires authentication
Revoke an API token. This will immediately stop all access using this token.
Example request:
curl --request DELETE \
"http://rank-tracker.test/api/v1/tokens/16" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/tokens/16"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/tokens/16';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/tokens/16'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
Example response (200):
{
"data": null,
"status": "success",
"message": "API token deleted successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to delete this token.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Keywords
Manage keywords for your SERP tracking projects. Track those gnarly search terms! 🎯
List project keywords
requires authentication
Get all keywords for a specific project with their latest rankings.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/projects/1/keywords" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/projects/1/keywords"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/projects/1/keywords';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/projects/1/keywords'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"data": [
{
"id": 1,
"keyword": "best seo tools",
"priority": true,
"active": true,
"latest_ranking": {
"position": 3,
"checked_at": "2024-01-20T08:00:00Z"
}
}
],
"status": "success",
"message": "Keywords retrieved successfully.",
"code": 200
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add keywords to project
requires authentication
Add one or more keywords to track for this project. Bulk creation supported!
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/projects/1/keywords" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"keywords\": [
\"seo tools\",
\"rank tracker\"
],
\"priority\": true,
\"devices\": [
\"desktop\"
]
}"
const url = new URL(
"http://rank-tracker.test/api/v1/projects/1/keywords"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"keywords": [
"seo tools",
"rank tracker"
],
"priority": true,
"devices": [
"desktop"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/projects/1/keywords';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'keywords' => [
'seo tools',
'rank tracker',
],
'priority' => true,
'devices' => [
'desktop',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/projects/1/keywords'
payload = {
"keywords": [
"seo tools",
"rank tracker"
],
"priority": true,
"devices": [
"desktop"
]
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (201):
{
"data": [
{
"id": 1,
"keyword": "seo tools",
"priority": true,
"active": true,
"created_at": "2024-01-20T10:00:00Z"
}
],
"status": "success",
"message": "Keywords created successfully.",
"code": 201
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to add keywords to this project.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get keyword details
requires authentication
Retrieve detailed information about a keyword including all ranking history.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/projects/1/keywords/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/projects/1/keywords/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/projects/1/keywords/1';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/projects/1/keywords/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"data": {
"id": 1,
"keyword": "best seo tools",
"priority": true,
"active": true,
"rankings": [
{
"position": 3,
"checked_at": "2024-01-20T08:00:00Z",
"search_engine": "google"
}
]
},
"status": "success",
"message": "Keyword retrieved successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to access this keyword.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update keyword
requires authentication
Update keyword settings like priority status or pause/resume tracking.
Example request:
curl --request PATCH \
"http://rank-tracker.test/api/v1/projects/1/keywords/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"keyword\": \"\\\"updated seo tools\\\"\",
\"priority\": false,
\"active\": true
}"
const url = new URL(
"http://rank-tracker.test/api/v1/projects/1/keywords/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"keyword": "\"updated seo tools\"",
"priority": false,
"active": true
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/projects/1/keywords/1';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'keyword' => '"updated seo tools"',
'priority' => false,
'active' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/projects/1/keywords/1'
payload = {
"keyword": "\"updated seo tools\"",
"priority": false,
"active": true
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('PATCH', url, headers=headers, json=payload)
response.json()
Example response (200):
{
"data": {
"id": 1,
"keyword": "updated seo tools",
"priority": false,
"active": true,
"updated_at": "2024-01-20T10:30:00Z"
},
"status": "success",
"message": "Keyword updated successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to update this keyword.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete keyword
requires authentication
Remove a keyword from tracking. This will also delete all ranking history.
Example request:
curl --request DELETE \
"http://rank-tracker.test/api/v1/projects/1/keywords/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/projects/1/keywords/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/projects/1/keywords/1';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/projects/1/keywords/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
Example response (200):
{
"data": null,
"status": "success",
"message": "Keyword deleted successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to delete this keyword.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Rankings
Track and manage SERP ranking data for your keywords. See how you're riding the waves! 📈
Get keyword rankings
requires authentication
Retrieve ranking history for a specific keyword, ordered by most recent first.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/keywords/1/rankings?page=1&per_page=20" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"per_page\": 1
}"
const url = new URL(
"http://rank-tracker.test/api/v1/keywords/1/rankings"
);
const params = {
"page": "1",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"per_page": 1
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/keywords/1/rankings';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'page' => '1',
'per_page' => '20',
],
'json' => [
'per_page' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/keywords/1/rankings'
payload = {
"per_page": 1
}
params = {
'page': '1',
'per_page': '20',
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()
Example response (200):
{
"data": {
"rankings": [
{
"id": 1,
"position": 3,
"url": "https://example.com/page",
"featured_snippet": false,
"competitors": [
"competitor1.com",
"competitor2.com"
],
"checked_at": "2024-01-20T08:00:00Z"
}
],
"meta": {
"current_page": 1,
"total": 150
}
},
"status": "success",
"message": "Rankings retrieved successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to access this keyword.",
"code": 403
}
Example response (422):
{
"data": null,
"status": "error",
"message": "The limit is up to 100 rankings per page. Please try again with a lower per page request.",
"code": 422
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Record new ranking
requires authentication
Add a new ranking data point for a keyword. Used for manual updates or external integrations.
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/keywords/1/rankings" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"position\": 5,
\"url\": \"\\\"https:\\/\\/example.com\\/seo-guide\\\"\",
\"featured_snippet\": true,
\"competitors\": [
\"competitor1.com\",
\"competitor2.com\"
],
\"checked_at\": \"\\\"2024-01-20T08:00:00Z\\\"\"
}"
const url = new URL(
"http://rank-tracker.test/api/v1/keywords/1/rankings"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"position": 5,
"url": "\"https:\/\/example.com\/seo-guide\"",
"featured_snippet": true,
"competitors": [
"competitor1.com",
"competitor2.com"
],
"checked_at": "\"2024-01-20T08:00:00Z\""
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/keywords/1/rankings';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'position' => 5,
'url' => '"https://example.com/seo-guide"',
'featured_snippet' => true,
'competitors' => [
'competitor1.com',
'competitor2.com',
],
'checked_at' => '"2024-01-20T08:00:00Z"',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/keywords/1/rankings'
payload = {
"position": 5,
"url": "\"https:\/\/example.com\/seo-guide\"",
"featured_snippet": true,
"competitors": [
"competitor1.com",
"competitor2.com"
],
"checked_at": "\"2024-01-20T08:00:00Z\""
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (201):
{
"data": {
"id": 1,
"position": 5,
"url": "https://example.com/seo-guide",
"featured_snippet": true,
"competitors": [
"competitor1.com",
"competitor2.com"
],
"checked_at": "2024-01-20T08:00:00Z",
"created_at": "2024-01-20T08:05:00Z"
},
"status": "success",
"message": "Ranking recorded successfully.",
"code": 201
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to add rankings for this keyword.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Searches
Search locations and manage search results for SERP tracking. Find your target locations! 🌍
Search Locations
requires authentication
Get a paginated list of available search locations with filtering options.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/locations?country_code=US&target_type=City&search=New+York&per_page=25" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/locations"
);
const params = {
"country_code": "US",
"target_type": "City",
"search": "New York",
"per_page": "25",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/locations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'country_code' => 'US',
'target_type' => 'City',
'search' => 'New York',
'per_page' => '25',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/locations'
params = {
'country_code': 'US',
'target_type': 'City',
'search': 'New York',
'per_page': '25',
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, params=params)
response.json()
Example response (200):
{
"data": {
"locations": [
{
"id": 1,
"name": "New York",
"canonical_name": "New York,New York,United States",
"country_code": "US",
"target_type": "City"
}
]
},
"links": {
"first": "...",
"last": "...",
"prev": null,
"next": "..."
},
"meta": {
"current_page": 1,
"per_page": 25,
"total": 150
},
"status": "success",
"message": "Locations retrieved successfully.",
"code": 200
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Location Details
requires authentication
Get detailed information about a specific location including parent/child relationships.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/locations/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/locations/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/locations/1';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/locations/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"data": {
"id": 1,
"external_id": "585069a1ee19ad271e9b4baf",
"google_id": 9075393,
"name": "New York",
"canonical_name": "New York,New York,United States",
"country_code": "US",
"target_type": "City",
"reach": 8400000,
"latitude": 40.7127753,
"longitude": -74.0059728,
"parent": {
"id": 2,
"name": "New York",
"canonical_name": "New York,United States"
},
"children": [
{
"id": 3,
"name": "Manhattan",
"canonical_name": "Manhattan,New York,United States"
}
]
},
"status": "success",
"message": "Location retrieved successfully.",
"code": 200
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Search Results
requires authentication
Get paginated search results with optional filtering by keyword or location. Historical data requires Enterprise plan.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/searches?keyword_id=1&location_id=1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/searches"
);
const params = {
"keyword_id": "1",
"location_id": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/searches';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'keyword_id' => '1',
'location_id' => '1',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/searches'
params = {
'keyword_id': '1',
'location_id': '1',
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, params=params)
response.json()
Example response (200):
{
"data": [
{
"id": 1,
"keyword_id": 1,
"location_id": 1,
"total_results": 1250000,
"searched_at": "2024-01-20T10:00:00Z",
"keyword": {
"id": 1,
"keyword": "rank tracker"
},
"location": {
"id": 1,
"name": "New York",
"country_code": "US"
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Store Search Results
requires authentication
Store new search results for a keyword and location combination.
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/searches" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"keyword_id\": 1,
\"location_id\": 1,
\"results\": [
\"architecto\"
],
\"total_results\": 1250000
}"
const url = new URL(
"http://rank-tracker.test/api/v1/searches"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"keyword_id": 1,
"location_id": 1,
"results": [
"architecto"
],
"total_results": 1250000
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/searches';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'keyword_id' => 1,
'location_id' => 1,
'results' => [
'architecto',
],
'total_results' => 1250000,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/searches'
payload = {
"keyword_id": 1,
"location_id": 1,
"results": [
"architecto"
],
"total_results": 1250000
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (201):
{
"id": 1,
"keyword_id": 1,
"location_id": 1,
"results": [],
"total_results": 1250000,
"searched_at": "2024-01-20T10:00:00Z",
"keyword": {
"id": 1,
"keyword": "rank tracker"
},
"location": {
"id": 1,
"name": "New York"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Perform Search
requires authentication
Execute a search for a keyword/location combination. Returns cached results if available, otherwise performs new search.
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/searches/perform" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"keyword_id\": 1,
\"location_id\": 1,
\"force_new\": false
}"
const url = new URL(
"http://rank-tracker.test/api/v1/searches/perform"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"keyword_id": 1,
"location_id": 1,
"force_new": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/searches/perform';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'keyword_id' => 1,
'location_id' => 1,
'force_new' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/searches/perform'
payload = {
"keyword_id": 1,
"location_id": 1,
"force_new": false
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (200):
{
"data": {
"id": 1,
"keyword_id": 1,
"location_id": 1,
"results": {},
"total_results": 1250000,
"searched_at": "2024-01-20T10:00:00Z",
"from_cache": false
},
"status": "success",
"message": "Search completed successfully.",
"code": 200
}
Example response (429):
{
"data": null,
"status": "error",
"message": "Search limit exceeded. Please try again later.",
"code": 429
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Search Details
requires authentication
Get detailed information about a specific search including full results.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/searches/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/searches/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/searches/1';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/searches/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"id": 1,
"keyword_id": 1,
"location_id": 1,
"results": {
"url1": "example.com",
"url2": "test.com"
},
"total_results": 1250000,
"searched_at": "2024-01-20T10:00:00Z",
"keyword": {
"id": 1,
"keyword": "rank tracker"
},
"location": {
"id": 1,
"name": "New York",
"canonical_name": "New York,New York,United States"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Team Projects
Manage SERP tracking projects for your team. Create, update, and organize your website tracking! 🏗️
List team projects
requires authentication
Get all projects for a specific team with keyword counts.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/teams/1/projects" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/projects"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/projects';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/projects'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"data": [
{
"id": 1,
"name": "My Website",
"domain": "https://example.com",
"location": "United States",
"language": "en",
"device": "desktop",
"keywords_count": 25,
"created_at": "2024-01-15T10:30:00Z"
}
],
"status": "success",
"message": "Projects retrieved successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to access this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new project
requires authentication
Create a new SERP tracking project for your team.
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/teams/1/projects" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"\\\"My Awesome Website\\\"\",
\"domain\": \"\\\"https:\\/\\/example.com\\\"\",
\"location\": \"\\\"United States\\\"\",
\"language\": \"\\\"en\\\"\",
\"device\": \"\\\"desktop\\\"\"
}"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/projects"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "\"My Awesome Website\"",
"domain": "\"https:\/\/example.com\"",
"location": "\"United States\"",
"language": "\"en\"",
"device": "\"desktop\""
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/projects';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => '"My Awesome Website"',
'domain' => '"https://example.com"',
'location' => '"United States"',
'language' => '"en"',
'device' => '"desktop"',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/projects'
payload = {
"name": "\"My Awesome Website\"",
"domain": "\"https:\/\/example.com\"",
"location": "\"United States\"",
"language": "\"en\"",
"device": "\"desktop\""
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (201):
{
"data": {
"id": 1,
"name": "My Awesome Website",
"domain": "https://example.com",
"location": "United States",
"language": "en",
"device": "desktop",
"active": true,
"created_at": "2024-01-20T10:00:00Z"
},
"status": "success",
"message": "Project created successfully.",
"code": 201
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to create projects for this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get project details
requires authentication
Retrieve detailed information about a project including all keywords and latest rankings.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/teams/1/projects/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/projects/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/projects/1';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/projects/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "My Awesome Website",
"domain": "https://example.com",
"location": "United States",
"keywords": [
{
"id": 1,
"keyword": "best seo tools",
"latest_ranking": {
"position": 3,
"checked_at": "2024-01-20T08:00:00Z"
}
}
]
},
"status": "success",
"message": "Project retrieved successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to access this project.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update project
requires authentication
Update project settings and configuration.
Example request:
curl --request PATCH \
"http://rank-tracker.test/api/v1/teams/1/projects/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"\\\"Updated Website Name\\\"\",
\"domain\": \"\\\"https:\\/\\/newdomain.com\\\"\",
\"location\": \"\\\"Canada\\\"\",
\"language\": \"\\\"fr\\\"\",
\"device\": \"\\\"mobile\\\"\",
\"active\": false
}"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/projects/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "\"Updated Website Name\"",
"domain": "\"https:\/\/newdomain.com\"",
"location": "\"Canada\"",
"language": "\"fr\"",
"device": "\"mobile\"",
"active": false
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/projects/1';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => '"Updated Website Name"',
'domain' => '"https://newdomain.com"',
'location' => '"Canada"',
'language' => '"fr"',
'device' => '"mobile"',
'active' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/projects/1'
payload = {
"name": "\"Updated Website Name\"",
"domain": "\"https:\/\/newdomain.com\"",
"location": "\"Canada\"",
"language": "\"fr\"",
"device": "\"mobile\"",
"active": false
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('PATCH', url, headers=headers, json=payload)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "Updated Website Name",
"domain": "https://newdomain.com",
"active": false,
"updated_at": "2024-01-20T10:30:00Z"
},
"status": "success",
"message": "Project updated successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to update this project.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete project
requires authentication
Delete a project and all associated keywords and ranking data.
Example request:
curl --request DELETE \
"http://rank-tracker.test/api/v1/teams/1/projects/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/projects/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/projects/1';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/projects/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
Example response (200):
{
"data": null,
"status": "success",
"message": "Project deleted successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to delete this project.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Teams
Manage your SERP crew! Create teams, invite members, and collaborate on projects. 🤙
List teams
requires authentication
Get all teams you're a member of. Admins can see all teams.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/teams?page=1&per_page=20" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"per_page\": 1
}"
const url = new URL(
"http://rank-tracker.test/api/v1/teams"
);
const params = {
"page": "1",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"per_page": 1
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'page' => '1',
'per_page' => '20',
],
'json' => [
'per_page' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams'
payload = {
"per_page": 1
}
params = {
'page': '1',
'per_page': '20',
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()
Example response (200):
{
"data": {
"teams": [
{
"id": 1,
"name": "My SERP Crew",
"slug": "my-serp-crew",
"owner": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
"members_count": 3,
"projects_count": 5
}
],
"meta": {
"current_page": 1,
"total": 25,
"per_page": 20,
"last_page": 2
}
},
"status": "success",
"message": "Teams retrieved successfully.",
"code": 200
}
Example response (422):
{
"data": null,
"status": "error",
"message": "The limit is up to 100 teams per page. Please try again with a lower per page request.",
"code": 422
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create team
requires authentication
Create a new team and become the owner. Start building your SERP crew!
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/teams" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"\\\"My SERP Crew\\\"\"
}"
const url = new URL(
"http://rank-tracker.test/api/v1/teams"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "\"My SERP Crew\""
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => '"My SERP Crew"',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams'
payload = {
"name": "\"My SERP Crew\""
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (201):
{
"data": {
"id": 1,
"name": "My SERP Crew",
"slug": "my-serp-crew",
"owner_id": 1,
"owner": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
"members": [
{
"id": 1,
"name": "John Doe",
"role": "owner"
}
],
"created_at": "2024-01-20T10:00:00Z"
},
"status": "success",
"message": "Team created successfully.",
"code": 201
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get team details
requires authentication
Retrieve detailed information about a team including members and projects.
Example request:
curl --request GET \
--get "http://rank-tracker.test/api/v1/teams/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "My SERP Crew",
"slug": "my-serp-crew",
"owner": {
"id": 1,
"name": "John Doe"
},
"members": [
{
"id": 1,
"name": "John Doe",
"role": "owner"
},
{
"id": 2,
"name": "Jane Smith",
"role": "member"
}
],
"projects": [
{
"id": 1,
"name": "Website Project",
"domain": "https://example.com",
"keywords_count": 25
}
]
},
"status": "success",
"message": "Team retrieved successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to access this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update team name
requires authentication
Update the team's name. Only team owners can update team names.
Example request:
curl --request PATCH \
"http://rank-tracker.test/api/v1/teams/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"\\\"Updated SERP Crew\\\"\"
}"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "\"Updated SERP Crew\""
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => '"Updated SERP Crew"',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1'
payload = {
"name": "\"Updated SERP Crew\""
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('PATCH', url, headers=headers, json=payload)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "Updated SERP Crew",
"slug": "my-serp-crew",
"updated_at": "2024-01-20T10:30:00Z"
},
"status": "success",
"message": "Team name updated successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to update this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete team
requires authentication
Delete a team and all associated projects and data. Only team owners can delete teams.
Example request:
curl --request DELETE \
"http://rank-tracker.test/api/v1/teams/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
Example response (200):
{
"data": null,
"status": "success",
"message": "Team deleted successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to delete this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add team member
requires authentication
Invite a user to join your SERP crew! User must already have an account.
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/teams/1/members" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"\\\"newmember@example.com\\\"\",
\"role\": \"\\\"member\\\"\"
}"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/members"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "\"newmember@example.com\"",
"role": "\"member\""
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/members';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => '"newmember@example.com"',
'role' => '"member"',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/members'
payload = {
"email": "\"newmember@example.com\"",
"role": "\"member\""
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "My SERP Crew",
"members": [
{
"id": 1,
"name": "John Doe",
"role": "owner"
},
{
"id": 2,
"name": "New Member",
"role": "member"
}
]
},
"status": "success",
"message": "Team member added successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to add members to this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update team member role
requires authentication
Change a team member's role. Only team owners can update member roles.
Example request:
curl --request PATCH \
"http://rank-tracker.test/api/v1/teams/1/members/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"role\": \"\\\"viewer\\\"\"
}"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/members/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"role": "\"viewer\""
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/members/1';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'role' => '"viewer"',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/members/1'
payload = {
"role": "\"viewer\""
}
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('PATCH', url, headers=headers, json=payload)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "My SERP Crew",
"members": [
{
"id": 1,
"name": "John Doe",
"role": "owner"
},
{
"id": 2,
"name": "Jane Smith",
"role": "viewer"
}
]
},
"status": "success",
"message": "Team member role updated successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to update member roles for this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Remove team member
requires authentication
Remove a member from your team. Only team owners can remove members.
Example request:
curl --request DELETE \
"http://rank-tracker.test/api/v1/teams/1/members/1" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/members/1"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/members/1';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/members/1'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
Example response (200):
{
"data": null,
"status": "success",
"message": "Team member removed successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to remove members from this team.",
"code": 403
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Change team plan
requires authentication
Upgrade or downgrade team to a different plan. Handles billing for paid plans.
Example request:
curl --request POST \
"http://rank-tracker.test/api/v1/teams/1/change-plan/"professional"" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/change-plan/"professional""
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/change-plan/"professional"';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/change-plan/"professional"'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "My SERP Crew",
"plan": {
"name": "Pro SERPer",
"slug": "pro",
"price": 29.99
},
"subscription_status": "active"
},
"status": "success",
"message": "Team plan updated successfully.",
"code": 200
}
Example response (403):
{
"data": null,
"status": "error",
"message": "You don't have permission to change this team's plan.",
"code": 403
}
Example response (422):
{
"data": null,
"status": "error",
"message": "Invalid plan selected.",
"code": 422
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel team subscription
requires authentication
Cancel the team's paid subscription at the end of the current billing period.
Example request:
curl --request DELETE \
"http://rank-tracker.test/api/v1/teams/1/subscription" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/subscription"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/subscription';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/subscription'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "My SERP Crew",
"plan": {
"name": "Pro SERPer",
"slug": "professional",
"price": 4900
},
"subscription_status": "cancelled",
"ends_at": "2025-08-30T23:59:59Z"
},
"status": "success",
"message": "Subscription cancelled successfully. You'll retain access until August 30, 2025.",
"code": 200
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel team subscription immediately
requires authentication
Immediately cancel and forfeit remaining billing period access.
Example request:
curl --request DELETE \
"http://rank-tracker.test/api/v1/teams/1/subscription/immediate" \
--header "Authorization: Bearer {your_api_token}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"http://rank-tracker.test/api/v1/teams/1/subscription/immediate"
);
const headers = {
"Authorization": "Bearer {your_api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'http://rank-tracker.test/api/v1/teams/1/subscription/immediate';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {your_api_token}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'http://rank-tracker.test/api/v1/teams/1/subscription/immediate'
headers = {
'Authorization': 'Bearer {your_api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
Example response (200):
{
"data": {
"id": 1,
"name": "My SERP Crew",
"plan": null,
"subscription_status": "cancelled_immediately",
"cancelled_at": "2025-07-30T12:00:00Z"
},
"status": "success",
"message": "Subscription cancelled immediately. Historical data preserved up to July 30, 2025.",
"code": 200
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.