Content and publishing
Posts, pages, pictures and the AI auto-posting campaigns, on every site type.
What a post on this site can have
GET/api/v1/sites/{site_id}/content/optionsScope content:read
Before writing anything, ask this: it says how a post appears on this site type, which fields it supports (featured picture, categories, tags, author, drafts) and the real categories and authors the site has. Site types with no drafts publish straight away - the answer says so.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
Example
curl -s "https://app.pbn.ltd/api/v1/sites/123/content/options" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/content/options", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/content/options", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"site_id": 123,
"domain": "example.com",
"type": "Wordpress",
"how": "Published as a WordPress post with its featured image, categories, tags and author.",
"supports": {
"featured": true,
"categories": true,
"tags": true,
"authors": true,
"drafts": true
},
"statuses": [
"publish",
"draft"
],
"categories": [
{
"id": "1",
"name": "Uncategorised"
}
],
"authors": [
{
"id": "1",
"name": "Ann Example"
}
],
"media_uploads": true,
"options_error": null
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, unauthorized
Posts on this site
GET/api/v1/sites/{site_id}/contentScope content:read
The latest posts the site itself reports, and every post this account has written for it through PBN.LTD (including ones still being written or waiting to go out).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
limit | query | integer | no | How many to return. Default: 20. |
state | query | string (one of: queued, writing, images, review, ready, publishing, done, failed, cancelled) | no | Only posts in this state. |
on_site | query | boolean | no | Also ask the site itself for its latest posts (slower). Default: True. |
Example
curl -s "https://app.pbn.ltd/api/v1/sites/123/content" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/content", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/content", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"site_id": 123,
"on_site": [
{
"title": "Welcome",
"url": "https://example.com/welcome/"
}
],
"on_site_error": null,
"ours": [
{
"id": 90210,
"site_id": 123,
"title": "Five ways to speed up your shop",
"slug": "five-ways",
"state": "done",
"state_text": "Published",
"step": "Published",
"source": "manual",
"status": "publish",
"tags": [
"speed",
"shop"
],
"excerpt": "A short summary of the post.",
"url": "https://example.com/blog/five-ways/",
"remote_id": "412",
"publish_at": "2026-09-20T10:00:00Z",
"published_at": "2026-09-20T10:00:14Z",
"created_at": "2026-09-20T09:59:02Z",
"error": null,
"error_code": null,
"campaign_id": null,
"images": 1
}
]
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, unauthorized
Everything being written or published
GET/api/v1/content/queueScope content:read
Every post on the account that is queued, being written, waiting for approval, scheduled, publishing, published, failed or cancelled - newest first, across all sites.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | no | How many to return. Default: 20. |
cursor | query | string | no | The next_cursor value of the previous page. |
state | query | string (one of: queued, writing, images, review, ready, publishing, done, failed, cancelled) | no | Only posts in this state. |
site_id | query | integer | no | Only this site. |
Example
curl -s "https://app.pbn.ltd/api/v1/content/queue" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/content/queue", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/content/queue", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 90210,
"site_id": 123,
"title": "Five ways to speed up your shop",
"slug": "five-ways",
"state": "done",
"state_text": "Published",
"step": "Published",
"source": "manual",
"status": "publish",
"tags": [
"speed",
"shop"
],
"excerpt": "A short summary of the post.",
"url": "https://example.com/blog/five-ways/",
"remote_id": "412",
"publish_at": "2026-09-20T10:00:00Z",
"published_at": "2026-09-20T10:00:14Z",
"created_at": "2026-09-20T09:59:02Z",
"error": null,
"error_code": null,
"campaign_id": null,
"images": 1
}
],
"next_cursor": null,
"has_more": false
}
Errors: payment_required, rate_limited, scope_missing, unauthorized
Read one post
GET/api/v1/sites/{site_id}/content/{post_id}Scope content:read
One post in full, with its text and the history of what happened to it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
post_id | path | integer | yes | The post id this API gave you when it was created. |
Example
curl -s "https://app.pbn.ltd/api/v1/sites/123/content/90210" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/content/90210", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/content/90210", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 90210,
"site_id": 123,
"title": "Five ways to speed up your shop",
"slug": "five-ways",
"state": "done",
"state_text": "Published",
"step": "Published",
"source": "manual",
"status": "publish",
"tags": [
"speed",
"shop"
],
"excerpt": "A short summary of the post.",
"url": "https://example.com/blog/five-ways/",
"remote_id": "412",
"publish_at": "2026-09-20T10:00:00Z",
"published_at": "2026-09-20T10:00:14Z",
"created_at": "2026-09-20T09:59:02Z",
"error": null,
"error_code": null,
"campaign_id": null,
"images": 1,
"body_html": "<p>The text of the post.</p>",
"events": [
{
"at": "2026-09-20T10:00:14Z",
"kind": "step",
"message": "Published: https://example.com/blog/five-ways/"
}
]
}
}
Errors: not_found, payment_required, rate_limited, scope_missing, unauthorized
Publish a post or page
POST/api/v1/sites/{site_id}/contentScope content:write · returns a job
Writes the post and puts it on the site. Works for every site type: WordPress, Joomla, Drupal, PrestaShop, OpenCart, Grav and MediaWiki get a native post/article/page, and Static HTML and PHP hosting sites get a page built in the look of their own pages, with a blog index and sitemap.xml kept up to date. The answer carries a job - wait for it and then read the post to get its address.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
title | body | string | yes | The title of the post. |
body_html | body | string | no | The text as HTML. Or send body_markdown. |
body_markdown | body | string | no | The text as Markdown (headings, lists, links, bold, code, quotes). |
status | body | string (one of: publish, draft) | no | "draft" only on site types that have drafts (see content.options). Default: publish. |
category | body | string | no | Category id or name, on site types that have them. |
author | body | string | no | Author id, on site types that have authors. |
tags | body | array | no | Tags for the post. |
slug | body | string | no | The address of the post; one is made from the title when you leave it out. |
publish_at | body | string | no | ISO date and time to publish it (default: now). |
featured_image_base64 | body | string | no | The main picture, base64. It leads the post and becomes the featured image on site types that have one. |
images_base64 | body | array | no | More pictures, base64; they are placed in the text. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/content" \
-H "Authorization: Bearer $PBN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title": "Five ways to speed up your shop", "body_markdown": "## Why speed matters\n\nA faster shop sells more.", "status": "publish", "tags": ["speed", "shop"]}'
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/content", headers=headers, json={"title": "Five ways to speed up your shop", "body_markdown": "## Why speed matters\n\nA faster shop sells more.", "status": "publish", "tags": ["speed", "shop"]}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/content", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
body: JSON.stringify({"title": "Five ways to speed up your shop", "body_markdown": "## Why speed matters\n\nA faster shop sells more.", "status": "publish", "tags": ["speed", "shop"]})
});
console.log(res.status, await res.json());
Response
202
{
"data": {
"id": 90210,
"site_id": 123,
"title": "Five ways to speed up your shop",
"slug": "five-ways",
"state": "done",
"state_text": "Published",
"step": "Published",
"source": "manual",
"status": "publish",
"tags": [
"speed",
"shop"
],
"excerpt": "A short summary of the post.",
"url": "https://example.com/blog/five-ways/",
"remote_id": "412",
"publish_at": "2026-09-20T10:00:00Z",
"published_at": "2026-09-20T10:00:14Z",
"created_at": "2026-09-20T09:59:02Z",
"error": null,
"error_code": null,
"campaign_id": null,
"images": 1
},
"job": {
"id": "job_4f1c0a9e2b7d6c5a3e10",
"kind": "...",
"status": "running",
"url": "https://app.pbn.ltd/api/v1/jobs/job_4f1c0a9e2b7d6c5a3e10"
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, too_large, unauthorized, validation_failed
Change a post
PATCH/api/v1/sites/{site_id}/content/{post_id}Scope content:write
Changes a post that has not gone out yet. A post that is already on the site cannot be edited from here - remove it and write a new one.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
post_id | path | integer | yes | The post id this API gave you when it was created. |
title | body | string | no | A new title. |
body_html | body | string | no | New text as HTML. |
body_markdown | body | string | no | New text as Markdown. |
tags | body | array | no | Replace the tags. |
status | body | string (one of: publish, draft) | no | |
publish_at | body | string | no | Move when it goes out. |
approve | body | boolean | no | Approve a post that is waiting for approval. |
Example
curl -s -X PATCH "https://app.pbn.ltd/api/v1/sites/123/content/90210" \
-H "Authorization: Bearer $PBN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title": "Five ways to speed up your shop (updated)"}'
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.patch("https://app.pbn.ltd/api/v1/sites/123/content/90210", headers=headers, json={"title": "Five ways to speed up your shop (updated)"}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/content/90210", {
method: "PATCH",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
body: JSON.stringify({"title": "Five ways to speed up your shop (updated)"})
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 90210,
"site_id": 123,
"title": "Five ways to speed up your shop",
"slug": "five-ways",
"state": "ready",
"state_text": "Scheduled",
"step": "Published",
"source": "manual",
"status": "publish",
"tags": [
"speed",
"shop"
],
"excerpt": "A short summary of the post.",
"url": "https://example.com/blog/five-ways/",
"remote_id": "412",
"publish_at": "2026-09-20T10:00:00Z",
"published_at": "2026-09-20T10:00:14Z",
"created_at": "2026-09-20T09:59:02Z",
"error": null,
"error_code": null,
"campaign_id": null,
"images": 1,
"body_html": "<p>The new text.</p>"
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, unauthorized, validation_failed
Take a post off the site
DELETE/api/v1/sites/{site_id}/content/{post_id}Scope content:write · destructive
Removes a published post from the site, or cancels one that has not gone out yet. There is no undo.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
post_id | path | integer | yes | The post id this API gave you when it was created. |
Example
curl -s -X DELETE "https://app.pbn.ltd/api/v1/sites/123/content/90210" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.delete("https://app.pbn.ltd/api/v1/sites/123/content/90210", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/content/90210", {
method: "DELETE",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 90210,
"removed": true,
"was": "published"
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, unauthorized
Upload a picture or file
POST/api/v1/sites/{site_id}/content/mediaScope content:write
Puts a picture or file on the site and gives back the address to use in a post. On WordPress it goes into the media library; on every other site type it goes into the site's own files.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
name | body | string | yes | The file name, e.g. "hero.jpg". |
content_base64 | body | string | yes | The file itself, base64. |
alt | body | string | no | Alt text (WordPress media library). |
folder | body | string | no | Where to put it on site types with no media library. Default: assets. |
overwrite | body | boolean | no | Replace a file of the same name. Default: False. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/content/media" \
-H "Authorization: Bearer $PBN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "hero.jpg", "content_base64": "iVBORw0KGgo=", "alt": "The shop front"}'
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/content/media", headers=headers, json={"name": "hero.jpg", "content_base64": "iVBORw0KGgo=", "alt": "The shop front"}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/content/media", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
body: JSON.stringify({"name": "hero.jpg", "content_base64": "iVBORw0KGgo=", "alt": "The shop front"})
});
console.log(res.status, await res.json());
Response
201
{
"data": {
"name": "hero.jpg",
"url": "https://example.com/wp-content/uploads/2026/09/hero.jpg",
"media_id": "881",
"where": "the WordPress media library",
"bytes": 145322
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, too_large, unauthorized, validation_failed
List auto-posting campaigns
GET/api/v1/campaignsScope content:read
The AI auto-posting campaigns on the account: what they write, when they run next and how many articles they have made.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | no | How many to return. Default: 20. |
cursor | query | string | no | The next_cursor value of the previous page. |
status | query | string (one of: active, paused, problem, finished) | no |
Example
curl -s "https://app.pbn.ltd/api/v1/campaigns" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/campaigns", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/campaigns", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 44,
"name": "Weekly shop tips",
"status": "active",
"status_reason": null,
"schedule": "weekly",
"times": "09:00",
"weekdays": "0,3",
"timezone": "Europe/London",
"per_site": 1,
"review": "auto",
"total_limit": 0,
"articles_created": 12,
"next_run_at": "2026-09-23T08:00:00Z",
"last_run_at": "2026-09-19T08:00:00Z",
"site_ids": [
123,
124
],
"created_at": "2026-07-01T10:00:00Z"
}
],
"next_cursor": null,
"has_more": false
}
Errors: payment_required, rate_limited, scope_missing, unauthorized
Read one campaign
GET/api/v1/campaigns/{campaign_id}Scope content:read
One campaign with its last ten runs.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
campaign_id | path | integer | yes | The campaign. |
Example
curl -s "https://app.pbn.ltd/api/v1/campaigns/44" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/campaigns/44", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/campaigns/44", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 44,
"name": "Weekly shop tips",
"status": "active",
"status_reason": null,
"schedule": "weekly",
"times": "09:00",
"weekdays": "0,3",
"timezone": "Europe/London",
"per_site": 1,
"review": "auto",
"total_limit": 0,
"articles_created": 12,
"next_run_at": "2026-09-23T08:00:00Z",
"last_run_at": "2026-09-19T08:00:00Z",
"site_ids": [
123,
124
],
"created_at": "2026-07-01T10:00:00Z",
"runs": [
{
"id": 7781,
"trigger": "schedule",
"slot_at": "2026-09-19T08:00:00Z",
"total": 2,
"done": 2,
"failed": 0,
"cancelled": 0,
"finished_at": "2026-09-19T08:04:11Z",
"state": "finished"
}
]
}
}
Errors: not_found, payment_required, rate_limited, scope_missing, unauthorized
Pause or resume
PUT/api/v1/campaigns/{campaign_id}/statusScope content:write
Pauses a campaign or starts it again. A campaign paused by our staff or by a problem with an AI key cannot be resumed from here - fix the cause first.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
campaign_id | path | integer | yes | |
status | body | string (one of: active, paused) | yes | "paused" stops it writing; "active" starts it again. |
Example
curl -s -X PUT "https://app.pbn.ltd/api/v1/campaigns/44/status" \
-H "Authorization: Bearer $PBN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "paused"}'
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.put("https://app.pbn.ltd/api/v1/campaigns/44/status", headers=headers, json={"status": "paused"}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/campaigns/44/status", {
method: "PUT",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
body: JSON.stringify({"status": "paused"})
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 44,
"name": "Weekly shop tips",
"status": "active",
"status_reason": null,
"schedule": "weekly",
"times": "09:00",
"weekdays": "0,3",
"timezone": "Europe/London",
"per_site": 1,
"review": "auto",
"total_limit": 0,
"articles_created": 12,
"next_run_at": "2026-09-23T08:00:00Z",
"last_run_at": "2026-09-19T08:00:00Z",
"site_ids": [
123,
124
],
"created_at": "2026-07-01T10:00:00Z"
}
}
Errors: not_found, payment_required, rate_limited, scope_missing, unauthorized, validation_failed
Write one now
POST/api/v1/campaigns/{campaign_id}/write-nowScope content:write
Asks a campaign to write and publish now, the same as the "Write now" button. Returns the run; follow it with runs.get.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
campaign_id | path | integer | yes | |
site_ids | body | array | no | Only these sites of the campaign (default: all of them). |
count | body | integer | no | Articles per site. Default: 1. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/campaigns/44/write-now" \
-H "Authorization: Bearer $PBN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"count": 1}'
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/campaigns/44/write-now", headers=headers, json={"count": 1}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/campaigns/44/write-now", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
body: JSON.stringify({"count": 1})
});
console.log(res.status, await res.json());
Response
202
{
"data": {
"run_id": 7782,
"articles": 2,
"problems": []
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, unauthorized
How a run is going
GET/api/v1/runs/{run_id}Scope content:read
One run of a campaign and every article in it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id | path | integer | yes | The run. |
Example
curl -s "https://app.pbn.ltd/api/v1/runs/7782" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/runs/7782", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/runs/7782", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 7782,
"campaign_id": 44,
"trigger": "manual",
"slot_at": "2026-09-20T10:00:00Z",
"total": 2,
"done": 1,
"failed": 0,
"cancelled": 0,
"finished_at": null,
"state": "running",
"articles": [
{
"id": 90210,
"site_id": 123,
"title": "Five ways to speed up your shop",
"slug": "five-ways",
"state": "done",
"state_text": "Published",
"step": "Published",
"source": "manual",
"status": "publish",
"tags": [
"speed",
"shop"
],
"excerpt": "A short summary of the post.",
"url": "https://example.com/blog/five-ways/",
"remote_id": "412",
"publish_at": "2026-09-20T10:00:00Z",
"published_at": "2026-09-20T10:00:14Z",
"created_at": "2026-09-20T09:59:02Z",
"error": null,
"error_code": null,
"campaign_id": null,
"images": 1
}
]
}
}
Errors: not_found, payment_required, rate_limited, scope_missing, unauthorized