Update an article
curl --request PATCH \
--url https://api.snowseo.com/v3/cms/articles/{slug} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"teamId": "<string>",
"content": "<string>",
"metaData": {},
"slug": "<string>",
"status": "<string>",
"isPublic": true,
"jsonLd": "<string>",
"keywords": [
{
"keyword": "<string>"
}
],
"prompts": [
{
"prompt": "<string>"
}
],
"revisionSource": "manual",
"revisionLabel": "<string>",
"authors": [
{
"name": "<string>",
"avatar": "<string>",
"url": "<string>"
}
],
"autoOptimizeState": {
"appliedIds": [
"<string>"
],
"dismissedIds": [
"<string>"
],
"undoData": {}
}
}
'import requests
url = "https://api.snowseo.com/v3/cms/articles/{slug}"
payload = {
"teamId": "<string>",
"content": "<string>",
"metaData": {},
"slug": "<string>",
"status": "<string>",
"isPublic": True,
"jsonLd": "<string>",
"keywords": [{ "keyword": "<string>" }],
"prompts": [{ "prompt": "<string>" }],
"revisionSource": "manual",
"revisionLabel": "<string>",
"authors": [
{
"name": "<string>",
"avatar": "<string>",
"url": "<string>"
}
],
"autoOptimizeState": {
"appliedIds": ["<string>"],
"dismissedIds": ["<string>"],
"undoData": {}
}
}
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({
teamId: '<string>',
content: '<string>',
metaData: {},
slug: '<string>',
status: '<string>',
isPublic: true,
jsonLd: '<string>',
keywords: [{keyword: '<string>'}],
prompts: [{prompt: '<string>'}],
revisionSource: 'manual',
revisionLabel: '<string>',
authors: [{name: '<string>', avatar: '<string>', url: '<string>'}],
autoOptimizeState: {appliedIds: ['<string>'], dismissedIds: ['<string>'], undoData: {}}
})
};
fetch('https://api.snowseo.com/v3/cms/articles/{slug}', 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.snowseo.com/v3/cms/articles/{slug}",
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([
'teamId' => '<string>',
'content' => '<string>',
'metaData' => [
],
'slug' => '<string>',
'status' => '<string>',
'isPublic' => true,
'jsonLd' => '<string>',
'keywords' => [
[
'keyword' => '<string>'
]
],
'prompts' => [
[
'prompt' => '<string>'
]
],
'revisionSource' => 'manual',
'revisionLabel' => '<string>',
'authors' => [
[
'name' => '<string>',
'avatar' => '<string>',
'url' => '<string>'
]
],
'autoOptimizeState' => [
'appliedIds' => [
'<string>'
],
'dismissedIds' => [
'<string>'
],
'undoData' => [
]
]
]),
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.snowseo.com/v3/cms/articles/{slug}"
payload := strings.NewReader("{\n \"teamId\": \"<string>\",\n \"content\": \"<string>\",\n \"metaData\": {},\n \"slug\": \"<string>\",\n \"status\": \"<string>\",\n \"isPublic\": true,\n \"jsonLd\": \"<string>\",\n \"keywords\": [\n {\n \"keyword\": \"<string>\"\n }\n ],\n \"prompts\": [\n {\n \"prompt\": \"<string>\"\n }\n ],\n \"revisionSource\": \"manual\",\n \"revisionLabel\": \"<string>\",\n \"authors\": [\n {\n \"name\": \"<string>\",\n \"avatar\": \"<string>\",\n \"url\": \"<string>\"\n }\n ],\n \"autoOptimizeState\": {\n \"appliedIds\": [\n \"<string>\"\n ],\n \"dismissedIds\": [\n \"<string>\"\n ],\n \"undoData\": {}\n }\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.snowseo.com/v3/cms/articles/{slug}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"teamId\": \"<string>\",\n \"content\": \"<string>\",\n \"metaData\": {},\n \"slug\": \"<string>\",\n \"status\": \"<string>\",\n \"isPublic\": true,\n \"jsonLd\": \"<string>\",\n \"keywords\": [\n {\n \"keyword\": \"<string>\"\n }\n ],\n \"prompts\": [\n {\n \"prompt\": \"<string>\"\n }\n ],\n \"revisionSource\": \"manual\",\n \"revisionLabel\": \"<string>\",\n \"authors\": [\n {\n \"name\": \"<string>\",\n \"avatar\": \"<string>\",\n \"url\": \"<string>\"\n }\n ],\n \"autoOptimizeState\": {\n \"appliedIds\": [\n \"<string>\"\n ],\n \"dismissedIds\": [\n \"<string>\"\n ],\n \"undoData\": {}\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snowseo.com/v3/cms/articles/{slug}")
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 \"teamId\": \"<string>\",\n \"content\": \"<string>\",\n \"metaData\": {},\n \"slug\": \"<string>\",\n \"status\": \"<string>\",\n \"isPublic\": true,\n \"jsonLd\": \"<string>\",\n \"keywords\": [\n {\n \"keyword\": \"<string>\"\n }\n ],\n \"prompts\": [\n {\n \"prompt\": \"<string>\"\n }\n ],\n \"revisionSource\": \"manual\",\n \"revisionLabel\": \"<string>\",\n \"authors\": [\n {\n \"name\": \"<string>\",\n \"avatar\": \"<string>\",\n \"url\": \"<string>\"\n }\n ],\n \"autoOptimizeState\": {\n \"appliedIds\": [\n \"<string>\"\n ],\n \"dismissedIds\": [\n \"<string>\"\n ],\n \"undoData\": {}\n }\n}"
response = http.request(request)
puts response.read_body{
"article": {
"slug": "<string>",
"title": "<string>",
"status": "<string>",
"isPublic": true,
"updatedAt": "<string>",
"lastRefreshedAt": "<string>",
"cmsSyncDirty": true,
"publishedSnapshot": {},
"jsonLd": "<string>"
}
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>",
"generationKind": "<string>",
"generationPhase": "<string>",
"lockedFields": [
"<string>"
]
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}Content
Manage Articles
Edit an existing article and control its visibility.
PATCH
/
v3
/
cms
/
articles
/
{slug}
Update an article
curl --request PATCH \
--url https://api.snowseo.com/v3/cms/articles/{slug} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"teamId": "<string>",
"content": "<string>",
"metaData": {},
"slug": "<string>",
"status": "<string>",
"isPublic": true,
"jsonLd": "<string>",
"keywords": [
{
"keyword": "<string>"
}
],
"prompts": [
{
"prompt": "<string>"
}
],
"revisionSource": "manual",
"revisionLabel": "<string>",
"authors": [
{
"name": "<string>",
"avatar": "<string>",
"url": "<string>"
}
],
"autoOptimizeState": {
"appliedIds": [
"<string>"
],
"dismissedIds": [
"<string>"
],
"undoData": {}
}
}
'import requests
url = "https://api.snowseo.com/v3/cms/articles/{slug}"
payload = {
"teamId": "<string>",
"content": "<string>",
"metaData": {},
"slug": "<string>",
"status": "<string>",
"isPublic": True,
"jsonLd": "<string>",
"keywords": [{ "keyword": "<string>" }],
"prompts": [{ "prompt": "<string>" }],
"revisionSource": "manual",
"revisionLabel": "<string>",
"authors": [
{
"name": "<string>",
"avatar": "<string>",
"url": "<string>"
}
],
"autoOptimizeState": {
"appliedIds": ["<string>"],
"dismissedIds": ["<string>"],
"undoData": {}
}
}
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({
teamId: '<string>',
content: '<string>',
metaData: {},
slug: '<string>',
status: '<string>',
isPublic: true,
jsonLd: '<string>',
keywords: [{keyword: '<string>'}],
prompts: [{prompt: '<string>'}],
revisionSource: 'manual',
revisionLabel: '<string>',
authors: [{name: '<string>', avatar: '<string>', url: '<string>'}],
autoOptimizeState: {appliedIds: ['<string>'], dismissedIds: ['<string>'], undoData: {}}
})
};
fetch('https://api.snowseo.com/v3/cms/articles/{slug}', 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.snowseo.com/v3/cms/articles/{slug}",
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([
'teamId' => '<string>',
'content' => '<string>',
'metaData' => [
],
'slug' => '<string>',
'status' => '<string>',
'isPublic' => true,
'jsonLd' => '<string>',
'keywords' => [
[
'keyword' => '<string>'
]
],
'prompts' => [
[
'prompt' => '<string>'
]
],
'revisionSource' => 'manual',
'revisionLabel' => '<string>',
'authors' => [
[
'name' => '<string>',
'avatar' => '<string>',
'url' => '<string>'
]
],
'autoOptimizeState' => [
'appliedIds' => [
'<string>'
],
'dismissedIds' => [
'<string>'
],
'undoData' => [
]
]
]),
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.snowseo.com/v3/cms/articles/{slug}"
payload := strings.NewReader("{\n \"teamId\": \"<string>\",\n \"content\": \"<string>\",\n \"metaData\": {},\n \"slug\": \"<string>\",\n \"status\": \"<string>\",\n \"isPublic\": true,\n \"jsonLd\": \"<string>\",\n \"keywords\": [\n {\n \"keyword\": \"<string>\"\n }\n ],\n \"prompts\": [\n {\n \"prompt\": \"<string>\"\n }\n ],\n \"revisionSource\": \"manual\",\n \"revisionLabel\": \"<string>\",\n \"authors\": [\n {\n \"name\": \"<string>\",\n \"avatar\": \"<string>\",\n \"url\": \"<string>\"\n }\n ],\n \"autoOptimizeState\": {\n \"appliedIds\": [\n \"<string>\"\n ],\n \"dismissedIds\": [\n \"<string>\"\n ],\n \"undoData\": {}\n }\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.snowseo.com/v3/cms/articles/{slug}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"teamId\": \"<string>\",\n \"content\": \"<string>\",\n \"metaData\": {},\n \"slug\": \"<string>\",\n \"status\": \"<string>\",\n \"isPublic\": true,\n \"jsonLd\": \"<string>\",\n \"keywords\": [\n {\n \"keyword\": \"<string>\"\n }\n ],\n \"prompts\": [\n {\n \"prompt\": \"<string>\"\n }\n ],\n \"revisionSource\": \"manual\",\n \"revisionLabel\": \"<string>\",\n \"authors\": [\n {\n \"name\": \"<string>\",\n \"avatar\": \"<string>\",\n \"url\": \"<string>\"\n }\n ],\n \"autoOptimizeState\": {\n \"appliedIds\": [\n \"<string>\"\n ],\n \"dismissedIds\": [\n \"<string>\"\n ],\n \"undoData\": {}\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snowseo.com/v3/cms/articles/{slug}")
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 \"teamId\": \"<string>\",\n \"content\": \"<string>\",\n \"metaData\": {},\n \"slug\": \"<string>\",\n \"status\": \"<string>\",\n \"isPublic\": true,\n \"jsonLd\": \"<string>\",\n \"keywords\": [\n {\n \"keyword\": \"<string>\"\n }\n ],\n \"prompts\": [\n {\n \"prompt\": \"<string>\"\n }\n ],\n \"revisionSource\": \"manual\",\n \"revisionLabel\": \"<string>\",\n \"authors\": [\n {\n \"name\": \"<string>\",\n \"avatar\": \"<string>\",\n \"url\": \"<string>\"\n }\n ],\n \"autoOptimizeState\": {\n \"appliedIds\": [\n \"<string>\"\n ],\n \"dismissedIds\": [\n \"<string>\"\n ],\n \"undoData\": {}\n }\n}"
response = http.request(request)
puts response.read_body{
"article": {
"slug": "<string>",
"title": "<string>",
"status": "<string>",
"isPublic": true,
"updatedAt": "<string>",
"lastRefreshedAt": "<string>",
"cmsSyncDirty": true,
"publishedSnapshot": {},
"jsonLd": "<string>"
}
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>",
"generationKind": "<string>",
"generationPhase": "<string>",
"lockedFields": [
"<string>"
]
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}Update an existing article’s content or metadata by slug. Only the fields you send are changed. Body fields:
content, metaData (merged into existing metadata), slug (must be unique within the team), status (draft, generated, or manual only), isPublic, jsonLd (a JSON string that parses to an object or array, or empty/null to clear), keywords and prompts (replace the stored lists; one keyword and one prompt are primary, and extra primaries are stored as secondary), authors (replaces the bylines, in order: { name, avatar?, url? }; assistant names such as “Snowy” are dropped, the article’s JSON-LD author is updated to match, and a published article is marked as needing a re-push), plus revisionSource: "manual" with revisionLabel to snapshot a history version first. Returns { article } with slug, title, status, isPublic, updatedAt, lastRefreshedAt, cmsSyncDirty, and publishedSnapshot. Errors: 400 for an invalid slug, status, or JSON-LD or an empty update; 404 for an unknown slug; 409 for a slug already in use, or when a generation job currently owns the article and you change content, metaData, jsonLd, status, slug, keywords, or prompts (isPublic stays writable).
These endpoints modify existing articles - they don’t create new ones. Use the Articles list to find slugs.
Authorizations
bearerAuthapiKey
Your SnowSEO API key (sk_...).
Path Parameters
Body
application/json
Replaces the article's keywords. Mark exactly one as primary; extra primaries are stored as secondary.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Available options:
manual Replaces the article's bylines, in order (the first is primary). Assistant names like 'Snowy' are dropped.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Response
Default Response
Show child attributes
Show child attributes
Was this page helpful?

