API reference
Base URL: https://modwall.dev. All responses are JSON. Machine-readable: openapi.json.
Authentication
The server key in the header of every request:
Authorization: Bearer sk_live_...
You create and revoke keys in the dashboard. It is a secret — keep it server-side, never in frontend code (for the browser, use the widget).
Moderate an image
/v1/moderateBody: multipart/form-data.
| Field | Type | Description |
|---|---|---|
image | file | Image (required). Alias: file. |
reference | text | An optional ID of the content on your side — it goes to the HITL queue. |
image_url | text | Optional preview URL on your infrastructure — for the HITL queue. |
Query parameter:
| Param | Description |
|---|---|
?threshold=0.8 | Overrides the block threshold for this request. The decision is then binary (allow/block), with no review band. |
200 response:
{
"scores": { "nsfw": 0.97, "safe": 0.03 },
"categories": { "nsfw": 0.97, "weapon": 0.12 }, // weapon/violence: BETA, wg profilu
"blocked_by": ["nsfw"],
"decision": "block",
"recommended_action": "block",
"mode": "enforce",
"threshold": 0.8,
"profile": "Domyślny",
"model_version": "falconsai-int8-1",
"review_id": 42 // tylko gdy decision = "review"
}
| Field | Meaning |
|---|---|
decision | The action for you, per the profile's mode: allow / review / block. In monitor mode it's always allow. |
recommended_action | The model's raw recommendation, independent of mode. In monitor it shows what modwall would do. |
categories | Score per category. nsfw always; weapon / violence (beta) only when you enable them in the key's profile. The strictest enabled category decides (per-category thresholds in the dashboard). |
blocked_by | Categories that exceeded their block threshold. |
profile | Name of the moderation profile that made the decision (you pin a profile to a key in the dashboard — a different policy per site). |
mode | The profile’s active mode: monitor / review / enforce. |
model_version | The model version that computed the score. |
We always return raw scores; decision and mode are computed according to your policy. The meaning of the decisions themselves (allow/review/block) and the mode table are in the Policy.
Moderate text
/v1/moderate-textBody: JSON { "text": "…" } (optionally reference, image_url for the queue). Requires the text or both scope on your plan. Multilingual model (understands Polish); returns raw scores and categories.
curl -X POST https://modwall.dev/v1/moderate-text \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"text":"treść do sprawdzenia"}'
{
"scores": { "unsafe": 0.94, "safe": 0.06 },
"categories": { "toxic": 0.94 },
"decision": "block",
"recommended_action": "block",
"mode": "enforce",
"threshold": 0.8,
"model_version": "xlmr-tox-int8-1"
}
unsafe is the toxicity score (multilingual, understands Polish). categories returns the model’s raw labels (currently toxic; the field is extensible for future models/categories). decision and the modes work exactly as they do for images (monitor/review/enforce).
Report content (reactive layer)
/v1/reportBody: reference (required), optionally image_url. Once the report threshold from your policy is exceeded, the content goes to the HITL queue. It does not call the model and does not count toward your limit.
{ "reference": "post-123", "reports": 2, "escalated": true }
Queue item status
/v1/review/{id}Returns the moderator’s decision for a queue item (e.g. by review_id from /v1/moderate).
{ "id": 42, "status": "approved", "reason": "score", "reference": "post-123" }
status: pending / approved / rejected.
Errors
| Code | Meaning |
|---|---|
400 | no_image / no_reference — a required field is missing. |
401 | Missing or invalid key. |
402 | quota_exceeded — plan limit exhausted (resets monthly). |
403 | capability_required — your plan doesn't cover this content type (images/text). |
413 | image_too_large — image above the size limit. |
429 | rate_limited — too many requests in a short time. |
503 | inference_unavailable — the engine is temporarily unavailable. |
Fail-open: on 503 you decide the fallback behavior — we recommend routing content to manual moderation instead of silently letting it through.