Detect bullying, harassment, and intimidation in text
Analyze a message for bullying indicators including verbal abuse, social exclusion, threats, and cyberbullying patterns. Returns severity (low/medium/high/critical), bullying type classification, confidence score, and a recommended action. Risk scores are age-calibrated when context.ageGroup is provided.
Request
- Base URL: https://api.tuteliq.ai
- URL: https://api.tuteliq.ai/api/v1/safety/bullying
- Auth: one of:
- HTTP bearer
- API key in header x-api-key
Request body
The message text to analyze
Top-level alias for options.support_threshold. Minimum severity to show crisis support resources (default: high). Critical always shows.
Opaque signed token from a previous /bullying call. Carries derived analysis state — no message content is stored server-side.
Discard any continuation_token and start a fresh conversation.
Optional customer-side message id for evidence pointers.
Your unique identifier (e.g. message ID, content ID) for correlating Tuteliq results with your own system. Echoed back in the response and included in webhook payloads so you can match alerts to the original content.
Your end-customer identifier for multi-tenant / B2B2C scenarios. If you serve multiple customers (schools, apps, brands) from a single API key, set this to route webhook alerts to the correct customer. Echoed back in the response and included in webhook payloads as "customerId".
Arbitrary key-value pairs for additional context (e.g. { "channel": "discord", "region": "eu" }). Stored with the detection result, echoed in the response, and included in webhook payloads. Maximum 20 properties.
Per-call override of your account incident logging setting. When set, it takes precedence over the account-level flag for THIS request: true forces the incident to be persisted, false suppresses persistence. Omit to use your account default (which itself defaults to enabled). Lets you control incident logging per request, e.g. suppress logging for test traffic.
Response
Default Response
The speaker's relationship to the conduct described, so a report can be routed to a victim-protection queue rather than a sender-sanction one without parsing rationale prose. enacting = the speaker is bullying. experiencing = the speaker describes what was done to them. reporting_other = a bystander describing a third party's conduct, or relaying someone else's decision. self_directed = the speaker disparages only themselves. unclear = cannot be determined. Descriptive: this never changes is_bullying, severity, risk_score or recommended_action. It is the ONLY field that distinguishes the person bullying from the person being bullied, since is_bullying reports presence for both. Same vocabulary as speaker_role on /safety/coercive-control.
Whether a bullying signal is PRESENT in the content, at ANY severity (including low / monitor cases). Presence, not authorship: this is true for a child describing bullying being done TO them, exactly as it is for the person doing it. Use speaker_role to tell those apart before you act on it, or you will sanction the victim. For production branching prefer recommended_action (flag_for_review / block / immediate_intervention), which is a stable enum, over the bare presence of a signal.
Canonical vocabulary. Values outside this enum are dropped before the response is built, so this field is safe to switch on.
Routing key, weakest to strongest: none, monitor, flag_for_review, block, immediate_intervention. Safe to switch on.
Optional human-readable expansion of recommended_action for a moderator UI. Free text: do not branch on it.
Language code used for analysis (auto-detected or provided)
Language support maturity: "stable" (en) or "beta" (all others)
Number of credits consumed by this request
Signed token carrying derived analysis state for the next call. Server stores nothing.
ISO 8601 expiry timestamp of the continuation_token.
How prior state was sourced.
Conversation-level risk 0-1, distinct from risk_score which scores only this message. Anchored on the highest severity seen so far and decaying slowly across benign turns, so a friendly message after an escalation does not reset it. Absent on the first turn. Derived from the signed token: no message content is stored to produce it.
Direction of travel across the conversation so far.
Per-turn severity, oldest first — the evidence behind trajectory_risk, so a moderator can see why a benign-looking message carries elevated conversation risk.
True when a coded-term match pushed severity toward critical but this endpoint's corroboration-cap logic held recommended_action below immediate_intervention pending independent confirmation. Absent when no cap applied.
Human-readable explanation of the cap. Present only when escalation_capped is true.
True when a declared context.conversation_type would have capped an urgent action to flag_for_review and did not, because the case is acute. Absent otherwise.
Human-readable explanation. Present only when urgency_kept is true.
True when a review alert was lowered to monitor because a separate reading found a remark about how someone is playing or performing, or a reaction to what they are doing in the moment, and nothing about the person themselves: no slur, no threat, nobody else urged to act, no sign it is repeated. Also set, with its own reason, where a separate reading found something being kept from a person in order to please them (a surprise, a present), or a rough word said together with plain affection, and nothing in the message going at the person. Trash talk about play is not bullying on its own. It applies only to a flag_for_review verdict that names no threat, identity attack, pile-on or other severe type, with no earlier turns in play; anything stronger is never lowered. It never clears to none, so a pattern across a conversation stays visible. Absent unless it applied.
Human-readable explanation. Present only when passing_remark_capped is true.
True when the analysis found bullying by the speaker and asked for no action (one isolated, low-severity insult), and recommended_action was set to monitor so that it can be counted. It is not sent for review. Absent otherwise.
Human-readable explanation. Present only when single_insult_watched is true.
True when the analysis asked for nothing above monitor and a separate reading found the speaker telling of a specific person, themselves or someone they know, being repeatedly or seriously mistreated by peers, with nothing saying it has stopped. The result is sent for review as a report to route to support, not as an action against the person writing. Absent otherwise. ADVISORY: for a moderator UI and triage queues. Branch production logic on recommended_action.
Human-readable explanation. Present only when bullying_report_surfaced is true.
True when the analysis asked for nothing above monitor and a separate reading found the writer passing on, or hinting at, something about a specific person who is not there that would lower them in the eyes of others, to people other than that person. The result is sent for review as a rumour being spread. Absent otherwise. ADVISORY: for a moderator UI and triage queues. Branch production logic on recommended_action.
Human-readable explanation. Present only when rumour_spread_raised is true.
True when the analysis asked for nothing above monitor and a separate reading found a put-down about the body, weight, face or looks of the person written to or of a specific named person, whatever disclaimer or affection followed it. The result is sent for review. Absent otherwise. ADVISORY: for a moderator UI and triage queues. Branch production logic on recommended_action.
Human-readable explanation. Present only when looks_attack_raised is true.
True when the analysis asked for nothing above monitor, the text reads as a conversation, and a separate reading found that one person objected (asked the other to stop, said it hurt, asked not to be shared or repeated, or asked to be included) and the other carried on. Sent for review, never more. Absent otherwise. ADVISORY: for a moderator UI and triage queues. Branch production logic on recommended_action.
Human-readable explanation. Present only when continued_after_objection_raised is true.
True when the caller declared an adult age group but the speaker states a minor age in the message or in the earlier turns sent with it. The declared age was not used. Nothing is escalated by this on its own; the analysis runs as if no age had been sent. Worth investigating at your end: an age check that disagrees with what the user says is what a bypassed age verification looks like. A stated ADULT age never has this effect. Absent unless it applied.
Human-readable explanation. Present only when declared_age_overridden is true.
True when an alert was lowered because a separate reading found a text working against the harm it describes: teaching, moderating, counselling, reporting or asking for advice. Two outcomes. When nobody is at risk in the text and the speaker is describing someone else, nothing is detected and the action is monitor. When a person is at risk and a responsible adult in the text is already acting, an urgent action becomes flag_for_review with the severity and score brought down, and never lower. It never applies to a person speaking about their own risk, to a verdict supported by an acute marker, or when earlier turns are in play. Absent unless it applied.
Human-readable explanation, naming which of the two outcomes applied. Present only when protective_speech_capped is true.
True when an alert rested on a number that is also known as a code, and a separate reading found the number in ordinary use (an address, a count, a price, a room) with nothing else harmful in the content. The verdict was cleared. Absent when this did not happen.
Human-readable explanation. Present only when number_coincidence_cleared is true.
Echo of the external_id you provided in the request
Echo of the customer_id you provided in the request
Echo of the metadata you provided in the request
Changes
No recorded changes to this operation across all 1 revision of this API.