@modsentry/sdk
v1.0.3
Published
Official JavaScript SDK for ModSentry moderation APIs
Readme
@modsentry/sdk
Official JavaScript SDK for ModSentry moderation APIs.
Install
npm install @modsentry/sdkQuick start
import { ModsentryClient } from '@modsentry/sdk';
const client = new ModsentryClient({
apiKey: process.env.MODSENTRY_API_KEY!,
});
const result = await client.moderateMessage({
sessionId: 'gaming_room_1',
userId: 'user123',
message: 'hello everyone',
});
console.log(result.decision);Setup options (client config)
new ModsentryClient(options) supports the following options:
| Option | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| apiKey | string | Yes | - | Required ModSentry API key. Sent as x-api-key header. |
| baseUrl | string | No | https://modsentry.appleberry.my | If protocol is omitted (for example modsentry.appleberry.my), SDK prepends https://. |
| withCredentials | boolean | No | false | Pass-through to Axios withCredentials. |
| headers | Record<string, string> | No | {} | Extra default headers for all requests. |
| timeoutMs | number | No | 30000 | Request timeout in milliseconds. |
Example with all options:
import { ModsentryClient } from '@modsentry/sdk';
const client = new ModsentryClient({
apiKey: process.env.MODSENTRY_API_KEY!,
baseUrl: 'https://staging.modsentry.appleberry.my',
withCredentials: false,
headers: {
'x-request-source': 'my-web-app',
},
timeoutMs: 45000,
});Rotate key at runtime:
client.setApiKey(process.env.MODSENTRY_API_KEY_ROTATED!);API methods and payload options
moderateMessage(payload)
const res = await client.moderateMessage({
sessionId: 'webinar_2026_march', // required
userId: 'user_123', // required
message: 'message text', // required
messageId: 'msg_001', // optional
metadata: { room: 'main' }, // optional
clientTs: new Date().toISOString()// optional
});Payload fields:
sessionId: string(required)userId: string(required)message: string(required)messageId?: stringmetadata?: Record<string, unknown>clientTs?: string(ISO timestamp recommended)
moderateBatch(payload)
const batch = await client.moderateBatch({
messages: [
{ sessionId: 's1', userId: 'u1', message: 'hello' },
{ sessionId: 's1', userId: 'u2', message: 'buy now!!!' }
]
});Payload fields:
messages: ModerateMessageDto[](required)
getSessionSettings(sessionId)
const settings = await client.getSessionSettings('gaming_room_1');Arguments:
sessionId: string(required)
updateSessionSettings(sessionId, payload)
const updated = await client.updateSessionSettings('gaming_room_1', {
mode: 'SLOW'
});Arguments:
sessionId: string(required)payload.mode: 'OPEN' | 'SLOW' | 'APPROVAL_ONLY' | 'OFF'(required)
Response types
moderateMessage and each item in moderateBatch.results return:
decision: 'ALLOW' | 'BLOCK' | 'MUTE' | 'SHADOW_MUTE' | 'REVIEW'reasons: string[]sanitizedText: stringactions:strikeDelta: numberstrikeCount: numbermutedUntil: string | nullshadowMutedUntil: string | nullbanUntil: string | nullcooldownMs: number
eventId: string
Moderation decision meanings
ALLOW: message passed moderation checks and is allowed.BLOCK: hard deny for a message. Also used when a user is currently banned.REVIEW: message is flagged for manual review flow.MUTE: user is currently muted (temporary user-level restriction).SHADOW_MUTE: user is currently shadow-muted (user can continue posting, but messages are intended to be hidden from others).
Important behavior notes:
BLOCKis primarily a message-level outcome.MUTEandSHADOW_MUTEare user-state restrictions that apply over time.- There is a moderator
banaction in dashboard APIs, but moderation events still store/show the decision asBLOCK(with reasons such asUSER_BANNEDorESCALATED_BAN).
How users become MUTE or SHADOW_MUTE
There are two paths:
- Automatic escalation from strikes
- The moderation pipeline adds strikes for rule hits such as
HTML_DETECTED,RATE_LIMIT, profanity/blocked-term hits, harassment heuristic hits, and OpenAI moderation flagged hits. - When strike count crosses threshold, the system applies timed restrictions:
LOWsensitivity: mute at5, shadow-mute at8, ban at12MEDsensitivity: mute at3, shadow-mute at5, ban at8HIGHsensitivity: mute at2, shadow-mute at3, ban at5
- Default restriction durations (configurable in backend
strikePolicy):muteMinutes: 10shadowMuteMinutes: 20banMinutes: 60
- While active, incoming messages from that user resolve to
MUTEorSHADOW_MUTE.
- Manual moderator action (dashboard API)
- Dashboard actions can apply
muteorshadow-mutedirectly. - If
durationMinutesis omitted, backend defaults are:mute: 10 minutesshadow-mute: 20 minutes
- Current Portal Monitor UI sends explicit values:
mute: 15 minutesshadow-mute: 20 minutes
- Manual
unmuteclears mute/shadow/ban state and can reset strike count.
Note: dashboard moderator actions are not currently exposed as methods in this NPM SDK client.
Error handling
SDK throws ModsentryApiError for API failures:
import { ModsentryApiError } from '@modsentry/sdk';
try {
await client.moderateMessage({
sessionId: 's1',
userId: 'u1',
message: 'hello'
});
} catch (error) {
if (error instanceof ModsentryApiError) {
console.error(error.status, error.code, error.message, error.details);
} else {
console.error(error);
}
}ModsentryApiError fields:
status: numbercode?: stringmessage: stringdetails?: unknown
Environment variable example
export MODSENTRY_API_KEY="mod_live_8fd92b..."const client = new ModsentryClient({
apiKey: process.env.MODSENTRY_API_KEY!,
});Monorepo SDK generation
This package is generated from the filtered OpenAPI spec at modsentry-api/openapi/swagger.npm.json.
From repository root:
npm --prefix modsentry-api run openapi:npmRelease automation
semantic-release is configured for automated versioning and publish.
- Dry-run:
npm --prefix modsentry-npm run release:dry-run - Release:
npm --prefix modsentry-npm run release - CI workflow:
.github/workflows/publish-modsentry-sdk.yml - Required repository secret:
NPM_TOKEN
Versioning rules (Conventional Commits):
feat:-> minorfix:-> patchBREAKING CHANGE:-> major
