ArticlesCreate article

POST /v1/articles

Create an article and start AI generation. Returns immediately with a queued article.

curl -X POST https://serpon.ai/v1/articles \
  -H "Authorization: Bearer $SERPON_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "project_id": 1,
    "title": "10 Best SEO Strategies for 2026",
    "article_type": "listicle",
    "target_word_count": 1500,
    "tone": "professional",
    "point_of_view": "second_person",
    "language": "en",
    "target_keyword": "SEO strategies 2026",
    "keywords": "search engine optimization, organic traffic",
    "country_targeting": "US",
    "research_enabled": true,
    "research_max_sources": 8,
    "webhook_url": "https://example.com/hooks/serpon"
  }'
{
  "success": true,
  "message": "Article created successfully! AI content generation has started.",
  "data": {
    "id": 123,
    "external_id": "550e8400-e29b-41d4-a716-446655440000",
    "title": "10 Best SEO Strategies for 2026",
    "description": null,
    "content": null,
    "original_content": null,
    "current_version_id": null,
    "published_version_id": null,
    "status": "queued",
    "article_type": "listicle",
    "target_keyword": "SEO strategies 2026",
    "keywords": ["search engine optimization", "organic traffic"],
    "target_word_count": 1500,
    "actual_word_count": 0,
    "tone": "professional",
    "point_of_view": "second_person",
    "language": "en",
    "country_targeting": "US",
    "ai_model_used": null,
    "cost": "0.00",
    "current_step": null,
    "humanize": false,
    "ai_detection_score": null,
    "originality_checked_at": null,
    "additional_context": null,
    "webhook_url": "https://example.com/hooks/serpon",
    "project": { "id": 1, "name": "My SEO Blog" },
    "created_at": "2026-08-02T10:30:00.000000Z",
    "updated_at": "2026-08-02T10:30:00.000000Z"
  }
}

Create an article and start generating it.

POST https://serpon.ai/v1/articles

The response arrives as soon as the job is queued — generation itself takes minutes. Supply a webhook_url to be notified on completion, or poll GET /v1/articles/{id}. See Article lifecycle.

Authentication

Bearer token in the Authorization header. See Authentication.

Cost

Creation reserves 120% of target_word_count against the account's monthly word allowance and fails with 422 if it does not fit. The allowance is then spent against the words actually generated. See Rate limits & quotas.

Body parameters

Required

body
project_idinteger
Required

The project the article belongs to. Must be a project on an account you can access.

body
titlestring
Required

3–255 characters. Also available to prompts as {title}.

body
article_typestring
Required

A built-in type, or a custom workflow type defined in this project. Determines which pipeline runs.

Built-in: blog_post, ultimate_guide, listicle, product_review, comparison, tutorial, news, case_study, song_meaning, song_meaning_single_gpt_5.

body
target_word_countinteger
Required

100–10,000. A target, not a guarantee — revision steps trim toward it.

body
tonestring
Required

professional, authoritative, friendly, conversational, casual, excited, or humorous. Also sets the generation temperature: the formal tones run cooler, the expressive ones hotter.

body
point_of_viewstring
Required

first_person, first_person_plural, second_person, or third_person.

body
languagestring
Required

en, es, fr, de, it, pt, ru, ja, ko, or zh.

SEO and targeting

body
target_keywordstring

Primary keyword, max 255 characters. Used throughout the prompts and as the search query when research is enabled.

body
keywordsstring | string[]

Secondary keywords, either as a comma-separated string or an array. Up to 15 keywords, each max 80 characters. Always returned as an array. Woven into the article naturally where they fit.

body
country_targetingstring

US, GB, CA, AU, DE, FR, ES, IT, BR, or MX. Adds regional context and localises examples.

body
audiencestring

Who the article is for, max 1,000 characters. Omit the field to inherit the project's default audience; send null to write without one.

Generation control

body
ai_model_usedstring

Model identifier, e.g. gpt-5.4, gpt-4.1-mini, claude-sonnet-4-6. Must be an active model. Defaults to the cheapest active model.

body
brand_voice_idinteger

A brand voice belonging to the same project. Applies its stored style rules to the writing.

body
additional_contextstring

Background material — product facts, notes, source text — max 25,000 characters. Reaches the steps with include_additional_context. The most effective single lever on output quality.

body
additional_instructionstring

Directives about structure or style, max 2,000 characters. Reaches the steps with include_additional_instruction.

body
humanizeboolean

Run a humanization pass after generation and store it as a new version. Delays the completion webhook until the pass finishes.

body
include_key_takeawaysboolean

Open the article with a bulleted "Key takeaways" summary, placed just after the introduction. Defaults to false.

body
include_faqboolean

Close the article with a "Frequently Asked Questions" section of 4-6 questions, placed after the conclusion. When a fresh SERP analysis exists for the target keyword, real searcher questions are preferred. Improves AI search coverage. Defaults to false.

body
heading_casestring

title or sentence. Omit to leave heading capitalization to the model.

body
use_batch_apiboolean

Submit through the provider's batch queue: about half the cost, up to 24 hours to return. Only valid for single-step workflows on a batch-enabled model — anything else is rejected. The article starts in batching rather than queued.

body
statusstring

Overrides the initial status. Rarely useful — leave it unset and let the pipeline manage it.

Research

body
research_enabledboolean

Search the web and feed extracted sources into the steps with include_research. Only valid for article types whose workflow contains such a step.

body
research_whitelisted_domainsarray

Up to 50 domains. When set, research uses only these, and the blocklist is ignored.

body
research_blocked_domainsarray

Up to 50 domains to exclude. Defaults to youtube.com, twitter.com, facebook.com, genius.com.

body
research_max_sourcesinteger

1–20. How many URLs to extract content from. Default 5.

body
research_min_content_wordsinteger

50–5,000. Pages shorter than this are discarded as thin. Default 100.

body
research_max_content_wordsinteger

100–10,000, and must be greater than or equal to research_min_content_words. Longer sources are truncated. Default 1000.

Images

body
image_countinteger

0–5 images to generate for the article.

body
image_aspect_ratiostring

1:1, 16:9, 9:16, 3:4, or 4:3.

body
image_preset_idinteger

An image preset to apply a consistent visual style.

Delivery

body
webhook_urlstring

Valid URL, max 500 characters. Receives a POST with the finished article when the status reaches completed. Three attempts, backing off 10s → 20s → 30s. See Article lifecycle.

Example

Response fields

successboolean
Required

Always true on 201.

messagestring
Required

Confirmation that generation has started.

dataobject
Required

The created article. See Get article for the full field reference. At creation, content, ai_model_used, and current_step are all null — they fill in as the pipeline runs.

Errors

StatusWhen
401Missing, invalid, or expired token
402Account has no active subscription
403No access to the requested project
422Validation failed, or the monthly word quota cannot cover the article
429Rate limit exceeded

See Errors for the full reference.

Tips

additional_context moves output quality more than any other field. Real product facts, source notes, or a competitor's article pasted in beats any amount of prompt tuning.

Set target_word_count about 10–20% above the length you actually want. The revision steps trim, and a target set exactly at the goal tends to land under it.