If your product accepts user-submitted text, an essay, a cover letter, a marketplace listing, a forum post, you're already dealing with AI-generated content whether you've built anything to handle it or not. The question isn't really whether to add detection anymore. It's how to wire it in without turning it into a multi-week project.
This guide walks through adding AI content detection to a real app using Walter's AI Detector API: getting a key, making your first request, parsing the response correctly, and handling the part everyone skips, what to actually do when the score is wrong.
Table of Contents
- What You're Building
- Getting an API Key
- Making Your First Request
- Understanding the Response
- Wiring It Into Your App
- Handling False Positives Properly
- Common Integration Patterns
- Pricing and Scaling
- Conclusion
- FAQs
1. What You're Building
By the end of this, you'll have a working function that takes a string of text, sends it to Walter's detector, and gets back a calibrated probability score you can act on, flag for review, log, or display, depending on what your app actually needs to do with it.
The API scores text generated by any major model, GPT-4, Claude, Gemini, Llama, and others, and returns a probability rather than a flat yes-or-no verdict, which matters more than it sounds like once you get to the section on false positives.
2. Getting an API Key
Sign up at platform.walterwrites.ai to get a key. Walter's infrastructure is SOC 2 Type I compliant, worth knowing if you're integrating this into anything that touches user data under a compliance requirement of your own, like an education product handling FERPA-covered records.
Keep the key server-side. This is a backend integration, not something you call directly from client-side JavaScript, for the same reason you wouldn't expose any other secret API key in a browser bundle.
3. Making Your First Request
The core endpoint is a single POST request:
curl https://api.walterwrites.ai/v1/detect \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "In todays rapidly evolving digital landscape, organizations must strategically leverage innovative technologies to optimize operational efficiency.",
"language": "en"
}'
That's the whole request. Text in, a language hint if you have one, standard bearer token auth. No batching setup, no async job queue required for a single check like this one.
4. Understanding the Response
A successful call returns something like this:
{
"id": "det_4k2p9x1m3",
"status": "completed",
"model": "detector-v3",
"created_at": "2026-06-12T13:45:00Z",
"output": {
"ai_probability": 0.87,
"words_processed": 12
},
"usage": {
"credits_used": 12
}
}
ai_probability is the field you'll build most of your logic around. It's a float between 0 and 1, not a binary flag, which is a deliberate design choice worth keeping intact in your own app rather than collapsing it into a boolean the first chance you get. A 0.87 and a 0.99 both round up to "flag this," but they're not the same signal, and you'll want that distinction later if you ever need to explain a decision to a user.
credits_used scales with word count, so logging it per request from day one saves you from guessing where your monthly quota went once volume picks up.
5. Wiring It Into Your App
Here's a minimal Node.js wrapper that handles the request, a timeout, and a couple of the error cases you'll actually hit in production:
async function detectAiContent(text, language = "en") {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000);
try {
const response = await fetch("https://api.walterwrites.ai/v1/detect", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WALTER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text, language }),
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`Detector API returned ${response.status}`);
}
const data = await response.json();
return {
probability: data.output.ai_probability,
wordsProcessed: data.output.words_processed,
creditsUsed: data.usage.credits_used,
};
} catch (err) {
if (err.name === "AbortError") {
throw new Error("Detector API request timed out");
}
throw err;
} finally {
clearTimeout(timeout);
}
}
And the Python equivalent, for anyone wiring this into a Django or FastAPI backend instead:
import os
import requests
def detect_ai_content(text: str, language: str = "en") -> dict:
response = requests.post(
"https://api.walterwrites.ai/v1/detect",
headers={
"Authorization": f"Bearer {os.environ['WALTER_API_KEY']}",
"Content-Type": "application/json",
},
json={"text": text, "language": language},
timeout=10,
)
response.raise_for_status()
data = response.json()
return {
"probability": data["output"]["ai_probability"],
"words_processed": data["output"]["words_processed"],
"credits_used": data["usage"]["credits_used"],
}
Both versions treat a timeout and a non-200 response as first-class cases, not afterthoughts. If this call sits in the middle of a submission flow, a hung request shouldn't be able to block your user from submitting anything.
6. Handling False Positives Properly
This is the part most detection integrations get wrong, and it's the difference between a useful feature and a support ticket generator.
Walter's own published data on this is worth internalizing before you write any flagging logic: false positive rates typically run 4 to 12 percent at a 50 percent confidence threshold, meaning legitimate human writing gets incorrectly flagged roughly once every 10 to 25 samples. That's not a bug to route around, it's the actual behavior of probabilistic detection, and it shows up more on non-native English writing, highly formal or technical text, anything under 100 words, and heavily edited human content, since all of those reduce the natural variation detectors use as a human signal.
The practical response is a two-pass workflow, not a single hard cutoff. Flag anything above a threshold you choose based on your own risk tolerance, then have a human reviewer look specifically at the flagged cases rather than trusting the score as a final verdict. If you're building for a high-stakes context like academic integrity or hiring decisions, build in a way for the person on the other end to respond or appeal before any consequence lands, not after.
Here's what that looks like as a simple threshold wrapper around the function above:
async function reviewSubmission(text) {
const result = await detectAiContent(text);
if (result.probability < 0.5) {
return { status: "clear", ...result };
} else if (result.probability < 0.85) {
return { status: "needs_review", ...result };
} else {
return { status: "high_confidence_flag", ...result };
}
}
Three buckets instead of one binary cutoff gives your reviewers somewhere to actually apply judgment on the middle tier, instead of a system that either does nothing or overreacts every time.
It's also worth knowing this isn't a solved problem in any permanent sense. A widely cited 2023 paper by Sadasivan et al., "Can AI-Generated Text Be Reliably Detected?", makes the case that detection evasion is theoretically unbounded as models keep improving, which is part of why Walter retrains its detection models on a regular cycle against newer model outputs rather than shipping a static classifier once and leaving it alone. Build your integration assuming accuracy today isn't a permanent guarantee, and you'll avoid having to rearchitect anything when the numbers shift.
7. Common Integration Patterns
A few patterns show up repeatedly depending on what you're building.
LMS and edtech platforms typically score every submission automatically at upload time, surface a per-student dashboard for instructors, and route anything flagged into a review queue rather than an automatic penalty. If you're in this space, ask about Walter's education tier specifically, since it includes FERPA-aligned data handling and discounted volume pricing.
Content marketplaces and publishers generally flag at ingestion, before content goes live, which keeps obviously low-effort AI submissions from ever reaching an editor's queue in the first place.
HR and recruiting platforms apply this to cover letters, take-home assignments, and written interview responses. This is the context where the two-pass review workflow matters most, since a wrongly flagged candidate is a real cost to get wrong, not just a UX annoyance.
8. Pricing and Scaling
Pricing runs on monthly word quotas, which makes it straightforward to forecast against your own expected volume rather than guessing at enterprise-only pricing upfront.
| Plan | Price | Included Volume |
|---|---|---|
| 300K | $49/mo | 300,000 words |
| 1M | $129/mo | 1,000,000 words |
| 2M | $229/mo | 2,000,000 words |
| 5M | $479/mo | 5,000,000 words |
| 12M | $899/mo | 12,000,000 words |
| 25M | $1,699/mo | 25,000,000 words |
Higher-volume workloads and enterprise deployment needs go through a direct sales conversation rather than a fixed public tier.
9. Conclusion
Adding AI detection to a product is a smaller lift than it sounds like on paper, a single POST request gets you a working score. The part that actually takes engineering judgment is what happens after that response comes back: treating the probability as a probability, building a review path instead of a hard cutoff, and accounting for the specific conditions, short text, technical writing, non-native English, where false positives cluster. Get that part right and the integration itself is genuinely just a few hours of work.
10. FAQs
Do I need to handle async processing for single text checks?
No. A single detection request completes synchronously and returns a result directly, no polling or webhook setup required unless you're doing high-volume batch processing.
What's a reasonable false positive rate to expect?
Walter's own published data puts it at 4 to 12 percent at a 50 percent confidence threshold. Build your review workflow around that expectation rather than assuming a flag is automatically correct.
Should I ever use the AI probability score as the sole basis for an automated decision?
Not for anything with real consequences attached. The recommended pattern is a calibrated threshold that routes borderline and high-confidence flags to a human reviewer rather than triggering an automatic penalty or rejection.
Does this work on text from any AI model, or just ChatGPT?
The detector scores text generated by GPT-4, Claude, Gemini, Llama, and other major models, not just one vendor's output.
How often are the detection models updated?
Walter retrains its detection models on a recurring basis using output from newer language models as they're released, since a static classifier trained once tends to lose accuracy as the models generating text keep changing.
Is there a free way to test this before committing to a paid plan?
Sign up at platform.walterwrites.ai to get an API key and test against your own sample text before choosing a volume tier that matches your actual usage.
Top comments (0)