API Documentation

Our API allows you to easily get the same sort of responses that you'd get from KoalaWriter and KoalaChat directly in your code or terminal!

You can use our API to integrate with a custom CMS, perform bulk article generation, create your own user interface for KoalaWriter or KoalaChat, and more!

All paid plans can use our API and there are no additional costs. The usage will be the same as using KoalaChat or KoalaWriter from our website. Each request to KoalaChat uses 1 chat credit and the KoalaWriter API is billed based on words generated the same as if you were using it on our website.


You will need an API key which requires having an active, paid subscription with Koala which start at just $9/month.

If you don't already have an account then first Register. Then, you can sign up for a paid plan.

Once you have an active plan visit your Account page. Click the Add API Key button to create an API key. Then, copy the value of the created key, it will look like this: a0ce8c2f-60ad-4edc-89eb-bd6da042e572.

To authenticate with our API you must include a Authorization: Bearer YOUR_API_KEY header in every request. This is known as Bearer authentication and you can see examples below.

KoalaWriter API

The KoalaWriter API is asynchronous meaning the article is created in the background. First, you will make an API call to queue an article for writing. Then you can call the API to get the status of the article. Once the status is finished then you can 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. Additionally, you can specify an integrationId that corresponds to a WordPress site you have linked in your account so that when the article is completed it will automatically be created as a draft in WordPress!

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

Creating an Article

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

Below is a simple example in JavaScript, but you can use any language. This code will queue an article and since an integrationId is specified the article will automatically be created in WordPress.

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-4",
    integrationId: "329cf56d-5409-43f3-b7fc-9cb64d725f6c",

The /api/articles/ route returns a JSON object with an articleId. If your request is not valid JSON or doesn't contain the targetKeyword then it will return a 400 error. Example response:

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

Below is a full list of available parameters. Every parameter is optional except for targetKeyword.

NameType / Possible ValuesDescription
targetKeywordstringThe main keyword for the article.
integrationIdstringProvide an integration ID for a connected WordPress site and we will automatically create a draft in WP.
webhookUrlstringYou 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 below.
gptVersion"gpt-3.5" (default) or "gpt-4"The GPT model to be used. GPT-4 uses 5 times more credits.
articleType"blog_post" (default) or "amazon_product_roundup"The type of article to be generated.
pointOfView"third_person" (default), "first_person_singular", "first_person_plural", or "second_person"The point of view to be used for the article.
language"English" (default) or any available language supported by KoalaWriterThe language to be used.
extraTitlePromptstringAn additional prompt to be used for generating the article title.
extraSectionPromptstringAn additional prompt to be used for each section.
toneOfVoiceProfile"seo_optimized" (default) or any string (e.g. "Friendly")The tone of voice to be used for the article.
titlestringYou can provide a title if you don't want us to generate one for you.
includeFaqboolean, defaults to falseIf enabled, we will add a FAQ section based on real-time data.
The below parameters only apply to the "blog_post" article type. This is the default article type.
realTimeDataboolean, defaults to falseWhether to use real-time data for the article.
shouldCiteSourcesboolean, defaults to trueWhether to include links to sources used in the article.
seoOptimizationLevel "default" (default), "manual", "ai_powered"The SEO optimization mode to apply to the article.
extraEntitiesPromptstringA comma-separated list of keywords/entities to cover in the article. Only used if seoOptimizationLevel is manual.
includeKeyTakeawaysboolean, defaults to falseIf enabled, a new version of the introduction will be used that includes a Key Takeaways section.
outlinearray of SectionsPlease 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.
extraOutlinePromptstringEach 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.
The below parameters only apply to the "amazon_product_roundup" article type.
amazonDomain"amazon.com" (default) or any Amazon domain supported by KoalaWriterThe domain of the Amazon store to search for products in.
numAmazonProductsinteger from 1 to 48, defaults to 10The number of Amazon products to include in the article.
enableFirstHandExperienceboolean, defaults to trueWhether to include the first-hand experience with the Amazon products.
amazonAssociatesId stringThe Amazon Associates ID to use for affiliate linking.
amazonProductSearchUrl stringThe URL of the Amazon product search to use.

Checking Article Status

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

This route is used to check the status of an article and to get the HTML (if it is finished).

Example response when the article is completed (the full HTML response will be included):

  "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..."

Example response when the article is still being written:

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

Status can be one of:

  • queued: The article is queued
  • processing: The article is being written
  • finished: The article is finished 🎉
  • failed: An error occurred and we could not finish writing the article. We automatically do a lot of retries so this is rare.

More Information

You can queue an unlimited number of articles at a time, but only a single article per account will be processed at a time. If you are on one of our Scale plans and you have a use case that requires you to write more than one article at a time, then contact us and we can increase your limit.

If there is an error when creating the article then our system will retry many times. It will be rare if the article is not able to be completed because we will be able to handle even extended downtime.

The time it takes to create an article will depend on many factors. A basic GPT-3.5 article only takes a couple of minutes. Using GPT-4, AI-Powered SEO Optimization, Real-Time Data, Amazon Product Roundups, and other factors all can increase the amount of time required.

If your account runs out of credits then the queue will be paused until your usage allowance changes such as when your credits reset or a subscription is purchased. Articles that are already in-progress will be allowed an overage of up to 5,000 words to prevent stopping an article in the middle.

More Examples

Below is some more code that shows how you can queue an article and then wait until it is completed. It checks the article status in a loop with a ten second delay each time. When the status is finished then it returns the article's HTML. If it returns null then it means there was an error.

Please note that you can also specify a webhookUrl to be notified when the article is completed rather than polling the API.

const sleep = async (ms) => new Promise((r) => setTimeout(r, ms));

const writeArticle = async (config) => {
  const { articleId } = await (
    await fetch("https://koala.sh/api/articles/", {
      method: "POST",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      body: JSON.stringify(config),

  while (true) {
    await sleep(10_000);

    const article = (
      await fetch(`https://koala.sh/api/articles/${articleId}`, {
        method: "GET",
        headers: {
          Authorization: "Bearer YOUR_API_KEY",
          "Content-Type": "application/json",

    if (article.status === "finished") {
      return article.output.html;

    if (article.status === "failed") {
      return null;

const articleHtml = await writeArticle({
  targetKeyword: "can you eat watermelon seeds?",
  gptVersion: "gpt-4",

Note: The KoalaWriter API is not supported in Google Sheets. You could build your own integration with Apps Script but it is not supported by us and you cannot call the API from a Google Sheets formula. Doing so would be error-prone and risks wasting a lot of your credits. If you are just wanting to do bulk writing then please check out the Bulk Mode in KoalaWriter.

KoalaChat API

Below is an example in JavaScript, but you can use any language or CLI tools like curl.

fetch('https://koala.sh/api/gpt/', {
    method: 'POST',
    headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
    body: JSON.stringify({
        input: 'My name is Bob. What about yours?',
        inputHistory: ['Hello'],
        outputHistory: ['Hi! What is your name?'],
        realTimeData: false,

You will get a JSON response like this:

{"output": "As an AI language model, I don't have a personal name, but you can call me KoalaChat. How can I assist you today, Bob?"}

The only required parameter is the input which is your prompt. You can optionally provide inputHistory and outputHistory as an array of strings to maintain conversation history or for prompt engineering. If provided, they must be of the same length.

You can also specify true for realTimeData to have live data injected into your prompt. If you don't need real-time data, then don't include it.