/v1/brands/{brand_id}/content-briefs/{brief_id}/publish Publish a content brief
Publish a finished brief and return it with its updated status.
Set target_type to pick where it goes:
cms_connection: push the article to a connected site (WordPress, Ghost, Shopify, Webflow, Wix, a webhook or a GitHub repository). Pass the connection id fromGET /v1/brands/{brand_id}/cms-connectionsastarget_id. Publishing the same brief to the same connection again updates the post in place rather than creating a duplicate. A GitHub repository gets a pull request instead: the publication answersdraftwith itsreview_urland goes live when the pull request merges (a repository set to commit directly takes a live send straight onto its branch and answerspublishedwith noreview_url); a draft send answersdraftwith its draft pull request asreview_url, and is refused (400) on a post already live there; scheduled, it opens nothing on GitHub until its time, so the repository holds nothing while it waits.hosted_site: publish to the brand's RankPrompt-hosted blog, which must already be active.external: record anexternal_urlyou published yourself, pushing nothing anywhere.
Use publish_status: draft to land the post as a CMS draft. scheduled_for queues the publish instead: the post waits on the site as a draft (the hosted blog keeps it in RankPrompt) and our queue makes it live at that time, retrying a site that does not answer. A draft cannot be scheduled: publish_status: draft with scheduled_for is a 400. A scheduled brief stays in needs_review until it actually goes live.
Publishing approves any open review on the article.
Path parameters
-
Content brief id (UUID).
-
Brand UUID.
Query parameters
-
Preview the call without executing it. Runs auth, scope, eligibility and body validation, then returns
200with adry_runobject reporting the request-unit and credit cost plus a non-consuming quota snapshot. Nothing is debited, reserved, dispatched or mutated. An invalid body still returns422.default: false
Header parameters
-
Required with an API key, else
400 idempotency_key_required: a new value per operation (a UUID works). A retry with the same key and body within 24 hours replays the first response instead of running again. Ignored withdry_run=true.
Request body
application/json required- external_url string (nullable) nullable
Canonical URL where the content was published. Only used when
target_typeisexternal. - publish_status enum
Whether the CMS post goes live (
publish) or is created as a draft for someone to review in the CMS (draft). Ignored forexternal.Left out, the post goes live even when the brand's owner has every send to that site start as a draft: read the target's
default_status(GET .../publish-targetsorGET .../cms-connections) and senddraftwhen it saysdraft, unless the person asked for it live. - scheduled_for string (nullable) nullable
Publish at this time instead of now, as an ISO-8601 datetime in the future. The post waits on the site as a draft (the hosted blog keeps it in RankPrompt) until our queue makes it live at that time, retrying a site that does not answer; the brief stays in
needs_reviewuntil then. Not accepted withpublish_status: draft.Scheduling a brief that is already published leaves the live post as it is until that time, then updates it.
- target_id string (nullable) nullable
The CMS connection id, required for
cms_connection. Leave it out forhosted_site, which is resolved from the brand, and forexternal. - target_type enum
Where to publish:
cms_connection: push the article to a connected destination (WordPress, Ghost, Shopify, Webflow, Wix, a GitHub repository or a webhook). Settarget_idto the connection id fromGET /v1/brands/{brand_id}/cms-connections.hosted_site: publish to the brand's RankPrompt-hosted blog, which is resolved from the brand. The hosted site must already be active; setting one up needs interactive DNS in the app.external: publish nothing, just mark the brief published and recordexternal_url, for when you pushed the article somewhere else yourself.
Responses
-
Owning brand id (UUID).
-
When the brief was created.
-
Content brief id (UUID).
-
Brief lifecycle state. One of
draft,processing,needs_review,published,failed. - assets array of ContentAsset
Generated assets (article HTML, images, meta).
- content_context object
The format's own fields (the ones a content opportunity pre-fills, e.g.
listThemeandlistSizeforranked_list), plussources:{"urls": [...], "only_mine": false}, up to 10 pages or PDFs the article reads before writing and cites, each reported inquality_report.enforcement.sourcesasused,not_usedorsource_unreadable(only_mine: trueturns web search off and unwraps any other outside link),sourcePrompts: ids of the report prompts the article answers, andlength:{"mode": "auto"|"short"|"standard"|"long"}or{"mode": "exact", "words": 300-5000}(omitted: the brand'sdefault_length), andblockedWords: up to 100 phrases of up to 100 characters this article must not use on top of the brand'sbanned_phrases, andknowledge:{"mode": "auto"}(the knowledge base chunks closest to the topic, the default),{"mode": "pick", "ids": [...]}(only those knowledge base items) or{"mode": "off"}. This article only:language(a language name, over the brand's),tone(up to 200 characters, over the brand's),audience(who it is written for, up to 200 characters) andtools({tool: on|off|auto}over the brand's AI tools, see content preferences). Other keys are ignored; the brand's banned phrases stay in its preferences.Show fields
Empty object (no properties).
- content_type string (nullable) nullable
Content format id (e.g.
blog_post,ranked_list). - error_message string (nullable) nullable
User-facing failure reason when
statusisfailed. - generated_at string (nullable) nullable
When content was last generated, if ever.
- generation_settings object | array of any
What the last run wrote with and where each value came from:
language,tone,length,audience,banned_phrases,knowledgeandsourcesas{value, origin}, andtoolsas{value: {tool: mode}, origin: {tool: origin}};originisarticle(this brief'scontent_context),brand(the brand's content preferences) orsystem. A regeneration keeps the brand values it records unless asked for today's. Null before the first run. - mode enum
createwrites a new article;optimizeimproves the page atsource_url(content-optimizations). - object string
Always
content_brief. - opportunity_id string (nullable) nullable
The content opportunity this article answers, when it was created from one.
- optimize_level enum (nullable) nullable
How far an
optimizebrief goes; null forcreate. - outline_json object | array of any
Structured article outline produced during generation.
- planned_publish_at string (nullable) nullable
The day the article sits on in the content calendar until it is published or a publish is queued; null when it has none. Set it with
PATCH /v1/brands/{brand_id}/content-briefs/{brief_id}. - publications array of ContentPublication
Every place the article was published, with its live URL. Empty until it is published.
- quality_report object | array of any
Rule-based checks run on the finished article:
{score, axes[], checks[], notes[], words, language, link_check}, wherescoreis the percentage of weighted checks that passed.link_checkis the source check run after writing:checked(how many external links were fetched),removed[](links unwrapped because the page is gone:url,reason,status),warnings[](links kept but worth a look, each{url, reason}:moved_to_rootwhen a deep link now lands on the site's home page, with thefinal_urlit landed on,unverifiedwhen the research never read the page) andunverified_claims[]({sentence, numbers[], urls[], reason},reasonbeingnot_on_sourcewhen the cited page does not carry the figures,source_removedwhen every cited link was removed,source_unreadablewhen no cited page could be read). Advisory only; it never blocks publishing. - research_output string (nullable) nullable
Research notes gathered during generation.
- review_due_at string (nullable) nullable
When the article's fastest-ageing fact (a price, a plan tier) is worth re-checking.
- serp_research object | array of any
What Google ranked for the target keyword when the article was researched:
pages(rank, url, domain, title, words, published_at, reachable),people_also_ask,features,table_stakes(subtopics most top pages cover),differentiators,median_wordsandintent(Google's main intent for the keyword:informational,commercial,transactionalornavigational, null when unknown). Null when the results page was unavailable. - source_url string (nullable) nullable
The brand's own page an
optimizebrief improves. - target_keywords array of string
Target keywords for the brief.
- title string (nullable) nullable
Brief title, set on creation or filled in from the article.
- topic string (nullable) nullable
Topic or target keyword the content is written around.
- updated_at string (nullable) nullable
When the brief was last updated.
-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "validation_error",
"message": "Request validation failed"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid credentials"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "forbidden",
"message": "You do not have permission to access this resource"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "not_found",
"message": "Resource not found"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "conflict",
"message": "Resource conflict"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "body_validation_error",
"message": "Request body did not match the expected schema"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "rate_limit_exceeded",
"message": "Per-minute rate limit exceeded"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "internal_error",
"message": "An unexpected error occurred"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}-
Show fields
-
Stable machine-readable error code from the catalog.
-
Human-readable description suitable for logging.
- details object
Optional, code-specific context (e.g.
errorsarray forvalidation_error,retry_afterforservice_unavailable). Shape depends onerror.code; treat as opaque otherwise.Show fields
Empty object (no properties).
-
- request_id string
Server-generated correlation id for the request. Mirrors the
X-Correlation-IDresponse header. Include this when contacting support.
Example response
{
"error": {
"code": "service_unavailable",
"message": "Service temporarily unavailable, please retry"
},
"request_id": "9f6c4e8a-1d3b-4c8b-9f1e-7a3b1c2d3e4f"
}