api reference · v1

Build with the humanizer directly.

Bearer-auth JSON API for humanize, detect, voice profiles, and the bypass loop. Pro-only.

The API is Pro-only. Reading the docs is fine; getting a key needs an upgrade.Sign in

Setup#

The API is Pro-only and uses Bearer-token auth. Create a key from your Pro dashboard API tab, then include it on every request:

Authorization: Bearer hmw_<your-key>
Content-Type: application/json

Base URL: https://www.humanizemywriting.com. All endpoints accept and return JSON.

Rate limits

API calls share your daily Pro quota (200 humanize/day). Each /v1/humanize, /v1/detect, and bypass attempt counts as one. When exhausted, you’ll get a 429 with a Retry-After header.

Privacy

Inputs to /v1/humanize, /v1/detect, and /v1/bypass are processed in memory and discarded — never logged, never used for training. Voice profile samples (when you POST to /v1/voices) are the documented exception; they’re retained on your account. See /privacy.

Posting non-trivial inputs from curl

Shell escaping bites with multi-line prose. Two reliable patterns:

# Pattern A: prose file + jq for escaping
cat > /tmp/prose.txt <<'PROSE_END'
<paste your text here, line breaks and quotes are fine>
PROSE_END

jq -n --rawfile text /tmp/prose.txt \
  '{text: $text, intensity: 4, mode: "academic"}' \
| curl -X POST https://www.humanizemywriting.com/api/v1/humanize \
    -H "Authorization: Bearer hmw_..." \
    -H "Content-Type: application/json" \
    --data @-
# Pattern B: python3 one-liner (no jq required)
python3 -c "import json, sys; print(json.dumps({
  'text': open('/tmp/prose.txt').read(),
  'intensity': 4
}))" | curl -X POST https://www.humanizemywriting.com/api/v1/humanize \
        -H "Authorization: Bearer hmw_..." \
        -H "Content-Type: application/json" \
        --data @-

POST /api/v1/humanize#

Rewrites text into a more natural, human-sounding version. Accepts all the dials the dashboard exposes — intensity, mode, voice, reference — in one call.

Body

FieldTypeDefaultDescription
textstringRequired. The input.
intensity1–53How aggressively to rewrite. 5 = maximum restructuring.
modestringstandardacademic preserves direct quotations and in-text citations verbatim.
voice_iduuidApply a saved voice profile.
reference_textstring100–2000 words. One-off style match. Wins over voice_id if both are sent.
include_detectorsboolfalseRun the 5-detector strip on the output in the same response.

Example

curl -X POST https://www.humanizemywriting.com/api/v1/humanize \
  -H "Authorization: Bearer hmw_..." \
  -H "Content-Type: application/json" \
  -d '{
    "text": "In today\'s rapidly evolving landscape...",
    "intensity": 4,
    "mode": "academic",
    "include_detectors": true
  }'

Response

{
  "original":      "...",
  "humanized":     "...",
  "diff":          [{ "type": "kept"|"removed"|"added", "text": "..." }],
  "word_count_in": 87,
  "word_count_out": 91,
  "latency_ms":    8432,
  "model":         "claude-sonnet-4-5",
  "prompt_version": "v3",
  "prompt_source": "db",
  "detectors": {                              // only if include_detectors=true
    "detectors": [
      { "id": "gptzero", "score": 0.18, "source": "live", "status": "ok", ... },
      ...
    ],
    "passed": 4,
    "total":  5,
    "disclaimer": "..."
  }
}

POST /api/v1/detect#

Runs the 5-detector strip on a piece of text. Returns per-detector scores plus a passed/total summary. Max 2000 words.

curl -X POST https://www.humanizemywriting.com/api/v1/detect \
  -H "Authorization: Bearer hmw_..." \
  -d '{ "text": "..." }'

gptzero is live when GPTZERO_API_KEY is configured on the server, plus an in-house detector. The others (Originality, Turnitin, Copyleaks) are deterministic stubs derived from the in-house score — each response’s source field discriminates live vs stub.

POST /api/v1/bypass#

The full bypass loop run server-side: humanize → detect → check against target, ramping intensity until either every detector lands at or below target_score, the output stops improving, or attempts run out.

Body

FieldTypeDefaultDescription
textstringRequired.
target_score0–10.3All detectors must land at or below this value to "pass."
max_attempts1–55Upper bound on iterations.
intensity_start1–53Each attempt bumps +1, capped at 5.
modestringstandardSame as humanize.
curl -X POST https://www.humanizemywriting.com/api/v1/bypass \
  -H "Authorization: Bearer hmw_..." \
  -d '{ "text": "...", "target_score": 0.2, "max_attempts": 5 }'

Response

{
  "attempts": [
    {
      "number": 1, "intensity": 3, "humanized": "...",
      "max_score": 0.41, "status": "miss",
      "detectors": [ ... ]
    },
    ...
  ],
  "best":         { ...the winning or lowest-score attempt... },
  "target_score": 0.2,
  "stopped_reason": "pass" | "ceiling" | "exhausted" | "rate_limited" | "error"
}

Each attempt counts as a humanize call against your daily quota; the loop short-circuits if you hit it mid-run (status: rate_limited, partial attempts still returned).

Voices#

Voices are persistent style fingerprints. Create one with a sample of your writing, then pass its id as voice_id in humanize/bypass requests.

GET /api/v1/voices

curl https://www.humanizemywriting.com/api/v1/voices \
  -H "Authorization: Bearer hmw_..."

POST /api/v1/voices

curl -X POST https://www.humanizemywriting.com/api/v1/voices \
  -H "Authorization: Bearer hmw_..." \
  -d '{ "name": "My thesis voice", "sample_text": "..." }'

Sample must be 100–2000 words. The analyzer runs synchronously (~5–10s) and returns a status of ready or failed. Max 8 voices per user.

PATCH /api/v1/voices/{id}

Body: { "is_active": true | false }. Marking a voice active makes it the default for the dashboard’s Humanize Pro tab. API callers should pass voice_id explicitly — the active flag is UI sugar.

DELETE /api/v1/voices/{id}

Hard-deletes the voice (sample + style fingerprint).

Combination recipes#

1. Humanize with a saved voice + academic mode

{
  "text":      "...",
  "voice_id":  "uuid-from-/v1/voices",
  "mode":      "academic",
  "intensity": 4
}

2. Humanize + verify (single round-trip)

{
  "text":              "...",
  "intensity":         4,
  "include_detectors": true
}

Cheaper than calling /v1/humanize then /v1/detect separately — one HTTP hop, one log line, atomic.

3. Style match by reference, one-off

{
  "text":           "...",
  "reference_text": "<paste 100-2000 words of the style you want>"
}

If you have both voice_id and reference_text, the reference wins. Use one or the other per request.

4. Loop until target, then stop

POST /api/v1/bypass
{
  "text":            "...",
  "target_score":    0.2,
  "max_attempts":    5,
  "intensity_start": 3
}

Use when you want guaranteed best-effort without orchestrating calls yourself.

Errors#

StatusMeaning
400Validation error — check the error field.
401Missing, malformed, or revoked key.
403Authenticated but not Pro.
404Resource not found (e.g. voice_id missing).
409Conflict — cap reached (e.g. 8 voices, 5 API keys).
413Payload too large (detector input caps at 2000 words).
429Rate-limit hit — check Retry-After.
503Upstream (Anthropic) busy — try again in ~30s.