curl --request GET \
--url https://api.snowseo.com/v3/cms/articles \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.snowseo.com/v3/cms/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.snowseo.com/v3/cms/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.snowseo.com/v3/cms/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.snowseo.com/v3/cms/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.snowseo.com/v3/cms/articles")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snowseo.com/v3/cms/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{
"articles": [
{
"slug": "<string>",
"topicId": "<string>",
"title": "<string>",
"status": "draft",
"type": "listicle",
"keywords": [
{
"keyword": "<string>",
"type": "primary"
}
],
"prompts": [
{
"prompt": "<string>",
"type": "primary",
"topic": "<string>"
}
],
"auditScore": 123,
"visitors": 123,
"url": "<string>",
"cmsArticleId": "<string>",
"provider": [
"wordpress"
],
"publishedAt": "<string>",
"scheduledAt": "<string>",
"lastRefreshedAt": "<string>",
"cmsPostStatus": "draft",
"createdAt": "<string>",
"updatedAt": "<string>",
"metaData": {},
"isPublic": true,
"isPillar": true,
"generating": true,
"generationKind": "<string>",
"finalizing": true,
"categories": [
"<string>"
],
"tags": [
"<string>"
]
}
],
"summary": {
"total": 123,
"publishable": 123,
"unpublishable": 123,
"unschedulable": 123,
"byStatus": {}
},
"activity": {
"generating": 123
},
"pagination": {
"page": 123,
"pageSize": 123,
"total": 123,
"totalPages": 123,
"hasMore": true
}
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}Articles
List all articles for your team with status, SEO scores, and metadata.
curl --request GET \
--url https://api.snowseo.com/v3/cms/articles \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.snowseo.com/v3/cms/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.snowseo.com/v3/cms/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.snowseo.com/v3/cms/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.snowseo.com/v3/cms/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.snowseo.com/v3/cms/articles")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snowseo.com/v3/cms/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{
"articles": [
{
"slug": "<string>",
"topicId": "<string>",
"title": "<string>",
"status": "draft",
"type": "listicle",
"keywords": [
{
"keyword": "<string>",
"type": "primary"
}
],
"prompts": [
{
"prompt": "<string>",
"type": "primary",
"topic": "<string>"
}
],
"auditScore": 123,
"visitors": 123,
"url": "<string>",
"cmsArticleId": "<string>",
"provider": [
"wordpress"
],
"publishedAt": "<string>",
"scheduledAt": "<string>",
"lastRefreshedAt": "<string>",
"cmsPostStatus": "draft",
"createdAt": "<string>",
"updatedAt": "<string>",
"metaData": {},
"isPublic": true,
"isPillar": true,
"generating": true,
"generationKind": "<string>",
"finalizing": true,
"categories": [
"<string>"
],
"tags": [
"<string>"
]
}
],
"summary": {
"total": 123,
"publishable": 123,
"unpublishable": 123,
"unschedulable": 123,
"byStatus": {}
},
"activity": {
"generating": 123
},
"pagination": {
"page": 123,
"pageSize": 123,
"total": 123,
"totalPages": 123,
"hasMore": true
}
}{
"success": true,
"error": "<string>",
"code": "<string>",
"message": "<string>",
"reference": "<string>"
}teamId, page (default 1), per_page (default 20, or all), status (any status below or all), topicId, startDate and endDate (match scheduledAt or publishedAt), search (title, slug, keywords, prompts, providers, topic name), sortBy (name, status, seo, topic, created, visitors; default created), sortDir (asc or desc; default desc), category, and tag. Limited to 30 requests per minute.
Visitor counts need analyticsProvider set to the brand’s connected analytics integration (ga, posthog, plausible or snow), counted over analyticsStartDate and analyticsEndDate. Sorting by visitors without it returns 400.
The response is { articles, summary, activity, pagination }:
summarycounts the articles that match your filters:total,publishable(statusgeneratedormanual),unpublishable(published to a CMS),unschedulable(scheduled with a date), andbyStatus(count per status).activity.generatingis the number of article generations currently running for your team.paginationhaspage,pageSize,total,totalPages, andhasMore.
Fields
| Field | Description |
|---|---|
slug | URL slug that identifies the article |
topicId | Topic cluster the article belongs to, or null |
title | Article title, or null |
status | Current status: draft, processing, generated, scheduled, published, failed, manual (imported from a CMS) |
type | Article type: listicle, comparison, news, review, guide, manual (imported from a CMS) |
auditScore | SEO audit score (0–100), from the article’s latest audit. null if the article has not been audited yet |
visitors | Page views from your analytics provider. null unless the article is published and live (not a CMS draft) |
url | Public URL of the article, or null |
cmsArticleId | The article’s ID in your CMS, or null |
cmsPostStatus | Post status in the CMS, or null |
publishedAt / scheduledAt / lastRefreshedAt | When the article was published, is scheduled to publish, and was last refreshed. Each can be null |
createdAt / updatedAt | When the article was created and last updated |
metaData | Article metadata object (such as the SEO title and description), or null |
prompts | Target prompts as { prompt, type, topic } objects |
isPublic | Whether the article is publicly accessible via your brand feed |
isPillar | Whether this is a pillar (cornerstone) article |
keywords | Target keywords with type (primary / secondary) |
provider | CMS provider(s) if published (wordpress, shopify, webflow, ghost, webhook, framer, grigora, embed) |
generating / generationKind / finalizing | Whether a generation or update job is running, which kind, and whether post-generation JSON-LD and audit work is still finishing |
categories / tags | Assigned taxonomy names |
Authorizations
Your SnowSEO API key (sk_...).
Query Parameters
Team ID
JSON all-matching or explicit article-slug selection, resolved only for bulk actions.
Page number (default: 1)
Items per page (default: 20, or "all")
Filter by status (draft, processing, generated, scheduled, published, failed, manual) or "all"
draft, processing, generated, scheduled, published, failed, manual, all Filter to articles belonging to a topic cluster
ISO date - only articles whose scheduledAt or publishedAt is on/after this (calendar-window scoping)
ISO date - only articles whose scheduledAt or publishedAt is on/before this (calendar-window scoping)
Case-insensitive search across title, slug, keywords, prompts, providers, and topic name
Sort column
name, status, seo, topic, created, visitors Sort direction
asc, desc Connected analytics integration to read page visitors from: ga (Google Analytics), posthog, plausible or snow (Snow Analytics). Without it, rows carry no visitor counts, and sorting by visitors returns 400.
ga, posthog, plausible, snow Start of the visitor-count window, YYYY-MM-DD.
End of the visitor-count window, YYYY-MM-DD.
Filter to articles carrying this category name
Filter to articles carrying this tag name
Was this page helpful?

