Sign In Get Started

Documentation

ModAPI moderates text and images over a small set of JSON/multipart endpoints. Every check returns a per-category confidence score from 0.00 to 1.00, so you decide where the line is.

Base URL:

https://api.modapi.xyz

Authentication

Send your API key as a bearer token on every request:

Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx

Each key has its own moderation toggles, set from Dashboard → API Keys → Settings: text, image, scam, context, and go_over_billing. A call to an endpoint whose toggle is off returns 403.

Text moderation

POST /v1/moderate/text

Scores a message across toxic, harassment, hate, and scam. Pass up to 5 prior messages in context for conversation-aware scoring — requires the key's context toggle.

curl -X POST https://api.modapi.xyz/v1/moderate/text \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "send btc now to claim your prize",
    "context": ["hey are you free today?"]
  }'
{
  "flagged": true,
  "confidence": { "scam": 0.90, "toxic": 0.00, "harassment": 0.00, "hate": 0.00 },
  "hash": "9f86d081884c7d65...2f4b2d",
  "cached": false,
  "latency_ms": 42,
  "route": "/v1/moderate/text"
}

Image NSFW detection

POST /v1/moderate/image

Multipart upload, field name file. Scores nudity signals from the image, up to 10MB. Requires the key's image toggle.

curl -X POST https://api.modapi.xyz/v1/moderate/image \
  -H "Authorization: Bearer $API_KEY" \
  -F "[email protected]"
{
  "flagged": false,
  "confidence": { "nudity": 0.12 },
  "hash": "e3b0c44298fc1c14...7852b855",
  "cached": true,
  "latency_ms": 3,
  "route": "/v1/moderate/image"
}

Scam image detection

POST /v1/moderate/image/scam

Multipart upload, field name file. Runs OCR on the image and scores the extracted text the same way as text moderation. Requires the key's scam toggle.

Optionally request extra signal checks via the signals form field — off by default, additive only:

curl -X POST https://api.modapi.xyz/v1/moderate/image/scam \
  -H "Authorization: Bearer $API_KEY" \
  -F "[email protected]" \
  -F "signals=qr_code" -F "signals=phone_number"

The cache key includes which signals were requested, so a plain scan and a signal-boosted scan of the same image are cached separately.

Hash lookup

GET /v1/moderate/{category}/hash/{hash}

Check whether a hash already has a cached result — without re-sending the message or re-uploading the image. Every moderation response returns a hash field; pass it back here to see if (and how) that content was scored, paying nothing for the model.

category is one of text, image, or scam, and requires that key toggle. hash is the 64-character hex SHA-256 digest from a prior response. Text and text-with-context hashes are both looked up under text.

curl https://api.modapi.xyz/v1/moderate/text/hash/9f86d081884c7d65...2f4b2d \
  -H "Authorization: Bearer $API_KEY"
{
  "category": "text",
  "hash": "9f86d081884c7d65...2f4b2d",
  "present": true,
  "confidence": { "scam": 0.90, "toxic": 0.00, "harassment": 0.00, "hate": 0.00 },
  "latency_ms": 2,
  "route": "/v1/moderate/text/hash"
}

If the hash isn't cached, present is false and confidence is null. A miss is not an error — it just means nothing has been scored under that hash yet. Note that lookups never run a model, so they don't reflect any rules, which are applied per request at moderation time.

Because a lookup is just an indexed cache read, it gets its own rate-limit budget at 5× your plan's per-minute limit, counted separately from moderation calls — so checking the cache before you submit never eats into your scoring quota.

Response format

The three moderation endpoints return the same shape:

{
  "flagged": boolean,
  "confidence": { category: 0.00–1.00, ... },
  "hash": string,
  "cached": boolean,
  "latency_ms": integer,
  "route": string,
  "annotations": { ... }   // only when a rule adds one
}

flagged is true if any category in confidence crosses its threshold (default 0.70), unless one of your rules overrides it. Categories with no signal are 0.00, not omitted. hash is the SHA-256 digest of the request — the same value you pass to hash lookup. annotations is present only when an annotate rule matched.

Rules & annotations

Rules let a key reshape its own results without you touching thresholds in code. Each rule tests one category against a threshold and takes an action when it matches. Manage them from Dashboard → Rules; how many rules a key may have depends on its plan.

Rules run in priority order after scoring; for flag/unflag, the last matching rule wins. Annotation keys are namespaced under annotations, so a rule can never overwrite a reserved field like flagged or confidence.

Caching & hashing

Every request is hashed and checked against a result cache before any model runs:

A cache hit skips OCR, the nudity model, and the LLM call entirely — you get the prior result back in a few milliseconds, marked "cached": true.

Regex fast-path

Before any model runs, text is checked against curated regex patterns per category. A high-confidence regex match (≥ 0.90) short-circuits the request — no LLM call, no added latency. Ambiguous text falls through to the language model for nuance.

Plans & rate limits

Every API key bills against either a personal plan or a workspace plan, never both:

PlanScopeActive keysRequests / minPrice
FreePersonal225€0
DeveloperPersonal5200€4.99/mo
ProPersonal10600€9.99/mo
TeamWorkspace202000€29.99/mo
EnterpriseWorkspaceCustomCustomContact us

Upgrade or manage billing from Dashboard → Billing, via Stripe or PayPal. Enterprise is provisioned manually after a sales conversation. Personal and workspace key quotas are counted independently, so a workspace's Team or Enterprise plan never raises (or lowers) the cap on your own personal keys, and vice versa.

Errors

StatusMeaning
401Missing, invalid, or revoked API key.
403That moderation type is disabled for this key, or context was sent without the context toggle enabled.
404Unknown hash-lookup category (must be text, image, or scam).
413Image larger than 10MB.
422Request failed validation (e.g. message empty, more than 5 context messages, or a malformed lookup hash).
429Rate limit exceeded for the key's plan (see Plans & rate limits). Upgrade for a higher limit.