Reading the result
The API rates every sentence on its own. This is how to read the verdict, the shares and the positions.
Verdict
| Value | Meaning |
|---|---|
none | No signs of AI found. |
some | Some passages stand out. |
mostly | At least half of the text is in the two upper levels. |
There is deliberately no “human” class: a text without flags is not proven to be written by a person. The API returns no raw probability either.
Levels
band | Label | Meaning |
|---|---|---|
very_likely_ai | Very likely AI | The sentence carries clear patterns of a language model. |
likely_ai | Likely AI | Several sentences in a row read as machine-written. |
possibly_ai | Possibly AI | A weaker hint. It does not count towards ai_share. |
not_flagged | Not flagged | Only with all_sentences: the sentence carries no flag. It does not say who wrote the sentence. |
A flag is a hint, not proof. Show it to your users as a reason to look at the passage again.
All sentences
With "all_sentences": true, sentences holds every rated sentence in text order. Whitespace between sentences and fragments shorter than three characters belong to no entry. Sentences without a flag carry the level not_flagged. That does not mean a person wrote the sentence: the API flags strictly, a single sentence only on a very clear signal and otherwise several conspicuous sentences in a row. Verdict, shares and billing stay the same.
"sentences": [
{ "start": 0, "end": 118, "band": "not_flagged" },
{ "start": 119, "end": 247, "band": "likely_ai" },
{ "start": 248, "end": 391, "band": "likely_ai" },
{ "start": 392, "end": 470, "band": "not_flagged" }
]Use it when you show the whole text sentence by sentence or want to work with the same sentence split.
Positions
start and end count from 0; end is behind the last character. You choose the unit with offset_unit:
| Value | Counts | Fits |
|---|---|---|
codepoint | Unicode code points | Python, Go (runes), Rust (chars) |
utf16 | UTF-16 code units | JavaScript, Java, C# |
The two differ only for characters outside the basic plane, such as emojis.
Highlighting passages
parts, last = [], 0
for s in result["sentences"]:
parts.append(html.escape(text[last:s["start"]]))
parts.append(f'<mark class="{s["band"]}">{html.escape(text[s["start"]:s["end"]])}</mark>')
last = s["end"]
parts.append(html.escape(text[last:]))
marked_html = "".join(parts)let out = "", last = 0;
for (const s of result.sentences) { // request with offset_unit: "utf16"
out += escapeHtml(text.slice(last, s.start));
out += `<mark class="${s.band}">${escapeHtml(text.slice(s.start, s.end))}</mark>`;
last = s.end;
}
out += escapeHtml(text.slice(last));