Skip to content

Retrieving and using artifacts

Learn how to fetch structured output from completed content jobs — outline, draft, SEO metadata, entities, FAQs, FAQ schema, and content score — and how to use each piece in your publishing workflow.

Learn how to fetch structured output from completed content jobs — outline, draft, SEO metadata, entities, FAQs, FAQ schema, and content score — and how to use each piece in your publishing workflow.

After a content job reaches the completed status (or brief_ready in stepped mode), you can retrieve its structured artifacts. Each artifact is a self-contained piece of content you can feed directly into your CMS, page template, or downstream automation.

Use GET /api/agent/v1/copywriter/queue/status when you need the organization’s bounded research and draft queue position, estimated wait, or service alerts. It is a read-only operational status call and does not start work.

GET /api/agent/v1/copywriter/jobs/:id/artifacts
Authorization: Bearer rk_live_...

Replace :id with the job_id returned when you created the job.

  • Auto mode — Call after the status endpoint returns "completed".
  • Stepped mode at brief_ready — You can call immediately to inspect partial artifacts (outline, SEO metadata, entities, FAQs). The draft and score fields will be null until you approve the brief and the draft finishes generating.
  • Stepped mode after approval — Poll the status endpoint until "completed", then call artifacts for the full set.

If you call the endpoint before the job is ready, the API returns 409 with the code not_ready.

copywriter:read

A completed job returns the following JSON structure:

{
"outline": [
{
"heading": "What Is Emergency Plumbing?",
"level": "h2",
"subheadings": [
{ "heading": "Signs You Need Emergency Service", "level": "h3" }
]
}
],
"draft": {
"format": "markdown",
"content": "# Emergency Plumber St. Louis\n\nWhen a pipe bursts...",
"word_count": 1247
},
"seo": {
"title_tag": "Emergency Plumber St. Louis | 24/7 Licensed Service",
"meta_description": "Need an emergency plumber in St. Louis? ...",
"h1": "Emergency Plumber St. Louis"
},
"entities": [
{ "name": "St. Louis", "type": "location", "relevance": 0.95 }
],
"faqs": [
{
"question": "How much does an emergency plumber cost in St. Louis?",
"answer": "Emergency plumbing in St. Louis typically costs..."
}
],
"faq_schema_json_ld": "{\"@context\":\"https://schema.org\",\"@type\":\"FAQPage\",...}",
"score": {
"overall": 82,
"overall_max": 100,
"calculated_at": "2026-09-22T17:36:39.879Z",
"scored_revision": "sha256:abc123...",
"draft_revision": "sha256:abc123...",
"freshness_state": "current",
"score_source": "editor",
"calculation_state": "partial_categories",
"category_model": "partial_current",
"category_total": 38,
"overall_category_delta": 44,
"categories": {
"copywriting": 17,
"readability": 8,
"seo": 13
},
"category_details": {
"copywriting": { "score": 17, "max_score": 20, "percent": 85 },
"readability": { "score": 8, "max_score": 10, "percent": 80 },
"seo": { "score": 13, "max_score": 15, "percent": 86.7 }
}
}
}

Each field in the response serves a specific purpose. Below is a detailed breakdown.

An ordered array of heading objects representing the article structure.

Field Type Description
heading string The heading text
level string HTML heading level: h2, h3, or h4
subheadings array Nested headings under this section (same shape, recursive)

How to use: Compare the outline against your content strategy before approval (stepped mode). You can also use it to generate a table of contents or validate that the draft covers every planned section.

The generated article content.

Field Type Description
format string Always "markdown"
content string The full article in Markdown format
word_count integer Total word count of the draft

How to use: Convert the Markdown to HTML for your CMS, or pass it directly to a headless CMS that accepts Markdown. The content is ready to publish but you may want to add your own images, internal links, or brand-specific formatting.

Stepped mode note: This field is null at brief_ready. It populates after the brief is approved and the draft finishes generating.

Pre-written SEO metadata for the page.

Field Type Description
title_tag string Suggested <title> tag (typically 50–60 characters)
meta_description string Suggested meta description (typically 150–160 characters)
h1 string Suggested H1 heading for the page

How to use:

  • Set title_tag as your page’s <title> element.
  • Set meta_description as the <meta name="description" content="..."> tag.
  • Use h1 as the visible page heading. This may differ slightly from the title tag for better on-page optimization.

Named entities extracted during research, ranked by relevance to the topic.

Field Type Description
name string The entity name (e.g., “St. Louis”, “PVC pipe”)
type string Entity category (e.g., location, material, brand, concept)
relevance number Relevance score from 0 to 1

How to use: Entities help you understand topical coverage. High-relevance entities that are missing from your draft may represent gaps. You can also use entities for internal linking, tagging, or building topic clusters.

Question-and-answer pairs derived from competitor content and People Also Ask data.

Field Type Description
question string A frequently asked question about the topic
answer string A concise answer to the question

How to use: Add these as an FAQ section at the bottom of your article, or weave individual Q&A pairs into relevant sections of the content. FAQs improve the chance of appearing in Google’s featured snippets and People Also Ask boxes.

A ready-to-use JSON-LD string for the FAQPage structured data type.

How to use: Inject this string into your page’s <head> inside a <script type="application/ld+json"> tag:

<script type="application/ld+json">
{{ faq_schema_json_ld }}
</script>

This tells search engines that your page contains FAQ content, which can trigger rich results in the SERP. The schema is pre-built from the faqs array — you do not need to construct it yourself.

The content optimization score, calculated by comparing your draft against top-ranking competitors.

Field Type Description
overall integer Composite score from 0 to 100
overall_max integer Maximum overall score; currently 100
calculated_at string or null When this exact score snapshot was calculated; null for unverifiable historical rows
scored_revision string or null Opaque revision of the draft body used for the score
draft_revision string or null Opaque revision of the currently saved draft body
freshness_state string current, stale, or unverified
score_source string Whether the overall came from the editor, server scoring, or a legacy record
calculation_state string Whether the stored overall and available category model are internally comparable
category_model string Current seven-category, partial-current, legacy/unknown, or unavailable category model
category_total integer or null Sum of the returned category values
overall_category_delta integer or null Stored overall minus category_total
categories object Backward-compatible numeric category scores
category_details object Each category’s score, max_score, and percentage of its maximum

The standard category maxima are Copywriting 20, Readability 10, SEO 15, Structure 10, Coverage 15, Uniqueness 20, and Credibility 10. A legacy category without a defined modern maximum returns max_score: null and percent: null rather than an invented denominator. legacy_mismatch means the stored overall and seven-category total differ; it does not by itself mean the overall is stale. Use freshness_state for draft freshness. Do not describe the category difference as weighting unless the response explicitly supplies a weighted model.

How to use: Request draft and quality_score together. Use the overall score as a quality gate only when freshness_state is current. Retry or request review when it is stale; historical records without enough provenance return unverified. With legacy_mismatch, preserve overall as the editor score and treat the categories as informational rather than adding them together.

Stepped mode note: This field is null at brief_ready. The score is only available after the draft is generated.

Before drafting, read target_word_count_min and target_word_count_max from the project or artifacts. These match the editor’s target range and are available at brief_ready. word_count_target also identifies whether it is a locked competitor target, a requested override, or a default fallback. The older target_word_count is a separate single-number brief hint.

Use include=word_count_target (or seo_assets) for the range, and include=keywords,quality_score to inspect recommendations and draft coverage. keywords includes covered/uncovered state, usage counts, recommended usage, ignored state, score eligibility, and any required verification. Page using keyword_limit (1–100, default 50) and keyword_offset; follow keyword_checklist.next_offset until has_more is false. Before drafting, coverage is null rather than zero. These are unfiltered saved-project results, not unsaved browser-local custom keywords or unsaved text. Guidance/ignored rows can make checklist totals differ from scored keyword totals.

score.editor_breakdown provides the editor’s coverage (85%) and placement (15%) components, keyword totals, and individual placement checks. The separate seven-category fields remain available when that model has been saved; categories_unavailable does not mean the editor breakdown is unavailable. No new research, paid scoring, or project writes are started by these reads.

These lifecycle routes use the normal organization scope. Send a stable Idempotency-Key header on every mutation so reconnect retries do not repeat the operation.

Method Path Purpose
PATCH /api/agent/v1/copywriter/jobs/:id/brief Patch selected fields of a stepped-mode brief before approval
PUT /api/agent/v1/copywriter/jobs/:id/draft Replace the complete draft body with Markdown or HTML
DELETE /api/agent/v1/copywriter/jobs/:id Permanently delete the project and its saved artifacts

Brief patching preserves omitted sections and refuses jobs that are not in the editable brief-ready state. Draft replacement refuses an active generation job and resets scores and review artifacts tied to the previous body. Deletion is permanent. Read the current project first and require a human confirmation of the exact topic before replacing or deleting content; the MCP tools enforce that preflight automatically.

In stepped mode, calling the artifacts endpoint at brief_ready returns a partial response. This lets you inspect the research output before committing to draft generation.

Field At brief_ready At completed
outline Available Available
draft null Available
seo Available Available
entities Available Available
faqs Available Available
faq_schema_json_ld Available Available
score null Available

To move from brief_ready to completed, approve the brief:

POST /api/agent/v1/copywriter/jobs/:id/approve
Authorization: Bearer rk_live_...

Then poll the status endpoint until "completed" and fetch artifacts again for the full set.

After retrieving artifacts, map each field to your CMS:

  • seo.title_tag → Page title / <title>
  • seo.meta_description → Meta description field
  • seo.h1 → Page heading
  • draft.content → Post body (convert Markdown to HTML if needed)
  • faq_schema_json_ld → Custom code / head injection field
artifacts = fetch_artifacts(job_id)
if artifacts["score"]["freshness_state"] == "current" and artifacts["score"]["overall"] >= 70:
publish_to_cms(artifacts)
else:
flag_for_review(job_id, artifacts["score"])
for section in artifacts["outline"]:
print(f"{section['level']}: {section['heading']}")
for sub in section.get("subheadings", []):
print(f" {sub['level']}: {sub['heading']}")
HTTP Code When
404 not_found Job ID does not exist or does not belong to your organization
409 not_ready Job has not completed yet — keep polling the status endpoint