How to Add AI Content Detection to Your App with a REST API (Node.js + Python)
If your app accepts essays, job applications, reviews, blog posts or support tickets, someone on your team has probably asked: "Can we tell if this was written by AI?" In this tutorial we'll add AI content detection to an app using a REST API, with working Node.js and Python examples. We'll also co

If your app accepts essays, job applications, reviews, blog posts or support tickets, someone on your team has probably asked: "Can we tell if this was written by AI?"
In this tutorial we'll add AI content detection to an app using a REST API, with working Node.js and Python examples. We'll also cover the parts most tutorials skip: minimum input length, error handling, keeping your API key safe and showing results responsibly.
We'll use the ProofAI API because it's what we build, but the patterns apply to any detection provider.
POST https://ai.proofai.in/api/v1/detect Content-Type: application/x-www-form-urlencoded content=<the text to analyze> Enter fullscreen mode Exit fullscreen mode A successful response looks like this:
{ "ai_probability": 85, "human_probability": 15, "final_probability": 85, "verdict": "Likely AI", "input_type": "text", "model_version": "v1.0", "segments": [ { "text": "...", "ai_prob": 85, "human_prob": 15, "color_label": "red", "is_data": true } ] } Enter fullscreen mode Exit fullscreen mode The segments array is useful: it lets you highlight which parts of a document look AI-generated instead of labelling the whole thing.
#.env PROOFAI_API_KEY = sk_live_your_key_here PROOFAI_ORIGIN = https://yourapp.com Enter fullscreen mode Exit fullscreen mode Step 3: Node.js (18+) example Node 18+ ships with fetch, so there's nothing to install.
// detect.js const API_URL = " https://ai.proofai.in/api/v1/detect "; const MIN_WORDS = 50; // the API docs recommend at least 50 words export async function detectAI ( text ) { const words = text. trim (). split ( / \s +/ ). filter ( Boolean ). length; if ( words < MIN_WORDS ) { return { status: " too_short ", words, minWords: MIN_WORDS }; } const res = await fetch ( API_URL, { method: " POST ", headers: { " x-api-key ": process. env. PROOFAI_API_KEY, " Origin ": process. env. PROOFAI_ORIGIN, " Content-Type ": " application/x-www-form-urlencoded ", }, body: new URLSearchParams ({ content: text }), }); if ( res. status === 429 ) { return { status: " rate_limited " }; // quota hit: retry later or queue it } if (! res. ok ) { const err = await res. text (); throw new Error ( `Detection failed ( ${ res. status } ): ${ err } ` ); } const data = await res. json (); return { status: " ok ", aiProbability: data. ai_probability, level: toConfidenceLevel ( data. ai_probability ), segments: data. segments?? [], }; } function toConfidenceLevel ( p ) { if ( p >= 85 ) return " high "; if ( p >= 60 ) return " medium "; return " low "; } Enter fullscreen mode Exit fullscreen mode And a minimal Express route that your frontend calls:
// server.js import express from " express "; import { detectAI } from "./detect.js "; const app = express (); app. use ( express. json ({ limit: " 200kb " })); app. post ( " /api/check-text ", async ( req, res ) => { try { const result = await detectAI ( String ( req. body. text?? "" )); res. json ( result ); } catch ( e ) { console. error ( e ); res. status ( 502 ). json ({ status: " error " }); } }); app. listen ( 3000, () => console. log ( " Listening on:3000 " )); Enter fullscreen mode Exit fullscreen mode Step 4: Python example # detect.py import os import requests API_URL = " https://ai.proofai.in/api/v1/detect " MIN_WORDS = 50 def detect_ai ( text: str ) -> dict: words = len ( text. split ()) if words < MIN_WORDS: return { " status ": " too_short ", " words ": words, " min_words ": MIN_WORDS } resp = requests. post ( API_URL, headers = { " x-api-key ": os. environ [ " PROOFAI_API_KEY " ], " Origin ": os. environ [ " PROOFAI_ORIGIN " ], }, data = { " content ": text }, # requests sends this as form-urlencoded timeout = 15, ) if resp. status_code == 429: return { " status ": " rate_limited " } resp. raise_for_status () data = resp. json () p = data [ " ai_probability " ] level = " high " if p >= 85 else " medium " if p >= 60 else " low " return { " status ": " ok ", " ai_probability ": p, " level ": level, " segments ": data. get ( " segments ", [])} Enter fullscreen mode Exit fullscreen mode Step 5: Handle errors like a production feature The API uses standard HTTP codes. Map each one to a clear behaviour:
For bulk jobs (for example, scanning every application submitted today), use a queue with a concurrency limit instead of firing hundreds of requests at once.
This is the most important step, and it's a product decision rather than a code one.
AI detection is probabilistic. Research has shown real false positives. A 2023 Stanford study by Liang et al. found that popular GPT detectors flagged a majority of essays written by non-native English speakers as AI-generated. So:
We'll go deeper on this UX side in the next post in this series.
You now have a server-side detection helper in Node.js and Python, with input validation, error handling and a safe way to present results. From here you can add caching for repeated texts, batch processing or a review dashboard.
馃摎 Full reference: ProofAI API documentation 馃攽 Try the detector free first (no login, 10 scans a day): proofai.in
Question for you: where would AI detection actually help in your product? Submissions, reviews, moderation or something else? Tell us in the comments. 馃憞
Disclosure: we're the team behind ProofAI at 4Born Solutions. This article was drafted with AI assistance and reviewed and edited by our team.