> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wibbleai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Submit text to the Wibble humanizer and read the result in three steps.

This guide takes you from an API key to a humanized result. You submit text, wait for the job to finish, then read the output.

## Prerequisites

Before you begin, you need:

* A Wibble account.
* API words in your balance. Each request reserves words equal to its input word count. Buy word packs and learn how billing works in [Words and billing](/concepts/words-and-billing).
* An API key with the `humanize` scope. Keys look like `wib_live_...`. Create one at [https://www.wibbleai.com/dashboard/api](https://www.wibbleai.com/dashboard/api).

<Info>
  Keep your API key on the server. Anyone with the key can spend your account's API words.
</Info>

## Get started

<Steps>
  <Step title="Submit a job">
    Send your text to `POST /humanize`. Wibble reserves the required API words and responds with HTTP `202` and a job in status `queued`.

    <CodeGroup>
      ```bash curl theme={null}
      curl https://www.wibbleai.com/api/v1/humanize \
        -H "Authorization: Bearer wib_live_..." \
        -H "Content-Type: application/json" \
        -d '{"text": "The mitochondria is the powerhouse of the cell."}'
      ```

      ```python Python theme={null}
      import requests

      response = requests.post(
          "https://www.wibbleai.com/api/v1/humanize",
          headers={"Authorization": "Bearer wib_live_..."},
          json={"text": "The mitochondria is the powerhouse of the cell."},
      )
      job = response.json()
      print(job["id"], job["status"])
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch("https://www.wibbleai.com/api/v1/humanize", {
        method: "POST",
        headers: {
          Authorization: "Bearer wib_live_...",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          text: "The mitochondria is the powerhouse of the cell.",
        }),
      });
      const job = await response.json();
      console.log(job.id, job.status);
      ```
    </CodeGroup>

    The response includes the job `id` and a `status_url` to poll:

    ```json Response theme={null}
    {
      "id": "7b42f1d6-0a8c-4e8f-9a21-c6d9f47c2b10",
      "status": "queued",
      "mode": "humanize",
      "input_words": 9,
      "words_reserved": 9,
      "words_charged": 9,
      "status_url": "https://www.wibbleai.com/api/v1/humanize/7b42f1d6-0a8c-4e8f-9a21-c6d9f47c2b10",
      "current_stage": "detecting_language",
      "detected_language": null,
      "created_at": "2026-06-14T12:00:00.000Z",
      "completed_at": null
    }
    ```
  </Step>

  <Step title="Wait for the result">
    Poll `GET /humanize/{id}` until `status` is `succeeded` or `failed`. A single lookup looks like this:

    ```bash curl theme={null}
    curl https://www.wibbleai.com/api/v1/humanize/7b42f1d6-0a8c-4e8f-9a21-c6d9f47c2b10 \
      -H "Authorization: Bearer wib_live_..."
    ```

    In practice, loop until the job reaches a terminal status. Poll about every 2.5 seconds, and stop on `succeeded` or `failed`. Lookups are limited to 120 requests per minute per key, so keep the interval at or above the recommended value.

    <CodeGroup>
      ```python Python theme={null}
      import time
      import requests

      headers = {"Authorization": "Bearer wib_live_..."}
      status_url = "https://www.wibbleai.com/api/v1/humanize/7b42f1d6-0a8c-4e8f-9a21-c6d9f47c2b10"

      while True:
          response = requests.get(status_url, headers=headers)
          job = response.json()

          if job["status"] == "succeeded":
              print(job["output"])
              break
          if job["status"] == "failed":
              print("Job failed:", job["error"]["code"], job["error"]["message"])
              break

          time.sleep(2.5)
      ```

      ```javascript JavaScript theme={null}
      const headers = { Authorization: "Bearer wib_live_..." };
      const statusUrl = "https://www.wibbleai.com/api/v1/humanize/7b42f1d6-0a8c-4e8f-9a21-c6d9f47c2b10";
      const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

      while (true) {
        const response = await fetch(statusUrl, { headers });
        const job = await response.json();

        if (job.status === "succeeded") {
          console.log(job.output);
          break;
        }
        if (job.status === "failed") {
          console.log("Job failed:", job.error.code, job.error.message);
          break;
        }

        await sleep(2500);
      }
      ```
    </CodeGroup>

    <Note>
      A job that never finishes is marked `failed` after about an hour with the error code `job_expired`, and its reserved words are refunded. Treat a `failed` status as terminal and stop polling.
    </Note>
  </Step>

  <Step title="Read the output">
    A succeeded job returns the humanized text in `output`:

    ```json Response theme={null}
    {
      "id": "7b42f1d6-0a8c-4e8f-9a21-c6d9f47c2b10",
      "status": "succeeded",
      "mode": "humanize",
      "input_words": 9,
      "words_reserved": 9,
      "words_charged": 9,
      "status_url": "https://www.wibbleai.com/api/v1/humanize/7b42f1d6-0a8c-4e8f-9a21-c6d9f47c2b10",
      "current_stage": "completed",
      "detected_language": "en",
      "created_at": "2026-06-14T12:00:00.000Z",
      "completed_at": "2026-06-14T12:00:42.000Z",
      "output": "Mitochondria are the cell's powerhouses."
    }
    ```

    If a job `failed`, read the `error` object for the reason. The reserved words are refunded automatically.
  </Step>
</Steps>

## Skip polling with a webhook

Instead of polling, pass a `webhook_url` when you submit. Wibble sends a signed `POST` to that URL when the job finishes.

```bash curl theme={null}
curl https://www.wibbleai.com/api/v1/humanize \
  -H "Authorization: Bearer wib_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The mitochondria is the powerhouse of the cell.",
    "webhook_url": "https://example.com/webhooks/wibble"
  }'
```

Verify the signature before trusting a delivery. See [Webhooks](/concepts/webhooks) for the payload, delivery behavior, and verification steps. Keep polling available as a fallback.

<Tip>
  Retrying a submission? Send an `Idempotency-Key` header so a repeated request returns the original job instead of creating a duplicate. See [Idempotency](/concepts/idempotency) for how safe retries work.
</Tip>

<Check>
  You submitted text, waited for the job to reach `succeeded`, and read the humanized `output`. You now have the full request-and-poll loop working.
</Check>

## Next steps

<Columns cols={2}>
  <Card title="Humanization" icon="wand-magic-sparkles" href="/concepts/humanization">
    What the humanizer does, the request options, supported languages, and responsible use.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/introduction">
    The full job lifecycle, limits, error codes, and webhooks.
  </Card>
</Columns>
