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.
Endpoint
Section titled “Endpoint”GET /api/agent/v1/copywriter/jobs/:id/artifactsAuthorization: Bearer rk_live_...Replace :id with the job_id returned when you created the job.
When to call
Section titled “When to call”- 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). Thedraftandscorefields will benulluntil 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.
Scope required
Section titled “Scope required”copywriter:read
Full response example
Section titled “Full response example”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 } } }}Artifact reference
Section titled “Artifact reference”Each field in the response serves a specific purpose. Below is a detailed breakdown.
outline
Section titled “outline”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_tagas your page’s<title>element. - Set
meta_descriptionas the<meta name="description" content="...">tag. - Use
h1as the visible page heading. This may differ slightly from the title tag for better on-page optimization.
entities
Section titled “entities”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.
faq_schema_json_ld
Section titled “faq_schema_json_ld”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.
Word-count targets and keyword coverage
Section titled “Word-count targets and keyword coverage”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.
Edit or remove a saved project
Section titled “Edit or remove a saved project”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.
Stepped mode: partial artifacts
Section titled “Stepped mode: partial artifacts”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/approveAuthorization: Bearer rk_live_...Then poll the status endpoint until "completed" and fetch artifacts again for the full set.
Practical examples
Section titled “Practical examples”Publishing to a CMS
Section titled “Publishing to a CMS”After retrieving artifacts, map each field to your CMS:
seo.title_tag→ Page title /<title>seo.meta_description→ Meta description fieldseo.h1→ Page headingdraft.content→ Post body (convert Markdown to HTML if needed)faq_schema_json_ld→ Custom code / head injection field
Quality gate automation
Section titled “Quality gate automation”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"])Building a table of contents
Section titled “Building a table of contents”for section in artifacts["outline"]: print(f"{section['level']}: {section['heading']}") for sub in section.get("subheadings", []): print(f" {sub['level']}: {sub['heading']}")Error responses
Section titled “Error responses”| 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 |
Related articles
Section titled “Related articles”- Creating content jobs — How to create jobs and understand auto vs stepped mode.
- Getting started with the API — End-to-end walkthrough from API key to finished content.
- Understanding your content score — How the 0–100 content score is calculated and what each category measures.
