NeverPrompted
For machines

JSON API

The same engine the browser runs, plus any detection keys this deployment holds that cannot be shipped to a browser. Metered at 2p per 1,000 words, rounded-[var(--radius-control)] up.

OpenAPI 3.1 document · pricing.json · Get a key

Authentication

Pass your key as a bearer token. Keys are created in the dashboard, stored only as a SHA-256 hash, and shown once.

Authorization: Bearer mw_live_...

POST /api/v1/check

curl -X POST https://www.neverprompted.com/api/v1/check \
  -H "Authorization: Bearer $WATERMARKREMOVERPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The text you want to check...",
    "language": "en",
    "granularity": "sentence"
  }'

language is optional. Omit it and the engine identifies it, or returns language_undetermined rather than guessing. Supported: en, es, fr, de, pt.

POST /api/v1/calibrate

The lighter, deterministic layer behind the on-device rewrite engine: suggests word-frequency substitutions with before/after metrics, rather than producing a finished, targeted rewrite. Authentication is optional, as with /check; an anonymous call is capped at the no-account word limit rather than a tracked monthly allowance.

curl -X POST https://www.neverprompted.com/api/v1/calibrate \
  -H "Authorization: Bearer $WATERMARKREMOVERPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The text you want to calibrate...",
    "language": "en",
    "mode": "preview",
    "config": {
      "excludedWords": ["NeverPrompted", "on-device AI detector"]
    }
  }'

mode is preview (the default, returns suggested substitutions without applying them) or apply (returns the calibrated text). config.excludedWords lists words or phrases this call must never substitute, matched case-insensitively as whole words or phrases: useful for SEO keywords, product names or other terms that need to survive calibration unchanged. A substitution skipped for this reason is reported back with reason: "excluded" rather than silently omitted.

Reading the response

Every statistic is either a number or null. Null means the value was not computed, and the sibling status and detail fields say why. Rendering null as zero would turn “we could not measure this” into “we measured this and found nothing”, which are very different claims to make about someone’s document.

{
  "result": {
    "status": "ok",
    "documentHash": "9f2c...",           // SHA-256 of the exact text
    "watermark": {
      "keysTested": [ { "id": "openmark-ref-1", "vendorPublished": false } ],
      "results": [ {
        "status": "computed",
        "trials": 412,                   // distinct word pairs, repeats counted once
        "greenRate": 0.508,
        "greenRateInterval": { "low": 0.460, "high": 0.556 },
        "expectedGreenRate": 0.5,
        "z": 0.32,
        "pValue": 0.374
      } ],
      "anyDetected": false,
      "coverageNotice": "Tested against 1 key ... no vendor publishes one ..."
    },
    "distribution": { "status": "computed", "compositeDeviation": 1.42, ... },
    "passages": [ ... ],
    "passageCorrection": { "method": "benjamini-hochberg", "tested": 34, "survived": 0 },
    "limits": [ "A detected mark is not proof of authorship.", ... ]
  },
  "billing": { "words": 812, "billableUnits": 1, "pence": 2, "currency": "GBP" }
}

coverageNotice and limits are part of the result, not decoration. If you surface this data to a user, surface those too, because a null watermark result quoted without its coverage notice says something the measurement does not support.

Status codes

  • 200Analysis complete. Note that a successful call can still carry a result whose status is language_undetermined , because the request worked and the measurement declined.
  • 400Body was not valid JSON, or failed validation. issues names the fields.
  • 401Missing, unknown or revoked key.
  • 402Outside your plan allowance. The message names the exact limit reached and when it resets.
  • 503This deployment has no metering ledger, so metered access cannot be granted. It refuses rather than serving unmetered.

What this API does not offer

/calibrate above is the lighter, deterministic layer: word-frequency substitutions with before/after metrics, not a finished, targeted rewrite. There is no endpoint or parameter, on any plan, that runs the fuller rewrite engine over this REST API. That is a deliberate omission, not a missing feature: the targeted rewrite is on-device only, on every tier, and a REST endpoint that accepted your document text for it would break that guarantee. Call it instead via the MCP server's reduce_ai_evidence tool, or the published local package/CLI, both of which run in your own process and never transmit the document.