Detect LLM text watermark evidence: green-list z-test for a key you hold, plus invisible-character markers
Tests whether text carries watermark evidence, for a pipeline that must decide whether to trust or label content. Two independent checks: (1) a green-list z-test (Kirchenbauer et al. 2023) over green flags you supply, or over token ids and a key using this endpoint's own HMAC-SHA256 scheme, returning the z-score and exact binomial p-value; (2) an invisible-character scan of the text for zero-width characters, Unicode tag characters (which spell hidden ASCII), variation selectors and bidi controls, with offsets. It cannot detect a vendor watermark without that vendor's key and tokenizer, never recovers a key, and does not remove or alter anything. A pass means no evidence at this threshold, not that the text is human-written; paraphrase can erase a statistical watermark.
What you get
Cheap deterministic provenance gate before content is accepted or labelled; also catches hidden tag-character payloads that may be injected instructions.
Call it
Send the JSON body below to https://agents.writerslogic.com/api/v1/llm-watermark-detector. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.
curl -i -X POST https://agents.writerslogic.com/api/v1/llm-watermark-detector \
-H 'content-type: application/json' \
-d '{"text":"Quarterly summary: revenue rose.","greenFlags":[1,1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1]}'
Input
| Field | Type | Required | Description |
|---|---|---|---|
text | string; length 1..100000 | no | Text to scan for invisible markers. |
greenFlags | array<integer; 0..1>; max 100000 items | no | One 0/1 per scored token: 1 when your own detector's green list contains the token. Deduplicate repeated n-grams yourself if your scheme requires it. |
tokenIds | array<integer; 0..2147483647>; max 5000 items | no | Token ids in order (at most 5000). Green membership is computed from the key with the hmac-sha256-green-1 scheme; each distinct consecutive pair is scored once. |
key | string; length 1..256 | no | Secret key for tokenIds. Used for this call only and never stored or echoed. |
scheme | string; one of "hmac-sha256-green-1" | no | Scheme for tokenIds; default and only value. |
gamma | number; 0.01..0.99 | no | Expected green fraction under no watermark. Default 0.25. |
zThreshold | number; 1..10 | no | z at or above which the result is fail. Default 4 (Kirchenbauer et al.). |
minTokens | integer; 5..1000 | no | Fewer scored tokens than this is unknown. Default 25. |
Example request body
{
"text": "Quarterly summary: revenue rose.",
"greenFlags": [
1,
1,
0,
1,
1,
1,
0,
1,
1,
1,
1,
0,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
0,
1
]
}
Result
The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.
| Field | Type | Required | Description |
|---|---|---|---|
status | string; one of "pass", "fail", "unknown", "unsupported" | no | pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass. |
checksRun | array<string; one of "statistical", "invisible">; max 2 items | no | |
statistical | one of | no | |
invisible | one of | no | |
witnesses | array<object> | no | |
versions | object | no | Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile). |
limits | array<string> | no | |
deterministic | boolean | no | Always true: pure code, no model. |
Pay and connect
Available through: x402 (USDC on Base), MCP. MCP clients reach it through the context-evidence-kit package.
Machine-readable
- This agent as JSON (schemas, example, OpenAPI operation)
- Free signed sample response
- OpenAPI 3.1 · Catalog · Index of every agent