Ninja Developer API v1 Reference

AI Humanizer API Documentation

Humanize AI-generated text, detect AI authorship, and track usage through a simple REST API. Header-based authentication, predictable word pricing, plain JSON.

Base URL https://api.ninjahumanizer.com/v1

Quickstart

Get up and running in under a minute.

1

Get your API key

Sign up or log in, pick a plan with API access, then create a key from your dashboard. Live keys are prefixed nhk_live_.

2

Make your first request

curl -X POST https://api.ninjahumanizer.com/v1/humanize \
  -H "X-API-Key: nhk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"text": "Artificial intelligence has revolutionized the way we approach content creation.", "tone": "standard"}'
3

See the response

Take humanized_text from the body and read quota to track your balance.

200 OK
{
  "success": true,
  "humanized_text": "AI has changed how we create content and communicate online.",
  "input_word_count": 14,
  "output_word_count": 14,
  "tone": "standard",
  "truncated": false,
  "response_time_ms": 1843,
  "quota": {
    "remaining": 98500,
    "plan_words_remaining": 98500,
    "pack_words_remaining": 0
  }
}

Authentication

All API requests require your key in the X-API-Key header. There is no OAuth flow and no session cookie. Create and manage keys from your dashboard.

X-API-Key: nhk_live_your_api_key_here

Keys use the prefix nhk_live_ followed by a unique token. The full key is shown once at creation β€” we only store a hash, so treat it like a password. Never ship a key in browser or mobile code; call the API from your backend and proxy the result. You can revoke any key at any time.

Plans & Limits

Choose a plan that fits your usage. All plans include a monthly word allowance that resets each billing cycle.

Standard Premium
Monthly price $24.00 $59.00
Monthly words 150,000 500,000
Max words per request 2,000 4,000
Rate limit 60 req/min 120 req/min
API keys 2 5

Usage is tracked by input word count and shared across /v1/humanize and /v1/detect. Words are deducted from your monthly allowance first, then from any top-up packs, which never expire. Requests longer than your per-request limit are truncated rather than rejected β€” the response sets truncated: true.

Endpoint Reference

Five REST endpoints, one base URL, one API key. All requests authenticate the same way.

POST

/v1/humanize

https://api.ninjahumanizer.com/v1/humanize

Rewrite AI-generated text so it reads naturally human. Deducts input words from your balance. Words come out of your monthly plan allowance first, then from any purchased top-up packs. Inputs longer than your per-request word limit are truncated rather than rejected.

Request body β€” application/json

text Required

string

The text to humanize.

>= 10 characters, <= 100,000 characters, minimum 10 words

tone Optional

string

Optional writing tone. Omit for the default style.

Allowed values: standard, professional, academic, blog, casual

200 Text humanized successfully

Response body β€” application/json

success

boolean

True when the request completed. Always check this first.

humanized_text

string

The rewritten text.

input_word_count

integer

Words billed for this request, counted after any truncation.

output_word_count

integer

Words in the returned text.

tone

string

The tone that was applied.

truncated

boolean

True when the input exceeded your per-request word limit and was cut short.

response_time_ms

integer

Server-side processing time in milliseconds.

quota

object

Your remaining word balance after this request.

Fields: remaining (integer), plan_words_remaining (integer), pack_words_remaining (integer)

Example response
{
  "success": true,
  "humanized_text": "AI has changed how we create content and communicate online.",
  "input_word_count": 14,
  "output_word_count": 14,
  "tone": "standard",
  "truncated": false,
  "response_time_ms": 1843,
  "quota": {
    "remaining": 98500,
    "plan_words_remaining": 98500,
    "pack_words_remaining": 0
  }
}

Error responses

401 Missing or invalid API key.

Missing header

{ "error": "No API key provided", "error_code": "missing_api_key" }

Invalid, revoked or expired key

{ "error": "Invalid API key", "error_code": "invalid_api_key" }
403 Your plan does not include API access.

No API access

{ "error": "API access is not available on your plan", "error_code": "api_access_required" }
422 Invalid input or unavailable tone.

Text too short

{ "error": "Input text is too short. Please provide at least 10 words.", "error_code": "text_too_short" }

Text too long

{ "error": "The text field must not be greater than 100000 characters.", "error_code": "text_too_long" }

Tone not available

{ "error": "Tone 'xyz' is not available. Use GET /v1/tones to see available tones.", "error_code": "tone_not_available" }
429 Rate limit exceeded or word quota exhausted.

Rate limit

{ "error": "Too many requests. Please slow down.", "error_code": "rate_limited" }

Quota exhausted

{ "error": "You have exhausted your API word quota.", "error_code": "quota_exhausted", "plan_words_remaining": 0, "pack_words_remaining": 0 }
500 Processing failure.

Server error

{ "error": "Failed to humanize text. Please try again later.", "error_code": "server_error" }
POST

/v1/detect

https://api.ninjahumanizer.com/v1/detect

Score text for AI authorship. Billed per input word from the same balance as /v1/humanize. Returns an AI probability from 0 to 100 where higher means more likely machine-written, plus a convenience boolean derived from that score.

Request body β€” application/json

text Required

string

The text to score for AI authorship.

>= 10 characters, <= 50,000 characters

200 Text scored successfully

Response body β€” application/json

success

boolean

True when the request completed.

ai_probability

number

Likelihood the text was AI-generated.

0–100, higher = more likely AI

is_human

boolean

Convenience flag derived from the probability score.

ai_score

number

Raw detection score returned by the model.

word_count

integer

Words billed for this request.

response_time_ms

integer

Server-side processing time in milliseconds.

quota

object

Your remaining word balance after this request.

Fields: remaining (integer), plan_words_remaining (integer), pack_words_remaining (integer)

Example response
{
  "success": true,
  "ai_probability": 94.5,
  "is_human": false,
  "ai_score": 94.5,
  "word_count": 215,
  "response_time_ms": 1200,
  "quota": {
    "remaining": 97800,
    "plan_words_remaining": 97800,
    "pack_words_remaining": 0
  }
}

Error responses

401 Missing or invalid API key.

Missing header

{ "error": "No API key provided", "error_code": "missing_api_key" }

Invalid, revoked or expired key

{ "error": "Invalid API key", "error_code": "invalid_api_key" }
403 Your plan does not include API access.

No API access

{ "error": "API access is not available on your plan", "error_code": "api_access_required" }
422 Invalid input.

Text too short

{ "error": "The text field must be at least 10 characters.", "error_code": "text_too_short" }

Text too long

{ "error": "The text field must not be greater than 50000 characters.", "error_code": "text_too_long" }
429 Rate limit exceeded or word quota exhausted.

Rate limit

{ "error": "Too many requests. Please slow down.", "error_code": "rate_limited" }

Quota exhausted

{ "error": "You have exhausted your API word quota.", "error_code": "quota_exhausted", "plan_words_remaining": 0, "pack_words_remaining": 0 }
500 Processing failure.

Server error

{ "error": "Failed to humanize text. Please try again later.", "error_code": "server_error" }
GET

/v1/status

https://api.ninjahumanizer.com/v1/status

Retrieve the limits configured on your key together with your current quota. Read-only β€” it never deducts words. Remaining balance = plan_words_remaining + pack_words_remaining.

No request body or query parameters. Send the API key header only.

200 Key status returned

Response body β€” application/json

name

string

The label you gave this key.

environment

string

Key environment.

live

word_limit_per_request

integer

Maximum words accepted in a single request before truncation.

rate_limit_per_minute

integer

Requests allowed per minute on this key.

expires_at

string | null

ISO-8601 expiry timestamp, or null when the key does not expire.

quota

object

Monthly allowance, usage so far, and remaining balance.

Fields: monthly_quota, monthly_used, plan_words_remaining, pack_words_remaining, total_remaining

Example response
{
  "success": true,
  "name": "My Production Key",
  "environment": "live",
  "word_limit_per_request": 5000,
  "rate_limit_per_minute": 60,
  "expires_at": null,
  "quota": {
    "monthly_quota": 100000,
    "monthly_used": 1500,
    "plan_words_remaining": 98500,
    "pack_words_remaining": 50000,
    "total_remaining": 148500
  }
}

Error responses

401 Missing or invalid API key.

Missing header

{ "error": "No API key provided", "error_code": "missing_api_key" }

Invalid, revoked or expired key

{ "error": "Invalid API key", "error_code": "invalid_api_key" }
403 Your plan does not include API access.

No API access

{ "error": "API access is not available on your plan", "error_code": "api_access_required" }
GET

/v1/usage

https://api.ninjahumanizer.com/v1/usage

Retrieve a 30-day daily usage breakdown for the calling key, grouped by date, endpoint and status. Read-only β€” it never deducts words. Useful for building your own usage dashboard.

No request body or query parameters. Send the API key header only.

200 Usage returned

Response body β€” application/json

summary

object

Lifetime totals for this key.

Fields: total_requests (integer), success_rate (number), monthly_words_used (integer)

daily_breakdown

object[]

One row per date, endpoint and status combination over the last 30 days.

Fields: date, endpoint, status, requests, words

Example response
{
  "success": true,
  "summary": {
    "total_requests": 842,
    "success_rate": 99.1,
    "monthly_words_used": 1500
  },
  "daily_breakdown": [
    {
      "date": "2026-07-25",
      "endpoint": "humanize",
      "status": "success",
      "requests": 12,
      "words": 4200
    }
  ]
}

Error responses

401 Missing or invalid API key.

Missing header

{ "error": "No API key provided", "error_code": "missing_api_key" }

Invalid, revoked or expired key

{ "error": "Invalid API key", "error_code": "invalid_api_key" }
403 Your plan does not include API access.

No API access

{ "error": "API access is not available on your plan", "error_code": "api_access_required" }
GET

/v1/tones

https://api.ninjahumanizer.com/v1/tones

List the writing tones you can pass to /v1/humanize. The available flag reflects your own plan β€” premium tones report available: false until you upgrade. Read-only, no words deducted.

No request body or query parameters. Send the API key header only.

200 Tones returned

Response body β€” application/json

has_premium_access

boolean

True when your plan unlocks premium tones.

tones

object[]

Every active tone, ordered for display.

Fields: key (string), label (string), requires_pro (boolean), available (boolean)

Example response
{
  "success": true,
  "has_premium_access": true,
  "tones": [
    { "key": "standard", "label": "Standard", "requires_pro": false, "available": true },
    { "key": "formal", "label": "Formal", "requires_pro": true, "available": true }
  ]
}

Error responses

401 Missing or invalid API key.

Missing header

{ "error": "No API key provided", "error_code": "missing_api_key" }

Invalid, revoked or expired key

{ "error": "Invalid API key", "error_code": "invalid_api_key" }
403 Your plan does not include API access.

No API access

{ "error": "API access is not available on your plan", "error_code": "api_access_required" }

Code Examples

Production-shaped snippets with error handling and backoff on rate limits.

import os, time, requests

BASE = "https://api.ninjahumanizer.com/v1"
HEADERS = {"X-API-Key": os.environ["NINJA_API_KEY"]}


def humanize(text, tone="standard", retries=3):
    for attempt in range(retries):
        r = requests.post(
            f"{BASE}/humanize",
            headers=HEADERS,
            json={"text": text, "tone": tone},
            timeout=60,
        )

        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", 2 ** attempt)))
            continue

        data = r.json()
        if not data.get("success"):
            raise RuntimeError(data.get("error_code", "unknown_error"))

        return data["humanized_text"]

    raise RuntimeError("rate_limited")

Tones

Pass any of these keys as the tone parameter on /v1/humanize. Call GET /v1/tones at runtime to see which ones your own plan unlocks.

standard Standard professional Professional Pro academic Academic Pro blog Blog Pro casual Casual Pro

Support

Send us the endpoint, your request body and the error_code you received and we'll dig in. Custom limits and volume pricing are available on request.

NinjaHumanizer

Language / Idioma