API
For the cases a browser tab cannot cover: batch jobs, build pipelines, and anything that has to run without a person present.
Authentication
Send an API key as x-api-key. Keys are minted in the dashboard and carry their own per-minute rate limit, set by your plan. Anonymous calls work too, at 20 a day, so you can try the endpoint before signing up.
Browser clients can instead send the session bearer token from sign-in, which is what our own front end uses.
POST /v1/clean
curl https://api.removellmwatermark.com/v1/clean \
-H "content-type: application/json" \
-H "x-api-key: rlw_..." \
-d '{
"text": "Paste anything here.",
"options": { "punctuation": false },
"model": "claude/opus-5"
}'{
"ok": true,
"data": {
"text": "Paste anything here.",
"deleted": 3,
"replaced": 1,
"suspicion": 41,
"verdict": "3 invisible characters found and removed. ...",
"findings": [
{ "technique": "zero-width", "name": "ZERO WIDTH SPACE",
"codePoint": "U+200B", "count": 3, "removed": true }
],
"caveats": ["A statistical watermark ... cannot be removed by cleaning."],
"usage": { "used": 12, "limit": -1, "plan": "developer" }
}
}Decoded payloads
Both endpoints return a payloads array. Hidden characters are not always just a marker: three schemes carry actual data, and each has a fixed published mapping, so a run of them can be read back rather than merely counted. Variation-selector byte encoding, Unicode tag sequences and zero-width binary are all decoded to text. A decoded payload puts the suspicion score at 100, because it is proof of deliberate insertion rather than a stylistic habit.
There is also a whitespace array for spacing used as a carrier: inconsistent double spaces after sentences, or trailing spaces on a suspicious share of lines. Those are reported as suspicions, since a careless human produces them too.
POST /v1/detect
The same scan with no rewritten output, the report only. Use it when you want to know whether a document is marked without changing it.
Limits and errors
GET /v1/limits reports what the caller may do right now. Over the per-minute ceiling returns 429; over the daily quota or off-plan returns 402 with an upgradeUrl. Every response carries ok, so a client never has to guess whether it holds data or an error.
What we store
Counts and code-point classes, for our own usage numbers. Not the text, not a fragment of it, not a hash of it. Scan rows are deleted after 90 days.