KoalaWriter API

The KoalaWriter API is the best API for creating SEO-optimized articles. It is billed based on the number of words generated, the same as if you were using KoalaWriter manually. All paid plans can use this API with no additional costs.

How It Works

The KoalaWriter API is asynchronous, meaning the article is created in the background. The process works as follows:

  1. Make an API call to queue an article for writing
  2. Call the API to check the status of the article
  3. Once the status is finished, access the full HTML of the completed article

When an article is completed, it is automatically saved to your account so you can also access it there.

You can specify an integrationId so that when the article is completed it will automatically be created as a draft in WordPress, Shopify, Webflow, etc! Webhooks are also supported by specifying the webhookUrl parameter.

If you are just wanting to do bulk writing, please check out the Bulk Mode in KoalaWriter.

Endpoints

Creating an Article (v2)

POST https://koala.sh/api/articles/v2/

The v2 endpoint uses a new generation engine for higher quality articles. For the legacy v1 engine, use /api/articles/ instead — see the Legacy v1 section below.

Example Request (v2)

fetch("https://koala.sh/api/articles/v2/", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    targetKeyword: "can you eat watermelon seeds?",
    gptVersion: "gpt-5.2",
    realTimeData: true,
    shouldCiteSources: true,
    multimediaOption: "images",
    imageStyle: "photo",
    brandId: "your-brand-uuid",
    brandMentionLevel: "subtle",
    articleInstructions: "Focus on health benefits. Write from a nutritionist's perspective.",
  }),
});

Example Response

{"articleId": "7b53671d-da26-4ab1-b096-6e014125f712"}

Parameters

Below is a full list of parameters for the v2 endpoint. Only the targetKeyword is required.

NameType / Possible ValuesDescription
targetKeywordstring (required)The main keyword for the article.
articleType"blog_post" (default), "listicle", "service_page", "amazon_product_roundup", "youtube_video", "rewrite_blog_post", "amazon_single_product_review", "local_places_roundup"The type of article to generate.
gptVersion"gpt-5-mini" (default), "gpt-5.2", "claude-4.5-sonnet"The model to use.
language"English" (default) or any language supported by KoalaWriterThe language of the article.
pointOfView"third_person" (default), "first_person_singular", "first_person_plural", "second_person"The point of view for the article.
toneOfVoiceProfile"seo_optimized" (default), "automatic", or any string (e.g. "Friendly")The writing style for the article. Use "automatic" to have the AI generate a tailored writing style during outline generation, or "custom" with a toneOfVoice parameter for your own style.
titlestringProvide a title if you don't want one generated automatically.
readabilityMode"default" or "8th_grade"Set to "8th_grade" for shorter sentences and simpler language.
integrationIdstringIntegration ID for a connected site to auto-create a draft.
webhookUrlstringURL to POST to when the article is completed. Payload matches the /api/articles/{article_id} response.
v2-only parameters
articleInstructionsstringFree-form instructions to guide article generation (e.g. "Focus on budget-friendly options, write from a beginner's perspective").
brandIdstringUUID of a brand created in Brand DNA. The article will be written with your brand's voice, knowledge, and context. Supported for blog_post, listicle, and service_page.
brandMentionLevel"subtle" (default), "prominent", "none"How prominently the brand is mentioned. "prominent" adds a dedicated section; "subtle" mentions where relevant; "none" uses brand knowledge for accuracy without naming it.
Research & real-time data (blog_post, service_page)
realTimeDataboolean, defaults to falseWhether to use real-time data for the article.
enableDeepResearchboolean, defaults to falseEnable Deep Research. Only used when realTimeData is true.
shouldCiteSourcesboolean, defaults to trueWhether to include links to sources used.
realTimeDataSource"web", "scholarly", "news", "custom"Source of real-time data. Only used when realTimeData is true.
realTimeDateRange"" (all time, default), "past_hour", "past_day", "past_week", "past_month", "past_year"Time range for news data. Only used when realTimeDataSource is "news".
countrystringThe country to target in the article.
urlsarray of stringsURLs to use as references.
Content structure (blog_post)
includeFaqboolean, defaults to falseAdd a FAQ section based on real-time data.
includeKeyTakeawaysboolean, defaults to falseInclude a Key Takeaways section in the introduction.
disableIntroductionbooleanDisable the introduction.
disableConclusionbooleanDisable the conclusion.
articleLength"default", "custom", "short", "shorter", "medium", "long", "longer"Article length. Set to "custom" to use numberOfSections.
numberOfSectionsintegerNumber of sections. Requires articleLength set to "custom".
outlinearray of SectionsCustom outline. See documentation. By default, an outline is generated from the keyword.
extraOutlinePromptstringSection names (one per line, indent for H3s) to guide outline generation. Use outline for full control.
seoOptimizationLevel"default", "manual", "ai_powered"SEO optimization mode.
extraEntitiesPromptstringComma-separated keywords/entities to cover. Only used when seoOptimizationLevel is "manual".
internalLinkingDomainIdstringDomain ID for internal linking. Find it in the URL when viewing a domain in KoalaLinks.
Custom prompts
extraTitlePromptstringAdditional prompt for the article title.
extraSectionPromptstringAdditional prompt applied to each section.
extraIntroductionPromptstringAdditional prompt for the introduction.
Multimedia (blog_post, listicle)
multimediaOption"none" (default), "auto", "images", "videos"Type of multimedia to include.
imageStyle"illustration" (default), "photo", "watercolor", "fantasy", "anime", "isometric"Style of AI-generated images.
imageModel"gpt-image-2-fast" (default), "gpt-image-2-medium", "ideogram-3.0-turbo", "nano-banana-2"Model for generating AI images.
maxImagesintegerMaximum number of images.
imageSizestringImage size (must be a supported size listed here).
maxVideosintegerMaximum number of videos.
Auto-Polish
autoPolishboolean, defaults to falseAutomatically run Polish on the completed article.
polishSettingsobject, defaults to {"split-up-long-paragraphs":true,"remove-mid-article-conclusions":true,"remove-repetitive-sentences":true,"convert-passive-voice":false,"simplify-complex-sentences":false,"humanize":false}Polish settings. Requires autoPolish: true.
polishCustomInstructionsstring (max 1,024 chars)Custom instructions for Polish. Requires autoPolish: true.
Call-to-action (blog_post, listicle, service_page)
includeCtabooleanWhether to include a call-to-action section at the end of the article.
ctaPromptstringCustom prompt for the CTA section. Requires includeCta: true.
listicle and local_places_roundup parameters
enableSupplementalInformationboolean, defaults to trueAdd 1-3 relevant sections at the end of the article. Recommended for comprehensive, optimized articles.
enableAutomaticLengthboolean, defaults to trueAutomatically detect the number of items from the keyword (e.g. "5 cutest dog breeds" uses 5). Set to false to use numberOfItems.
numberOfItemsinteger, default 10Number of items. Requires enableAutomaticLength: false.
extraListItemPromptstringAdditional prompt applied to each list item.
amazon_product_roundup parameters
amazonDomain"amazon.com" (default) or any Amazon domain supported by KoalaWriterAmazon store domain to search.
numAmazonProductsinteger 1-48, defaults to 10Number of Amazon products to include.
enableFirstHandExperienceboolean, defaults to trueInclude first-hand experience with the products.
amazonAssociatesIdstringAmazon Associates ID for affiliate linking.
amazonProductSearchUrlstringAmazon product search URL to use.
youtube_video parameters
youTubeVideoUrlstringURL of the YouTube video.
rewriteAllSourceDatabooleanWhether to rewrite all source data from the video.
rewrite_blog_post parameters
articleUrlstringURL of the article to rewrite.
rewriteAllSourceDatabooleanWhether to rewrite all source data from the article.
amazon_single_product_review parameters
asinstringAmazon Standard Identification Number for the product.
enableCondensedModebooleanEnable condensed mode for the product review.

Checking Article Status

GET https://koala.sh/api/articles/{article_id}

Check the status of an article and retrieve the HTML when finished.

Example Response (Completed)

{
  "config": {
    "targetKeyword": "are great danes good pets?"
  },
  "status": "finished",
  "statusDetail": "Finished article",
  "updatedAt": 1683095362612,
  "progress": 1,
  "error": null,
  "output": {
    "html": "<h1>Are Great Danes Good Pets? Pros and Cons You Need to Know</h1>...",
    "polishedHtml": null
  }
}

polishedHtml will be null unless autoPolish was set to true or the article was manually polished.

Example Response (In Progress)

{
  "config": {
    "targetKeyword": "are great danes good pets?"
  },
  "status": "processing",
  "statusDetail": "Writing section 3",
  "updatedAt": 1683095271489,
  "progress": 0.33,
  "error": null
}

Status Values

  • queued: Article is queued
  • processing: Article is being written
  • finished: Article is finished
  • failed: An error occurred

Complete Example

async function createAndWaitForArticle(keyword) {
  try {
    // Step 1: Create the article
    const createResponse = await fetch("https://koala.sh/api/articles/v2/", {
      method: "POST",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        targetKeyword: keyword,
        gptVersion: "gpt-5.2",
        realTimeData: true,
        shouldCiteSources: true,
      }),
    });

    if (!createResponse.ok) {
      throw new Error(`Failed to create article: ${createResponse.status}`);
    }

    const { articleId } = await createResponse.json();
    console.log(`Article created with ID: ${articleId}`);

    // Step 2: Poll for article status
    let article = null;

    while (true) {
      const statusResponse = await fetch(
        `https://koala.sh/api/articles/${articleId}`,
        {
          headers: { Authorization: "Bearer YOUR_API_KEY" },
        }
      );

      if (!statusResponse.ok) {
        throw new Error(`Failed to check status: ${statusResponse.status}`);
      }

      article = await statusResponse.json();

      if (article.status === "finished") {
        console.log("Article is complete!");
        break;
      } else if (article.status === "failed") {
        throw new Error(`Article failed: ${article.error}`);
      }

      console.log(`${article.status} - ${article.statusDetail || "In progress"} (${Math.round(article.progress * 100)}%)`);
      await new Promise(resolve => setTimeout(resolve, 5000));
    }

    console.log("Article HTML:", article.output.html);
    return article;
  } catch (error) {
    console.error("Error:", error);
    return null;
  }
}

createAndWaitForArticle("best hiking trails in colorado");

Error Handling

  • 400 Bad Request: Invalid parameters or request format
  • 401 Unauthorized: Invalid or missing API key
  • 500 Internal Server Error: Server-side error

Migrating from v1

If you have an existing v1 integration, upgrading to v2 is straightforward. Most parameters are unchanged.

Legacy v1 API

Deprecated

The v1 engine generates articles section-by-section. It is still supported but we recommend using v2 for all new integrations. To use v1, send requests to /api/articles/ instead of /api/articles/v2/.

Need Help?

If you need additional assistance with the KoalaWriter API, please contact us.