Docs / Connect it
Connect a website or CMS
The safe way to check text from your own site. Server to server, never from the browser.
The one rule
Your API key is a password. If you call the API from JavaScript in a web page, the key is visible to anyone who opens the page's code. So the call must be made by your server. The browser only talks to your server.
- Store the key on your serverPut it in an environment variable (
PIJ_KEY), a secrets manager, or your hosting control panel. Never write it into a file that is published. - Make a small endpointCreate a route on your server, for example
/check. It receives text from your page, adds the key, and forwards it to the API withasync: true. It returns thejob_id. - Make a second endpoint for the result
/check-result?id=...asks the API for that job and passes the answer back. - Call your endpoints from the pageThe page sends text to
/check, then asks/check-resultevery 10 seconds untilstateisdone.
Node.js (Express) example
import express from "express";
const app = express();
app.use(express.json({ limit: "100kb" }));
const API = "https://api.chatniai.com";
const H = { "Authorization": "Bearer " + process.env.PIJ_KEY, "Content-Type": "application/json" };
app.post("/check", async (req, res) => {
const text = String(req.body.text || "").slice(0, 8000);
const r = await fetch(API + "/v1/check", { method: "POST", headers: H,
body: JSON.stringify({ text, async: true, user: req.user?.email }) });
res.status(r.status).json(await r.json());
});
app.get("/check-result", async (req, res) => {
const id = String(req.query.id || "").replace(/[^0-9a-f-]/gi, "");
const r = await fetch(API + "/v1/job/" + id, { headers: H });
res.status(r.status).json(await r.json());
});
app.listen(3000);
Python (Flask) example
import os, requests
from flask import Flask, request, jsonify
app = Flask(__name__)
API = "https://api.chatniai.com"
H = {"Authorization": "Bearer " + os.environ["PIJ_KEY"]}
@app.post("/check")
def check():
text = (request.json.get("text") or "")[:8000]
r = requests.post(API + "/v1/check", headers=H, json={"text": text, "async": True})
return jsonify(r.json()), r.status_code
@app.get("/check-result")
def result():
jid = "".join(c for c in request.args.get("id", "") if c in "0123456789abcdefABCDEF-")
r = requests.get(API + "/v1/job/" + jid, headers=H)
return jsonify(r.json()), r.status_code
The page side
async function checkText(text) {
const start = await (await fetch("/check", { method: "POST",
headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text }) })).json();
if (!start.job_id) throw new Error(start.message || "Could not start");
for (let i = 0; i < 90; i++) {
await new Promise(r => setTimeout(r, 10000));
const j = await (await fetch("/check-result?id=" + start.job_id)).json();
if (j.state === "done") return j.result;
if (j.state === "failed") throw new Error("The check failed. Try again.");
}
throw new Error("Took too long.");
}
Before you show itShow
claims[].text and claims[].disclosure together. Never show a claim whose status is not_yet_confirmed as a finding.About CORS errorsIf your page gets a CORS error when it calls
api.chatniai.com directly, that is the API telling you not to. Call your own server instead.