/v1/brands/{brand_id}/content-briefs Create a content brief
Create a content brief and generate its content inline, returning the finished article.
The AI pipeline runs synchronously and routinely takes minutes, so allow a long timeout, and prefer POST /v1/brands/{brand_id}/content-briefs/generations for anything unattended, which queues the same work and hands you a job to poll. A client that gives up on this request does not stop the pipeline: it keeps running and still charges.
Provide a topic or at least one target_keywords entry. Costs credits, charged to the brand's owner.
Path parameters
-
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- content_context object
The format's own fields (the ones a content opportunity pre-fills, e.g.
listThemeandlistSizeforranked_list), plussources(see the brief'scontent_context), andlength,knowledge,language,tone,audienceandtools(see the brief'scontent_context). Those keys are checked: an unknownlanguage, atoneoraudienceover 200 characters, a tool or mode outside the lists, or a source that is not an http(s) address answers 422. Other keys are ignored.Show fields
Empty object (no properties).
- content_type enum (nullable) nullable
Content format to generate; inferred from the topic when omitted.
- opportunity_id string (nullable) nullable
The
idof the content opportunity this article answers. - planned_publish_at string (nullable) nullable
When it should go live. It prefills the CMS schedule; nothing fires from it.
- source_prompt_ids array of string
Report prompts this article is written to answer. They are snapshotted now, so the citation uplift can later say which of them came back.
- target_keywords array of string
Target keywords to write around (each up to 200 chars).
- title string (nullable) nullable
Optional title; the generator fills one in when omitted.
- topic string (nullable) nullable
Topic or target keyword to write about. Provide this or at least one
target_keywordsentry.
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": "insufficient_credits",
"message": "Not enough credits to complete this operation"
},
"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"
}