API

Check how AI-like a text reads and rewrite the passages that give it away, from your own code. The API doesn’t keep the texts you send or save them as documents.

Authentication

Create a key under Settings → API keys and send it as a bearer token. Keys are shown once; revoke one there if it leaks. All requests and responses are JSON. Call the API from your server, not from a browser. Texts aren’t saved as documents, but on a free account (no plan or bought credits) they’re kept to train and improve our models, as described in the privacy policy.

curl https://qualifical.com/api/v1/credits \
  -H "Authorization: Bearer qk_…"

Passages

Texts are scored and rewritten a passage at a time, because detectors judge short text poorly: their scores become unreliable under about 600 characters. A passage is one paragraph (one line of the text). A paragraph under 600 characters, such as a heading, joins the paragraph after it; the last one joins the paragraph before. A paragraph over 2,500 characters is split at sentence boundaries into similar-sized parts. /rewrite takes passages by their text, so you send only the ones to rewrite.

Check text

POST /api/v1/detect

Scores each passage of the text, then the whole text as the average of its passages weighted by their words. Costs a credit per word of the passages that were scored. Texts need at least 300 characters; results are more reliable above 600.

FieldTypeDescription
textstringThe text to check. Up to your account’s per-document word limit.
curl https://qualifical.com/api/v1/detect \
  -H "Authorization: Bearer qk_…" \
  -H "Content-Type: application/json" \
  -d '{"text": "When I first came to Oxford I got lost three times…"}'
{
  "aiScore": 0.49,
  "verdict": "mixed",
    "words": 162,
  "creditsCharged": 162,
  "attackDetected": false,
  "passages": [
    { "index": 0, "aiScore": 0.12, "words": 85, "start": 0, "end": 412, "text": "When I first came to Oxford…" },
    { "index": 1, "aiScore": 0.92, "words": 77, "start": 413, "end": 790, "text": "In today's rapidly evolving…" }
  ]
}
FieldTypeDescription
aiScorenumber | nullProbability the text is AI-written, from 0 to 1. Null only if no passage could be scored.
verdictstring | nullhuman below 0.3, mixed from 0.3 to 0.7, ai above 0.7.
wordsnumberWords in the text.
creditsChargednumberCredits spent: one per word of the passages that were scored.
attackDetectedbooleanHidden characters or look-alike letters that can skew detection.
passagesarrayEach passage with its index, aiScore, words, character offsets in text, and text. A passage the provider failed on has a null aiScore, and its credits are given back.

Rewrite passages

POST /api/v1/rewrite

Rewrites passages so they read less like AI, usually the ones /detect scored 0.3 or higher. Send their text; nothing else of the text is needed. Each is rewritten paragraph by paragraph: headings and other short lines that don’t end a sentence stay as they are and aren’t charged. Costs seven credits per word sent for rewriting. Prose works best: tables, lists, and other markdown may not survive.

FieldTypeDescription
passagesstring[]The text of each passage to rewrite, as it appears in your text: from /detect, or any paragraphs. 1 to 50.
tonestringacademic (default; essays, papers), professional (work writing, email), casual (posts, notes), or creative (stories, personal essays).
strengthstringlight, balanced (default), or strong: how far a rewrite may move from the wording.
curl https://qualifical.com/api/v1/rewrite \
  -H "Authorization: Bearer qk_…" \
  -H "Content-Type: application/json" \
  -d '{
    "passages": ["In today's rapidly evolving…"],
    "tone": "casual"
  }'
{
  "passages": [
    { "index": 0, "rewritten": "Nobody tells you how much of the first term is admin…" }
  ],
  "creditsCharged": 539
}
FieldTypeDescription
passagesarrayOne per passage sent, by its index in your list, with the rewritten text to put in its place, or null if it came back unchanged.
creditsChargednumberCredits spent: seven per word sent for rewriting.

A passage that comes back unchanged still costs its credits, because the model ran on it. Read rewrites before using them: one can shift the emphasis, change a term, or drop a detail.

Credits

GET /api/v1/credits

Your plan, the credits you can spend, and what each action costs per word. Credits come from the free plan’s month (free), a plan’s period (subscription), and packs you bought (purchased), each null when you have none; expiresAt is when the first of them runs out. The ones that run out soonest are spent first. freeToday is the free credits used of today’s cap since 00:00 UTC, or null without free credits.

{
  "plan": "free",
  "isPaying": true,
  "creditsPerWord": { "detect": 1, "rewrite": 7 },
  "available": 33480,
  "free": { "available": 3480, "total": 5000, "expiresAt": "2026-11-01T00:00:00.000Z" },
  "subscription": null,
  "purchased": { "available": 30000, "total": 30000, "expiresAt": "2027-10-24T09:12:00.000Z" },
  "freeToday": { "used": 1520, "limit": 2500 }
}

Errors and limits

Errors share one shape. Branch on code; message is for people.

{ "error": { "code": "INSUFFICIENT_CREDITS", "message": "This needs 1,240 credits, more than you have left." } }
CodeStatusMeaning
INVALID_INPUT400The body is missing a field or has a bad value.
TEXT_TOO_SHORT400Fewer than 300 characters to check.
UNAUTHORIZED401Missing, malformed, or revoked key.
INSUFFICIENT_CREDITS402Not enough credits left. Nothing is charged.
DOCUMENT_TOO_LONG413Over your account’s per-document word limit.
RATE_LIMITED429Over 60 requests per minute for this key.
FREE_DAILY_LIMIT429Only free credits are left, and this would pass today’s cap on them for your account. Nothing is charged; retry after 00:00 UTC.
FREE_DAILY_LIMIT_ALL429Only free credits are left, and today’s cap on free credits across all accounts is reached. Nothing is charged; retry after 00:00 UTC.
DETECTION_UNAVAILABLE503The provider failed. Credits for the failed part are given back; retry later.
REWRITE_UNAVAILABLE503Rewriting failed and its credits were given back.

Analytics

Optional Google Analytics and Google Ads cookies measure site use, purchases and ad performance. Your writing and email are never included.

Change anytime in our Privacy policy. See also our Terms.