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:
- Make an API call to queue an article for writing
- Call the API to check the status of the article
- 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
POST https://koala.sh/api/articles/
Example Request
fetch("https://koala.sh/api/articles/", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
targetKeyword: "can you eat watermelon seeds?",
gptVersion: "gpt-4o",
integrationId: "329cf56d-5409-43f3-b7fc-9cb64d725f6c",
}),
});
Example Response
{"articleId": "7b53671d-da26-4ab1-b096-6e014125f712"}
Parameters
Below is a full list of available parameters. Only the targetKeyword is required.
Name | Type / Possible Values | Description |
---|---|---|
targetKeyword | string | The main keyword for the article. |
integrationId | string | Provide an integration ID for a connected site and we will automatically create a draft. |
webhookUrl | string | You can provide a URL and we will POST to it when the article is completed. The payload will contain the same response as the /api/articles/{article_id} route. |
gptVersion | "gpt-4o-mini" (default), "gpt-4o", or "claude-3.7-sonnet" | The model to be used. |
articleType | "blog_post" (default), "amazon_product_roundup", "youtube_video", "rewrite_blog_post", "amazon_single_product_review", "listicle", "local_places_roundup" | The type of article to be generated. |
autoPolish | boolean, defaults to false | If enabled, we will automatically run Polish on the article using the settings below. |
polishSettings | object, defaults to {"split-up-long-paragraphs":true,"remove-mid-article-conclusions":true,"remove-repetitive-sentences":true,"convert-passive-voice":false,"simplify-complex-sentences":false} | The Polish settings to be used. autoPolish must be set to true for this to take effect. |
language | "English" (default) or any available language supported by KoalaWriter | The language to be used. |
pointOfView | "third_person" (default), "first_person_singular", "first_person_plural", "second_person" | The point of view to be used in the article. |
extraTitlePrompt | string | An additional prompt to be used for generating the article title. |
extraSectionPrompt | string | An additional prompt to be used for each section. |
extraIntroductionPrompt | string | An additional prompt to be used for the introduction. |
toneOfVoiceProfile | "seo_optimized" (default) or any string (e.g. "Friendly") | The tone of voice to be used for the article. |
title | string | You can provide a title if you don't want us to generate one for you. |
includeFaq | boolean, defaults to false | If enabled, we will add a FAQ section based on real-time data. |
readabilityMode | "default" or "8th_grade" | If set to "8th_grade", the output will contain shorter sentences and simpler language to target an 8th grade reading level. |
The below parameters only apply to the "blog_post" article type. This is the default article type. | ||
realTimeData | boolean, defaults to false | Whether to use real-time data for the article. |
shouldCiteSources | boolean, defaults to true | Whether to include links to sources used in the article. |
seoOptimizationLevel | "default" (default), "manual", "ai_powered" | The SEO optimization mode to apply to the article. |
extraEntitiesPrompt | string | A comma-separated list of keywords/entities to cover in the article. Only used if seoOptimizationLevel is manual. |
includeKeyTakeaways | boolean, defaults to false | If enabled, a new version of the introduction will be used that includes a Key Takeaways section. |
outline | array of Sections | Please read the documentation and contact us if you require more information. By default, we will generate an outline for you based on the target keyword. |
extraOutlinePrompt | string | Each section (H2) should be on a new line and you can specify sub-sections (H3s) by indenting them. Only one level of indentation is supported. You should only include the names of the sections. Use the outline parameter instead if you want full control over the outline. |
country | string | The country to be targeted in the article. |
urls | array of strings | Array of URLs to be used as references in the article. |
disableIntroduction | boolean | Whether to disable the introduction of the article. |
disableConclusion | boolean | Whether to disable the conclusion of the article. |
multimediaOption | "none" (default), "auto", "images", "videos" | The type of multimedia to include in the article. |
imageStyle | "illustration" (default), "photo", "watercolor", "fantasy", "anime", "isometric" | Style of the images to be included. |
imageModel | "standard" (default), "premium" | Model to be used for generating AI images. |
maxImages | integer | Maximum number of images to include. |
imageSize | string | Size of the images to be included (must be a supported size here). |
maxVideos | integer | Maximum number of videos to include. |
articleLength | "default" (default), "custom", "short", "shorter", "medium", "long", "longer" | Please refer to KoalaWriter to see the range of sections and estimated word count for each option. Set to "custom" if you want to manually specify the number of sections in the numberOfSections field. |
numberOfSections | integer | The number of sections to include. You must set articleLength to "custom" if you want this to take effect. |
The below parameters only apply to the "listicle" and "local_places_roundup" article types. | ||
enableSupplementalInformation | boolean, defaults to true | By default, 1-3 relevant sections will be added at the end of article. This is recommended for a comprehensive and optimized article. Set to false to disable. |
enableAutomaticLength | boolean, defaults to true | By default, if a number of items is specified in the Target Keyword then that will be used, otherwise it will default to 10. For example, "5 cutest dog breeds" would use 5 items. Override this by setting this to false and specifying the number of items in the numberOfItems parameter. |
numberOfItems | integer, default 10 | You must set enableAutomaticLength to false if you want this to take effect. This is the number of items to include in the listicle. |
The below parameters only apply to the "amazon_product_roundup" article type. | ||
amazonDomain | "amazon.com" (default) or any Amazon domain supported by KoalaWriter | The domain of the Amazon store to search for products in. |
numAmazonProducts | integer from 1 to 48, defaults to 10 | The number of Amazon products to include in the article. |
enableFirstHandExperience | boolean, defaults to true | Whether to include the first-hand experience with the Amazon products. |
amazonAssociatesId | string | The Amazon Associates ID to use for affiliate linking. |
amazonProductSearchUrl | string | The URL of the Amazon product search to use. |
Parameters for "youtube_video" article type: | ||
youTubeVideoUrl | string | URL of the YouTube video to be processed. |
rewriteAllSourceData | boolean | Whether to rewrite all source data of the video. |
Parameters for "rewrite_blog_post" article type: | ||
articleUrl | string | URL of the article to be rewritten. |
rewriteAllSourceData | boolean | Whether to rewrite all source data of the article. |
Parameters for "amazon_single_product_review" article type: | ||
asin | string | Amazon Standard Identification Number for the product. |
enableCondensedMode | boolean | Whether to enable condensed mode for the product review. |
Checking Article Status
GET https://koala.sh/api/articles/{article_id}
This endpoint is used to check the status of an article and to get the HTML (if it is finished).
Example Response (Completed Article)
{
"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><h2>Introduction</h2><p>Great Danes are one of the largest dog breeds in the world, known for their majestic appearance and gentle nature...",
"polishedHtml": null
}
}
polishedHtml
will be null unless autoPolish
was set to true
or the article was manually polished in KoalaWriter.
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
: The article is queuedprocessing
: The article is being writtenfinished
: The article is finished 🎉failed
: An error occurred and we could not finish writing the article
Complete Example
async function createAndWaitForArticle(keyword) {
try {
// Step 1: Create the article
const createResponse = await fetch("https://koala.sh/api/articles/", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
targetKeyword: keyword,
gptVersion: "gpt-4o",
}),
});
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 articleFinished = false;
let article = null;
while (!articleFinished) {
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 article status: ${statusResponse.status}`);
}
article = await statusResponse.json();
if (article.status === "finished") {
articleFinished = true;
console.log("Article is complete!");
} else if (article.status === "failed") {
throw new Error(`Article failed: ${article.error}`);
} else {
console.log(`Article status: ${article.status} - ${article.statusDetail || "In progress"} (${Math.round(article.progress * 100)}%)`);
// Wait 5 seconds before checking again
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
// Step 3: Use the completed article
console.log("Article HTML:", article.output.html);
return article;
} catch (error) {
console.error("Error:", error);
return null;
}
}
// Example usage
createAndWaitForArticle("best hiking trails in colorado");
Error Handling
The API will return appropriate HTTP status codes for different error conditions:
- 400 Bad Request: Invalid parameters or request format
- 401 Unauthorized: Invalid or missing API key
- 500 Internal Server Error: Server-side error
Need Help?
If you need additional assistance with the KoalaWriter API, please contact us.