curl --request GET \
--url https://api.rankspot.ai/v1/articles \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.rankspot.ai/v1/articles"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.rankspot.ai/v1/articles', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.rankspot.ai/v1/articles",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.rankspot.ai/v1/articles"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.rankspot.ai/v1/articles")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rankspot.ai/v1/articles")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"total": 100,
"offset": 0,
"limit": 100,
"count": 10,
"items": [
{
"id": "clx...",
"title": "How to Start a Blog",
"status": "generated",
"slug": "how-to-start-a-blog",
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"isIndexed": true,
"description": "A comprehensive guide.",
"contentHtml": "<h1>How to Start a Blog</h1>...",
"coverImageUrl": "https://cdn.example.com/cover.jpg",
"categoryId": "clx...",
"firstPublishedAt": "<string>",
"lastPublishedAt": "<string>",
"indexCoverageState": "Crawled - currently not indexed",
"indexCheckedAt": "<string>",
"indexRequestedAt": "<string>"
}
]
}
}List articles
Returns a paginated list of articles in your workspace. Filter by search (title or description substring), slug (slug substring, which resolves a published URL back to its article), status or categoryId. The contentHtml field is omitted from list responses to keep payloads small — fetch a single article by ID to get the full HTML content.
curl --request GET \
--url https://api.rankspot.ai/v1/articles \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.rankspot.ai/v1/articles"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.rankspot.ai/v1/articles', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.rankspot.ai/v1/articles",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.rankspot.ai/v1/articles"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.rankspot.ai/v1/articles")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rankspot.ai/v1/articles")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"total": 100,
"offset": 0,
"limit": 100,
"count": 10,
"items": [
{
"id": "clx...",
"title": "How to Start a Blog",
"status": "generated",
"slug": "how-to-start-a-blog",
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"isIndexed": true,
"description": "A comprehensive guide.",
"contentHtml": "<h1>How to Start a Blog</h1>...",
"coverImageUrl": "https://cdn.example.com/cover.jpg",
"categoryId": "clx...",
"firstPublishedAt": "<string>",
"lastPublishedAt": "<string>",
"indexCoverageState": "Crawled - currently not indexed",
"indexCheckedAt": "<string>",
"indexRequestedAt": "<string>"
}
]
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Query Parameters
x >= 01 <= x <= 100Filter by title or description substring, case-insensitive. Use this to check whether an article on a subject already exists before writing a new one.
"screen recording"
Filter by slug substring, case-insensitive. A full slug matches exactly one article, since slugs are unique per workspace, and a partial one matches every article whose slug contains it.
Use this to go from a published URL back to its article: pass the last path segment. Matching on a substring rather than the whole string means a trailing slash, a file extension or a date prefix in the URL path does not stop it resolving.
"how-to-start-a-blog"
Filter by whether Google has indexed the page. false is the set worth acting on: pages that are live but invisible in search. Combine with status=published, since an article that never reached your site cannot be indexed and would otherwise pad the results.
Filter by status
draft, generating, generated, published Filter by category ID
Response
Hide child attributes
Hide child attributes
100
0
100
10
Hide child attributes
Hide child attributes
"clx..."
"How to Start a Blog"
Derived from the list rather than repeated here, so a new status cannot be returned while the docs still deny it exists. generated means the article has never left RankSpot; published means it reached your site.
draft, generating, generated, published "generated"
"how-to-start-a-blog"
Last write of any kind, including a status change or a metadata edit. This is not a reliable answer to "when was the content last refreshed" — use lastPublishedAt for that.
Whether Google Search Console reports the page as indexed. Refreshed by a weekly job, so it reflects the last check rather than this instant: read indexCheckedAt to know how fresh it is.
"A comprehensive guide."
Only returned by GE../articles/:slug
"<h1>How to Start a Blog</h1>..."
"https://cdn.example.com/cover.jpg"
"clx..."
When the article first went live. Null means it has never been published. This is the article's publication date: unlike lastPublishedAt it does not move on a re-publish, so it is what a page should show as "published on" and what answers "how many articles went out in this window".
When the article was last pushed to your site. Null means it has never been published. This is the field to check when deciding whether a page losing traffic is stale, and the one to show as "last updated": it moves only when the content actually reached readers, unlike updatedAt.
Search Console's own reason, verbatim, when the page is not indexed. This is the field that decides what to do about it: "Crawled - currently not indexed" means Google looked and declined, so the page needs work; "Discovered - currently not indexed" means it has not been crawled yet; a canonical or noindex reason means neither requesting nor rewriting will help.
"Crawled - currently not indexed"
When the index status above was last checked. Null means never checked, which is not the same as not indexed.
When indexing was last requested for this page. Null means it has never been submitted. Requests are throttled to one per page per week.
