DEV Community

Mohab Abdelkarim
Mohab Abdelkarim

Posted on

AI Humanizer API in 2026: A Developer Integration Guide

If your product generates text with a language model and ships it anywhere a detector might see it, raw model output is a liability. Humanizer APIs solve a narrow problem: take generated text, rewrite it so it reads like a person wrote it, and hand it back as JSON you can act on.

This guide covers integrating one end to end using Walter's Humanizer API, which is the most completely documented option in this category right now. The patterns transfer to any competitor with a REST surface.

Table of Contents

  1. What You're Actually Integrating
  2. Getting a Key and Choosing Scopes
  3. Your First Request
  4. Reading the Response
  5. Sync vs Async: Picking a Mode
  6. The Combined Detect-and-Humanize Endpoint
  7. A Production-Ready Wrapper
  8. Credits, Pricing, and Cost Control
  9. Failure Modes Worth Planning For
  10. What the API Can't Do
  11. FAQs

1. What You're Actually Integrating

A humanizer API takes text in, returns rewritten text out. Underneath, it restructures sentence rhythm and paragraph flow rather than swapping synonyms, which matters because detectors measure statistical properties like token predictability and sentence-length variance, not vocabulary.

Walter launched its unified API Platform in 2026, consolidating what were previously separate products behind one key and one credit balance. The available endpoints today:

  • /api/humanizer/ for rewriting AI text into natural output
  • /api/detector/ for sentence-level AI probability scoring
  • /api/detect-and-humanize/ for both in one call
  • Image detection, with voice detection, plagiarism, and grammar checking on the roadmap

Every endpoint shares the same auth, request shape, and response structure. Practically, that means adding a second endpoint later is a few lines rather than a second integration.

2. Getting a Key and Choosing Scopes

Sign in to the Developer Portal and create a key on the API Keys page. You select scopes at creation time: Humanizer, AI Detector, Image Detector, or any combination.

Two things to get right here.

Scope narrowly. If a service only humanizes, don't give its key detector scope. This is standard least-privilege practice and costs nothing to do upfront.

The full key is shown once. Copy it at creation and store it in your secrets manager immediately. There's no retrieval later.

Keys live server-side only. This is a backend integration, same reasoning as any other secret you wouldn't ship in a browser bundle.

3. Your First Request

The humanizer endpoint is a single POST:

curl -X POST https://developer-portal.walterwrites.ai/api/humanizer/ \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "content": "Artificial intelligence has revolutionized numerous industries by automating complex tasks and enhancing decision-making processes."
  }'
Enter fullscreen mode Exit fullscreen mode

That's the whole minimum request. Text in the content field, key in the X-API-Key header. No job setup, no queue configuration.

Note the auth scheme, because it's a common integration bug: this is a custom X-API-Key header, not Authorization: Bearer. If you're copying a wrapper from another API, that line needs changing.

4. Reading the Response

{
  "status": "success",
  "result": "AI has transformed many industries, making complex tasks automatic and improving how decisions are made.",
  "execution_time": 2.34,
  "word_count": 18,
  "credits_remaining": 1982,
  "user": {
    "id": 12345
  }
}
Enter fullscreen mode Exit fullscreen mode

Four fields matter for building on this.

result is your rewritten text. status tells you whether the job completed. word_count is what you were billed for. credits_remaining is the field most integrations ignore and then regret ignoring.

Log credits_remaining on every call from day one. It's the cheapest possible quota monitoring, and it means you can alert on depletion before a pipeline starts failing rather than after. A simple threshold check costs you nothing:

if (data.credits_remaining < LOW_CREDIT_THRESHOLD) {
  logger.warn(`Walter credits low: ${data.credits_remaining} remaining`);
}
Enter fullscreen mode Exit fullscreen mode

5. Sync vs Async: Picking a Mode

All service endpoints support both synchronous and asynchronous processing. Choosing correctly is mostly about where the call sits relative to a user.

Synchronous is the default. You send the request, the connection holds, the rewritten text comes back. Execution time in the example above was 2.34 seconds for 18 words. Fine for short text in a background job. Risky if a user is watching a spinner and your input is a 2,000-word article.

Async with webhooks is the right default for anything long-form or batch. Pass a callback_url and the API posts results when the job finishes:

curl -X POST https://developer-portal.walterwrites.ai/api/humanizer/ \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "content": "Your long-form draft here...",
    "callback_url": "https://your-app.com/webhooks/humanizer"
  }'
Enter fullscreen mode Exit fullscreen mode

Async with polling exists for environments that can't accept inbound webhooks, which covers a lot of internal tooling and local development. You get a job ID back and check it on an interval.

You can also combine webhook and polling on the same request, which is worth doing if webhook delivery reliability is a concern in your infrastructure. Belt and braces.

A practical rule: if the input is under roughly 300 words and the call is already inside a background worker, sync is simpler and there's no reason to add job-tracking complexity. Above that, or anywhere in a request path a user is waiting on, go async.

6. The Combined Detect-and-Humanize Endpoint

/api/detect-and-humanize/ is the endpoint most integrations should reach for, and it's underused because people build the two-step version first.

The naive pipeline is: score everything, then humanize everything above a threshold. That's two round trips, two sets of error handling, and you're burning credits humanizing text that was already fine. The combined endpoint collapses that into one call.

This matters for cost as much as for latency. If half your content doesn't need rewriting, humanizing all of it doubles your spend on the humanizer side for no benefit.

7. A Production-Ready Wrapper

Here's a Node wrapper with the things you'll otherwise add later after something breaks:

const WALTER_BASE = "https://developer-portal.walterwrites.ai/api";

async function humanize(content, { callbackUrl, timeoutMs = 30000 } = {}) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);

  const body = { content };
  if (callbackUrl) body.callback_url = callbackUrl;

  try {
    const res = await fetch(`${WALTER_BASE}/humanizer/`, {
      method: "POST",
      headers: {
        "X-API-Key": process.env.WALTER_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
      signal: controller.signal,
    });

    if (res.status === 429) {
      const retryAfter = Number(res.headers.get("retry-after") || 5);
      throw Object.assign(new Error("rate_limited"), { retryAfter });
    }
    if (!res.ok) {
      throw new Error(`Humanizer returned ${res.status}`);
    }

    const data = await res.json();
    return {
      text: data.result,
      wordCount: data.word_count,
      creditsRemaining: data.credits_remaining,
      executionTime: data.execution_time,
    };
  } catch (err) {
    if (err.name === "AbortError") throw new Error("humanizer_timeout");
    throw err;
  } finally {
    clearTimeout(timer);
  }
}
Enter fullscreen mode Exit fullscreen mode

And the Python equivalent, with exponential backoff on rate limits:

import os
import time
import requests

BASE = "https://developer-portal.walterwrites.ai/api"
HEADERS = {
    "X-API-Key": os.environ["WALTER_API_KEY"],
    "Content-Type": "application/json",
}

def humanize(content: str, callback_url: str | None = None,
             max_retries: int = 3) -> dict:
    payload = {"content": content}
    if callback_url:
        payload["callback_url"] = callback_url

    for attempt in range(max_retries):
        r = requests.post(f"{BASE}/humanizer/", headers=HEADERS,
                          json=payload, timeout=30)

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

        r.raise_for_status()
        data = r.json()
        return {
            "text": data["result"],
            "word_count": data["word_count"],
            "credits_remaining": data["credits_remaining"],
        }

    raise RuntimeError("humanizer: retries exhausted")
Enter fullscreen mode Exit fullscreen mode

Both treat timeouts and rate limits as expected conditions rather than exceptions to handle someday. If this call sits in a publishing pipeline, a hung request must not be able to block the publish.

8. Credits, Pricing, and Cost Control

Billing is credit-based and refreshingly simple to reason about: 1 credit = 1 word for text endpoints. Image detection is priced by resolution instead.

Published tiers run from $49/month for 300,000 words up to $1,699/month for 25 million, with custom enterprise pricing above that. There's a free tier requiring no credit card, which is enough to build and test an integration before committing.

Three things that actually control cost in production:

Don't humanize what doesn't need it. Use the combined endpoint or a detection threshold. This is the single biggest lever.

Set a minimum length. Humanizing a 12-word string burns credits for negligible benefit. A floor of a couple hundred words is reasonable for most pipelines.

Cache aggressively. If the same input can be submitted twice, hash it and store the result. Re-humanizing identical text costs credits and, since these systems are largely deterministic, usually returns near-identical output anyway.

The shared credit balance across endpoints is genuinely useful here. A detect-then-humanize pipeline draws from one pool, so you're not forecasting two budgets separately.

9. Failure Modes Worth Planning For

Fail open, not closed. If humanization fails, your pipeline should log it and flag the item for review, not reject the content. An outage in a nice-to-have service should never become an outage in your core flow.

Webhook deliveries can be missed. If you're webhook-only, add a reconciliation job that polls for jobs stuck in a pending state past some threshold. Or just enable polling alongside webhooks on the same request.

Idempotency is your problem. Store a hash of the input alongside the job so a retry after a network blip doesn't submit and bill twice.

Output can shift meaning. This is the failure mode people forget because it doesn't throw an error. A rewrite can alter a technical claim, a figure, or a sentence where one word carries the argument. If your content has non-negotiable terms, check whether your tool supports phrase preservation and use it. If it doesn't, diff the output.

10. What the API Can't Do

Worth stating plainly, because the marketing in this category rarely does.

Walter publishes a 96.4% combined pass rate tested against GPTZero, Proofademic, Turnitin AI, Originality.ai, Copyleaks, and Sapling. That's a vendor-published number, and it's higher than most competitors publish, but 96.4% is not 100% and shouldn't be architected around as if it were.

The vendor's own documentation cites two papers worth reading before you build anything high-stakes on this. The RAID benchmark (arXiv 2405.07940) found humanization drops detector accuracy by 30 to 70 percentage points across multiple systems, which quantifies both how well this works and how much it varies by detector. Sadasivan et al. 2023 (arXiv 2303.11156) argued that any detector can theoretically be evaded through paraphrasing, which cuts both ways: it explains why humanizers work, and why detection-evasion is a moving target rather than a solved state.

Practically: humanizers work best on well-structured input, occasionally produce awkward phrasing that needs a human pass, and vary in effectiveness by which detector you're up against. Build a review step. Don't build a system whose correctness depends on a detection score staying below a threshold indefinitely.

11. FAQs

What authentication does the Walter Humanizer API use?
A custom X-API-Key header, not bearer tokens. Keys are created in the Developer Portal with selectable scopes, and the full key is displayed only once at creation.

Is the humanizer endpoint synchronous or asynchronous?
Both. Every service endpoint supports sync responses, async with webhook delivery via callback_url, async with polling, or webhook and polling combined on the same request.

How is usage billed?
Credit-based, at 1 credit per word for text endpoints. Image detection is priced by resolution. Every endpoint draws from a single shared monthly balance, so a detect-then-humanize pipeline doesn't require forecasting two budgets.

Can I detect and humanize in one request?
Yes, via /api/detect-and-humanize/. It's usually the better default than two separate calls, since it avoids spending humanizer credits on content that scored clean.

Is there a free tier for testing?
Yes. You can create an account, generate a key, and make your first calls with no credit card required, which is enough to build and validate an integration before choosing a paid tier.

What happens to my keywords and product names during humanization?
That depends on whether you use phrase preservation. Humanizers routinely paraphrase brand names, technical terms, and cited figures unless told not to. If exact terms matter in your output, verify preservation support before wiring this into anything automated.

Should the humanizer sit in my request path or a background job?
Background job, in almost every case. Sync execution took 2.34 seconds on an 18-word sample, and longer inputs scale from there. Anything user-facing should go async with a webhook.

Top comments (0)