curl --request PATCH \
--url https://api.rankspot.ai/v1/articles/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "How to Start a Blog in 2024",
"description": "A comprehensive guide.",
"slug": "how-to-start-a-blog-2024",
"coverImageUrl": "https://cdn.example.com/cover.jpg",
"categoryId": "clx..."
}
'import requests
url = "https://api.rankspot.ai/v1/articles/{id}"
payload = {
"title": "How to Start a Blog in 2024",
"description": "A comprehensive guide.",
"slug": "how-to-start-a-blog-2024",
"coverImageUrl": "https://cdn.example.com/cover.jpg",
"categoryId": "clx..."
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: 'How to Start a Blog in 2024',
description: 'A comprehensive guide.',
slug: 'how-to-start-a-blog-2024',
coverImageUrl: 'https://cdn.example.com/cover.jpg',
categoryId: 'clx...'
})
};
fetch('https://api.rankspot.ai/v1/articles/{id}', 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/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'How to Start a Blog in 2024',
'description' => 'A comprehensive guide.',
'slug' => 'how-to-start-a-blog-2024',
'coverImageUrl' => 'https://cdn.example.com/cover.jpg',
'categoryId' => 'clx...'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.rankspot.ai/v1/articles/{id}"
payload := strings.NewReader("{\n \"title\": \"How to Start a Blog in 2024\",\n \"description\": \"A comprehensive guide.\",\n \"slug\": \"how-to-start-a-blog-2024\",\n \"coverImageUrl\": \"https://cdn.example.com/cover.jpg\",\n \"categoryId\": \"clx...\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.rankspot.ai/v1/articles/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"How to Start a Blog in 2024\",\n \"description\": \"A comprehensive guide.\",\n \"slug\": \"how-to-start-a-blog-2024\",\n \"coverImageUrl\": \"https://cdn.example.com/cover.jpg\",\n \"categoryId\": \"clx...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rankspot.ai/v1/articles/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"How to Start a Blog in 2024\",\n \"description\": \"A comprehensive guide.\",\n \"slug\": \"how-to-start-a-blog-2024\",\n \"coverImageUrl\": \"https://cdn.example.com/cover.jpg\",\n \"categoryId\": \"clx...\"\n}"
response = http.request(request)
puts response.read_body{
"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>"
}Update an article
Update metadata such as title, description, slug, coverImageUrl, or categoryId. The slug must be unique within your workspace. Article content and status are managed by RankSpot and cannot be changed via the API.
curl --request PATCH \
--url https://api.rankspot.ai/v1/articles/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "How to Start a Blog in 2024",
"description": "A comprehensive guide.",
"slug": "how-to-start-a-blog-2024",
"coverImageUrl": "https://cdn.example.com/cover.jpg",
"categoryId": "clx..."
}
'import requests
url = "https://api.rankspot.ai/v1/articles/{id}"
payload = {
"title": "How to Start a Blog in 2024",
"description": "A comprehensive guide.",
"slug": "how-to-start-a-blog-2024",
"coverImageUrl": "https://cdn.example.com/cover.jpg",
"categoryId": "clx..."
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: 'How to Start a Blog in 2024',
description: 'A comprehensive guide.',
slug: 'how-to-start-a-blog-2024',
coverImageUrl: 'https://cdn.example.com/cover.jpg',
categoryId: 'clx...'
})
};
fetch('https://api.rankspot.ai/v1/articles/{id}', 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/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'How to Start a Blog in 2024',
'description' => 'A comprehensive guide.',
'slug' => 'how-to-start-a-blog-2024',
'coverImageUrl' => 'https://cdn.example.com/cover.jpg',
'categoryId' => 'clx...'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.rankspot.ai/v1/articles/{id}"
payload := strings.NewReader("{\n \"title\": \"How to Start a Blog in 2024\",\n \"description\": \"A comprehensive guide.\",\n \"slug\": \"how-to-start-a-blog-2024\",\n \"coverImageUrl\": \"https://cdn.example.com/cover.jpg\",\n \"categoryId\": \"clx...\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.rankspot.ai/v1/articles/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"How to Start a Blog in 2024\",\n \"description\": \"A comprehensive guide.\",\n \"slug\": \"how-to-start-a-blog-2024\",\n \"coverImageUrl\": \"https://cdn.example.com/cover.jpg\",\n \"categoryId\": \"clx...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rankspot.ai/v1/articles/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"How to Start a Blog in 2024\",\n \"description\": \"A comprehensive guide.\",\n \"slug\": \"how-to-start-a-blog-2024\",\n \"coverImageUrl\": \"https://cdn.example.com/cover.jpg\",\n \"categoryId\": \"clx...\"\n}"
response = http.request(request)
puts response.read_body{
"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.
Path Parameters
Body
Response
"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.
