API reference.
Every field, every error.
The complete reference for the HumanGPT REST API: three endpoints, every request and response field, every error code, and the limits on each plan. New to the API? Start with the 60-second quick start on the developers page.
Base URL and authentication.
Base URL https://api.humangpt.io/v1. The same API also answers at https://humangpt.io/api/v1. Requests and responses are JSON (Content-Type: application/json).
Send your key on every request, either as Authorization: Bearer hgpt_... or as x-api-key: hgpt_.... Keys are free for any signed-in account with a confirmed email: open API keys in your dashboard. A free account can hold one active key, Pro and Founder up to ten.
Keys are stored hashed and shown once, when created. Revoking a key in the dashboard stops it on its next request. Every call resolves the owner's current plan, so there is nothing to rotate when you upgrade.
Keep keys on your server. The API sends no CORS headers, and a key in browser code can be copied by anyone.
POST /v1/humanize
Rewrites AI text so it reads like a person wrote it, using the same pipeline as the tool on humangpt.io. Free keys run the standard engine. Pro and Founder keys run the premium engine: dozens of candidate rewrites checked against GPTZero, the most human one kept, and a second batch run automatically when the best still reads as AI.
Request body
| Field | Type | Default | Description |
|---|---|---|---|
| text | string | required | The AI text to humanize. At least 15 words (shorter input makes the model invent content). Up to 1,500 words per call on a free key, 8,000 on Pro and Founder. |
| mode | string | medium | light, medium or heavy. The web tool's names are accepted as aliases: subtle, natural, strong. Available on every plan. |
| purpose | string | general | The kind of writing, so structure and tone survive. Free: general, academic, essay. Pro and Founder add article, cover letter, marketing, story, report, business, legal. |
| reading | string | university | Target reading level. Free: highschool, university. Pro and Founder add doctorate, journalist. |
| freeze | string[] | [] | Words or phrases returned exactly as sent. A comma-separated string also works. Citations, numbers, units, acronyms and code are protected automatically. |
| enhanced | boolean | false | Rewrites one step harder. Pro and Founder. |
| language | string | en | One of en, es, fr, de, it, pt, ru, tr, nl, pl, sv, no, da, fi, ja, ko, zh, ar, hi, auto. The engine is tuned for English, where results are best. |
| use_voice | boolean | true | Applies the owner's saved Brand Voice. Pro and Founder; ignored on Free. |
| premium | boolean | true | Pro and Founder: send false to skip the premium engine for one call (faster, less thorough). Free keys always run the standard engine. |
curl -X POST https://api.humangpt.io/v1/humanize \
-H "Authorization: Bearer $HUMANGPT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Artificial intelligence has fundamentally transformed the way modern organizations approach content creation, enabling teams to produce more material in less time than ever before.",
"mode": "heavy",
"purpose": "essay",
"freeze": ["content creation"]
}'Response fields
| Field | Type | Meaning |
|---|---|---|
| id | integer | Run id. The run also appears in the owner's dashboard history. |
| object | string | Always "humanization". |
| output | string | The humanized text. |
| words_in / words_out | integer | Words sent and returned. Also returned as input_words / output_words, the names used by the first version of this reference. |
| ai_score | number | null | Real GPTZero probability [0, 1] that the output reads as AI, from the check run on this call. null when that check was skipped. Lower is better. |
| engine | string | "premium" when the premium engine produced the output (Pro and Founder), otherwise "standard". |
| resisted | boolean | True when the text still read as AI after two full attempts. The call is not charged; message explains what to try. |
| message | string | null | Advice when resisted is true. |
| degraded | boolean | True if the rewrite engine was unavailable and the output is unlaundered. Retry later. |
| mode / purpose / reading / enhanced | The options that were applied. | |
| plan | string | The owner's plan at the time of the call: free, pro or founder. |
| usage.words_remaining | integer | null | Words left in the current period after this call. Also returned as quota_remaining. |
| usage.words_limit | integer | null | The period's allowance (500 a day on Free, 50,000 a month on Pro). null when the plan has no enforced cap. |
| usage.period | string | null | "day" on Free, "month" on Pro. |
| usage.resets_at | string | null | When the current window ends (ISO 8601). Free words come back 24 hours after they were used. |
POST /v1/detect
Checks a text for AI writing with the HumanGPT detector. Body: text (required, up to 8,000 words) and optional language. Detection does not use humanizer words. Each key is capped at 1,000 calls a month on Free, 50,000 on Pro and 1,000,000 on Founder, counting detect and humanize calls together; the cap is checked on /detect. /v1/check is an alias.
curl -X POST https://api.humangpt.io/v1/detect \
-H "Authorization: Bearer $HUMANGPT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Artificial intelligence has fundamentally transformed the way modern organizations approach content creation, enabling teams to produce more material in less time than ever before."}'Response fields
| Field | Type | Meaning |
|---|---|---|
| object | string | Always "detection". |
| request_id | string | Unique id for this check. |
| verdict | string | human, ai or mixed. |
| verdict_label | string | The verdict in words, e.g. "Likely AI-generated". |
| score | number | Probability [0, 1] that the text is AI-written. |
| confidence | string | high, medium or low. |
| abstain | boolean | True when the signals disagree (verdict mixed). Treat as "can't tell". |
| signals[] | array | Each signal that fed the verdict: name, score, and weight where applicable. |
| preprocessing | object | null | Evasion checks: unicode normalization, zero-width characters stripped, homoglyphs replaced, evasion_suspected. |
| plan / total_latency_ms | The owner's plan, and how long the check took. |
GET /v1/usage
Your plan and allowance right now. Calls on the website and through the API draw on the same allowance, so this matches your dashboard. Every humanize response also carries usage, so you rarely need a separate call.
curl https://api.humangpt.io/v1/usage -H "Authorization: Bearer $HUMANGPT_API_KEY"
Response fields
| Field | Type | Meaning |
|---|---|---|
| plan | string | The owner's current plan. Upgrades apply to existing keys immediately. |
| key.prefix / key.label | string | Which key made the request. |
| period | string | null | "day" on Free, "month" on Pro. |
| words_used / words_limit / words_remaining | integer | null | The current window. Shared with the website. |
| month.words_used / month.words_limit | integer | null | Free only: the 30-day total against the 2,000-word monthly cap. |
| runs_today | integer | null | Free only: calls in the last 24 hours, against the 25-call daily cap. |
| max_words_per_request | integer | 1,500 on Free, 8,000 on Pro and Founder. |
| requests_per_minute | integer | 30 on Free, 120 on Pro, 600 on Founder. |
| engine | string | standard (Free) or premium (Pro and Founder). |
Errors.
Every error has the same shape: { "error": { "code": "...", "message": "..." } }, plus fields where they help (words_remaining, max_words, retry_after_seconds). On a free key, errors caused by a plan limit also include upgrade_url. Branch on error.code, not on the message text.
| HTTP | error.code | Meaning |
|---|---|---|
| 401 | missing_api_key | No key sent. Use Authorization: Bearer hgpt_... or x-api-key. |
| 401 | invalid_api_key | Unknown or revoked key, or the owning account no longer exists. |
| 403 | endpoint_not_allowed | The key is scoped away from this endpoint. |
| 400 | invalid_json · missing_text | The body is not JSON, or text is missing. |
| 400 | invalid_mode · invalid_purpose · invalid_reading | An option value is not one of the allowed values. The message lists them. |
| 400 | invalid_request | Rejected before running, e.g. fewer than 15 words or an unsupported language code. |
| 402 | quota_exceeded | Not enough words left in the current window. words_remaining says how many. |
| 402 | exceeds_allowance | The text is bigger than the whole daily allowance, so it cannot run on this plan. |
| 402 | monthly_limit | Free: the 2,000-word monthly cap is used up. |
| 402 | plan_feature | A Pro-only option (purpose, reading level or enhanced) on a free key. |
| 403 | forbidden | The account is restricted. |
| 413 | input_too_long | More words than one call allows. max_words and max_words_pro say the limits. |
| 415 | unsupported_input | Tables, forms, or text in a language the engine can't take. Send prose. |
| 422 | declined | The content was declined by the model providers' safety filters. Retrying won't change it. |
| 429 | rate_limited | Over the per-minute limit. Wait retry_after_seconds (also the Retry-After header). |
| 429 | daily_run_limit | Free: 25 calls in 24 hours. |
| 500 | engine_error | Temporary failure. Retry with backoff. |
Limits by plan.
| Free key | Pro · $19/mo | Founder · $199 once | |
|---|---|---|---|
| Humanizer words | 500 a day, 2,000 a month | 50,000 a month | 150,000 a month |
| Words per humanize call | 15 to 1,500 | 15 to 8,000 | 15 to 8,000 |
| Humanize calls per day | 25 | No daily cap | No daily cap |
| Requests per minute, per key | 30 | 120 | 600 |
| Calls a month per key (checked on /detect) | 1,000 | 50,000 | 1,000,000 |
| Engine | Standard | Premium on every call | Premium on every call |
| Options | 3 purposes, 2 reading levels | All 10 purposes, 4 levels, enhanced | All |
| Brand Voice | No | Yes | Yes |
| Active keys | 1 | 10 | 10 |
Free words come back 24 hours after they are used; the Pro allowance is a rolling 30 days. Annual Pro is $108 a year ($9 a month). Compare plans.
Best practices.
- Timeouts. Use 300 seconds for /humanize and 120 for /detect. Most calls finish in under a minute; long documents on Pro take longer because more rewrites are checked.
- Retries. Retry 429 and 5xx with exponential backoff, honouring Retry-After. Do not retry other 4xx errors unchanged. A humanize call that timed out on your side may have completed and been charged, so check GET /usage before sending it again.
- Long documents. Split at paragraph boundaries, keep each call under your per-call limit, and send them in parallel within your requests-per-minute limit.
- Stubborn text. If ai_score stays high, send it again with mode heavy. Protect names and keywords with freeze rather than editing the output afterwards.
- Keys. One key per app or environment, stored in an environment variable. Revoke and replace a key you think leaked.
- Budget. Read usage.words_remaining from each response and stop before you hit 402.
Changelog.
- 2026-09-11 · v1 live: POST /v1/humanize, POST /v1/detect (with /v1/check as an alias), GET /v1/usage. Free keys for verified accounts. Bearer or x-api-key authentication. OpenAPI 3.1 spec published.
v1 changes are additive only: new fields may appear in responses, existing fields keep their meaning.
Reference questions.
Straight answers.
The words you send in text, once per successful call. A call that resisted the rewrite (resisted: true) is refunded. Detection calls do not use humanizer words. API calls and runs on humangpt.io share one allowance.
Yes. Every humanize call is recorded as a run on the key owner's account, the same as a run on the website, and returns its id.
On Pro and Founder, yes: if you have saved a Brand Voice in the dashboard, it is applied by default. Send use_voice: false for a neutral rewrite.
Yes, at https://humangpt.io/openapi.json (OpenAPI 3.1). Import it into Postman, Insomnia or a code generator.
Not yet. The API is plain HTTPS and JSON, so any HTTP client works; the examples on this page are complete.
Nothing you need to do. Every call reads your current plan, so an existing key gets Pro limits the moment you upgrade and Free limits when Pro ends.
It is an alias of /detect, kept because an earlier version of this reference documented it. New code should call /detect.
Use a 300-second timeout for /humanize. Retry 429 and 5xx with exponential backoff. Do not retry 4xx errors other than 429, and do not blindly retry a humanize call that timed out on your side: it may have completed and been charged. Check GET /usage first.
A free key, three endpoints, one allowance shared with the website.