Getting started

HumanizeWord
API quickstart

Send a draft, choose a model tier, and retrieve the rewrite when processing finishes. The web app and API use the same prepaid balance.

REST APIOne shared balance
On this page

Base URL

Use this base URL for all endpoints below.

API base URLHTTP
https://humanizeword.com/api/v1

Send and receive JSON. Timestamps are ISO 8601 UTC. Money is a decimal string, never a float, and field names end in _usd.

Your first run

  1. Create an API key at humanizeword.com/app/api-keys and copy it. It is shown once.
  2. Post the draft. Read restrictions.max_chars_per_run on GET /v1/me for your current character limit.
  3. Poll the run until it finishes. If status is succeeded, use output_text. For other final statuses, check the error details.
Create a runcURL
curl https://humanizeword.com/api/v1/runs \
  -H "Authorization: Bearer $HUMANIZEWORD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Artificial intelligence has fundamentally transformed the landscape of modern software development.",
    "quality": "standard"
  }'

202 Accepted means the run was queued and a hold was placed on your balance. events_url is a path on the same host.

Queued responseJSON
{
  "id": "run_01J9ABCDEF",
  "status": "queued",
  "quality": "standard",
  "word_count": 11,
  "prose_word_count": 11,
  "estimated_cost_usd": "0.050000",
  "held_usd": "0.050000",
  "is_estimate": true,
  "events_url": "/api/v1/runs/run_01J9ABCDEF/events"
}
Read a runcURL
curl https://humanizeword.com/api/v1/runs/run_01J9ABCDEF \
  -H "Authorization: Bearer $HUMANIZEWORD_API_KEY"

When status is succeeded, output_text is the rewrite and billing.charged_usd is what left the balance. A run that fails its checks comes back rejected and is still charged, because the work was done.

The same call in Python

Rewrite and pollPython
import os
import time
import requests

base = "https://humanizeword.com/api/v1"
headers = {"Authorization": f"Bearer {os.environ['HUMANIZEWORD_API_KEY']}"}

created = requests.post(
    f"{base}/runs",
    headers=headers,
    json={
        "text": "Artificial intelligence has fundamentally transformed the landscape of modern software development.",
        "quality": "standard",
    },
    timeout=30,
)
created.raise_for_status()
run_id = created.json()["id"]

terminal = {"succeeded", "rejected", "failed", "canceled"}
while True:
    run = requests.get(f"{base}/runs/{run_id}", headers=headers, timeout=30)
    run.raise_for_status()
    body = run.json()
    if body["status"] in terminal:
        break
    time.sleep(2)

print(body.get("output_text"))
print(body["billing"]["charged_usd"])
Check your current character limit.

The limit counts the full text, including spaces. Read restrictions.max_chars_per_run on GET /v1/me; the backend default is 35,000 characters. Estimates use the prose word count, excluding Markdown structure and code blocks. The final charge is based on model work.

What you can send

FieldRequiredDescription
textYesPlain text or Markdown. At least one prose word, within restrictions.max_chars_per_run returned by GET /v1/me.
qualityNolow, standard, or high. Defaults to standard.
optionsNoVoice and writing options. Unset options are chosen for each run. See Runs.

Unknown fields are rejected. A request that still sends model or mode returns 422.