docs.humanizeword.com

Rewrite text
from your own code.

Send a draft, pick a quality, and read the rewrite when the run finishes. The same prepaid balance pays for the app and for API keys.

Base URL

Every path below is rooted at the public API.

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. A run longer than 5,000 characters is rejected.
  3. Read the run until status is no longer queued or running, then use output_text.
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.

{
  "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"
}
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

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"])
5,000 characters per run.

The limit is the length of the text you paste, including spaces. Billing still counts prose words. Markdown structure and code blocks stay intact and are not billed.

What you can send

FieldRequired
textYesPlain text or Markdown. At least one prose word, at most 5,000 characters.
qualityNolow, standard, or high. Defaults to standard.
optionsNoVoice and noise. Anything you leave out is chosen for that run. See Runs.

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