import { APIResource } from "../core/resource.mjs"; import { APIPromise } from "../core/api-promise.mjs"; import { RequestOptions } from "../internal/request-options.mjs"; export declare class Content extends APIResource { /** * Open a WebSocket to moderate live voice/call audio in real time. Speech is * transcribed and each finalized utterance is moderated by your enabled text * policies; you receive a verdict per utterance as it's spoken. * * **This is a WebSocket upgrade, not a regular HTTP call.** The request body below * documents the frames you _send_ over the socket; the `101` response documents * the events you _receive_. * * - **Auth:** `Authorization: Bearer ` on the upgrade. A missing/invalid * key closes `4401`; voice not enabled on the plan/channel closes `4403`. * - **Subprotocol:** request `moderationapi.v1`. * - **Flow:** send one `start` frame, then `media` frames as audio arrives, then * `stop` (or disconnect). You receive `session.started`, `utterance.final` per * utterance, optional `utterance.partial`/`warning`, and `session.ended`. * - **Close codes:** `1000` normal · `1011` server error · `4400` bad request · * `4401` auth failed · `4403` voice not enabled · `4429` concurrency limit. * * See the * [Real-time voice guide](https://docs.moderationapi.com/content-moderation/real-time-voice) * for the full walkthrough and code examples. */ stream(params: ContentStreamParams, options?: RequestOptions): APIPromise; submit(body: ContentSubmitParams, options?: RequestOptions): APIPromise; } export interface ContentSubmitResponse { /** * The author of the content if your account has authors enabled. Requires you to * send authorId when submitting content. */ author: ContentSubmitResponse.Author | null; /** * What your casebook — the record of your past moderation decisions — found for * this content, or null when it had nothing close enough to say, when the matching * cases disagreed, or when casebook lookups are not switched on for this channel. * Reports what the casebook found; whether it decided the outcome is shown in * `recommendation`, where a higher-priority rule may have settled the item first. */ casebook: ContentSubmitResponse.Casebook | null; /** * Potentially modified content. */ content: ContentSubmitResponse.Content; /** * The evaluation of the content after running the channel policies. */ evaluation: ContentSubmitResponse.Evaluation; /** * Results of all insights enabled in the channel. */ insights: Array; /** * Metadata about the moderation request */ meta: ContentSubmitResponse.Meta; /** * Results of all policies in the channel. Sorted by highest probability. */ policies: Array; /** * The recommendation for the content based on the evaluation. */ recommendation: ContentSubmitResponse.Recommendation; /** * Policies that had errors */ errors?: Array; } export declare namespace ContentSubmitResponse { /** * The author of the content if your account has authors enabled. Requires you to * send authorId when submitting content. */ interface Author { /** * Author ID in Moderation API */ id: string; /** * Block or suspension details, if applicable. Null if the author is enabled. */ block: Author.Block | null; /** * Current author status */ status: 'enabled' | 'suspended' | 'blocked'; trust_level: Author.TrustLevel; /** * The author's ID from your system */ external_id?: string | null; } namespace Author { /** * Block or suspension details, if applicable. Null if the author is enabled. */ interface Block { /** * The moderators reason why the author was blocked or suspended. */ reason?: string | null; /** * The timestamp until which they are blocked if the author is suspended. */ until?: number | null; } interface TrustLevel { /** * Author trust level (-1, 0, 1, 2, 3, or 4) */ level: number; /** * True if the trust level was set manually by a moderator */ manual: boolean; } } /** * What your casebook — the record of your past moderation decisions — found for * this content, or null when it had nothing close enough to say, when the matching * cases disagreed, or when casebook lookups are not switched on for this channel. * Reports what the casebook found; whether it decided the outcome is shown in * `recommendation`, where a higher-priority rule may have settled the item first. */ interface Casebook { /** * How unanimous the matching cases are, from 0 to 1: the share of them that * decided this way, ignoring how many there are. Always at least 0.8 when a ruling * is returned — below that the casebook reports a disagreement instead of picking * a side — so it tells you how clean the consensus was, and is not a threshold to * re-apply yourself. */ agreement: number; /** * How many of your past cases backed this ruling. */ case_count: number; /** * How strongly the casebook holds this ruling, from 0 to 1: the agreement scaled * by how much evidence backs it, so a handful of close, recent cases outweighs one * distant one. Older cases count for less, halving in weight roughly every 180 * days. This is the number to use in rules when you want a strength condition. */ confidence: number; /** * How close the nearest matching case is, from 0 to 1. 1 means the content is * identical to something you have already decided. */ similarity: number; /** * The topic the closest matching case is filed under, or null when it has not been * grouped into one yet. */ topic: Casebook.Topic | null; /** * The ruling your past decisions point to for this content. */ verdict: 'allow' | 'reject'; } namespace Casebook { /** * The topic the closest matching case is filed under, or null when it has not been * grouped into one yet. */ interface Topic { id: string; label: string; } } /** * Potentially modified content. */ interface Content { /** * The unique identifier for the content. Either the contentId provided by you or * an autogenerated ID. */ id: string; /** * Whether any values have been masked. */ masked: boolean; /** * The modified content, if any. */ modified: string | { [key: string]: unknown; } | { [key: string]: Content.Text | Content.Image | Content.Video | Content.Audio; } | null; /** * Whether Unicode spoofing normalization rewrote the content — confusables folded * to their Latin lookalikes, invisible characters and combining-mark abuse * stripped. */ unicode_cleaned: boolean; /** * The transcribed text from audio content. Only present when audio moderation is * used and transcript inclusion is enabled on the channel. */ transcript?: string | null; } namespace Content { /** * Text */ interface Text { /** * The content text */ text: string; type: 'text'; } /** * Image */ interface Image { type: 'image'; /** * Base64-encoded image data. Either url or data must be provided. Note: base64 * images are not stored and will not appear in the review queue. */ data?: string; /** * A public URL of the image content. Either url or data must be provided. */ url?: string; } /** * Video */ interface Video { type: 'video'; /** * A public URL of the video content */ url: string; } /** * Audio */ interface Audio { type: 'audio'; /** * The URL of the audio content */ url: string; } } /** * The evaluation of the content after running the channel policies. */ interface Evaluation { /** * The probability that the content should be flagged. */ flag_probability: number; /** * Whether the content was flagged by any policy. */ flagged: boolean; /** * The severity score of the content. A higher score indicates more severe content. */ severity_score: number; /** * Whether the content would have been flagged by analyze-only policies (flag: * false). */ shadow_flagged?: boolean; /** * Whether the content was flagged for Unicode spoofing. */ unicode_spoofed?: boolean; } /** * Sentiment insight */ interface SentimentInsight { id: 'sentiment'; probability: number; type: 'insight'; value: 'positive' | 'neutral' | 'negative' | null; } /** * Language insight */ interface LanguageInsight { id: 'language'; probability: number; type: 'insight'; value: string | null; } /** * Metadata about the moderation request */ interface Meta { /** * The unique key of the channel where the content was handled. Either the channel * provided by you or automatically routed. */ channel_key: string; status: 'success' | 'partial_success'; timestamp: number; usage: number; processing_time?: string; } /** * Classifier policy. */ interface ClassifierOutput { /** * The unique identifier for the classifier output. */ id: string; flagged: boolean; probability: number; type: 'classifier'; /** * Optional structured data produced by the policy. For face detection: { count, * faces: [{ confidence, gender, age }] }. */ data?: { [key: string]: unknown; }; /** * The keys of the flagged fields if submitting an object. */ flagged_fields?: Array; labels?: Array; } namespace ClassifierOutput { interface Label { id: string; flagged: boolean; probability: number; shadowFlagged?: boolean; } } /** * Entity matcher policy. */ interface EntityMatcherOutput { id: string; flagged: boolean; matches: Array; probability: number; type: 'entity_matcher'; flagged_fields?: Array; } namespace EntityMatcherOutput { interface Match { match: string; probability: number; span: Array; /** * Sub-type of the entity match — e.g. the NER key (email, phone, name, …) for PII * matches. Absent for URL Risk and wordlist matches where the type is already * encoded in the parent label. */ entity_type?: string; /** * Stable codes explaining why a URL was flagged (URL Risk only). */ reasons?: Array; /** * Observable properties of a URL (URL Risk only). Absent for allow/block list * matches. */ signals?: Match.Signals; } namespace Match { /** * Observable properties of a URL (URL Risk only). Absent for allow/block list * matches. */ interface Signals { bot_protection: boolean | null; brand_impersonation: Signals.BrandImpersonation | null; domain_age_days: number | null; final_url: string | null; has_email_setup: boolean | null; has_suspicious_characters: boolean; is_link_shortener: boolean; is_reported: boolean; redirect_count: number | null; } namespace Signals { interface BrandImpersonation { brand: string; method: 'registered_domain_token' | 'subdomain_token'; } } } } /** * The recommendation for the content based on the evaluation. */ interface Recommendation { /** * The action to take based on the recommendation */ action: 'review' | 'allow' | 'reject'; /** * Reason codes for the recommendation. Standard codes plus a `rule:` code * identifying the rule that produced the action. Can be used to display a reason * to the user. */ reason_codes: Array<'severity_reject' | 'severity_review' | 'author_block' | 'dry_run' | 'trusted_allow' | 'untrusted_severity' | 'rule_match' | 'rule_default' | 'rule_fallback' | 'client_override' | 'casebook_match' | (string & {})>; /** * Rules that matched during evaluation, if rules engine is active. */ matched_rules?: Array; } namespace Recommendation { interface MatchedRule { key: string; name: string; } } interface Error { id: string; message: string; } } export interface ContentStreamParams { /** * Requested subprotocol. */ 'Sec-WebSocket-Protocol': 'moderationapi.v1'; } export interface ContentSubmitParams { /** * The content sent for moderation */ content: ContentSubmitParams.Text | ContentSubmitParams.Image | ContentSubmitParams.Video | ContentSubmitParams.Audio | ContentSubmitParams.Object; /** * The author of the content. */ authorId?: string; /** * Provide a channel ID or key. Will use the project's default channel if not * provided. */ channel?: string; /** * A recommendation from your own client-side flagging (e.g. a banned-IP list or a * third-party tool). Feeds the rules engine and can escalate or override the * recommended action. Does not change whether our analysis flagged the content. */ clientAction?: ContentSubmitParams.ClientAction; /** * The unique ID of the content in your database. */ contentId?: string; /** * For example the ID of a chat room or a post */ conversationId?: string; /** * Do not store the content. The content won't enter the review queue */ doNotStore?: boolean; /** * Any metadata you want to store with the content */ metadata?: { [key: string]: unknown; }; /** * The meta type of content being moderated */ metaType?: 'profile' | 'message' | 'post' | 'comment' | 'event' | 'product' | 'review' | 'voice' | 'other'; /** * (Enterprise) override the channel policies for this moderation request only. */ policies?: Array; /** * Unix timestamp (in milliseconds) of when the content was created. Use if content * is not submitted in real-time. */ timestamp?: number; } export declare namespace ContentSubmitParams { /** * Text */ interface Text { /** * The content text */ text: string; type: 'text'; } /** * Image */ interface Image { type: 'image'; /** * Base64-encoded image data. Either url or data must be provided. Note: base64 * images are not stored and will not appear in the review queue. */ data?: string; /** * A public URL of the image content. Either url or data must be provided. */ url?: string; } /** * Video */ interface Video { type: 'video'; /** * A public URL of the video content */ url: string; } /** * Audio */ interface Audio { type: 'audio'; /** * The URL of the audio content */ url: string; } /** * Object */ interface Object { /** * Values in the object. Can be mixed content types. */ data: { [key: string]: Object.Text | Object.Image | Object.Video | Object.Audio; }; type: 'object'; } namespace Object { /** * Text */ interface Text { /** * The content text */ text: string; type: 'text'; } /** * Image */ interface Image { type: 'image'; /** * Base64-encoded image data. Either url or data must be provided. Note: base64 * images are not stored and will not appear in the review queue. */ data?: string; /** * A public URL of the image content. Either url or data must be provided. */ url?: string; } /** * Video */ interface Video { type: 'video'; /** * A public URL of the video content */ url: string; } /** * Audio */ interface Audio { type: 'audio'; /** * The URL of the audio content */ url: string; } } /** * A recommendation from your own client-side flagging (e.g. a banned-IP list or a * third-party tool). Feeds the rules engine and can escalate or override the * recommended action. Does not change whether our analysis flagged the content. */ interface ClientAction { /** * Your recommendation for the content: allow, review, or reject. */ action: 'review' | 'allow' | 'reject'; /** * How your recommendation combines with ours. Defaults to 'escalate', which only * applies it when stricter than ours; 'override' replaces ours outright. */ behavior?: 'override' | 'escalate'; /** * A human-readable explanation for your recommendation. */ reason?: string; /** * Where your recommendation came from, e.g. "banned-ip". */ source?: string; } interface Toxicity { id: 'toxicity'; flag: boolean; threshold?: number; } interface PersonalInformation { id: 'personal_information'; flag: boolean; threshold?: number; } interface ToxicitySevere { id: 'toxicity_severe'; flag: boolean; threshold?: number; } interface Hate { id: 'hate'; flag: boolean; threshold?: number; } interface Illicit { id: 'illicit'; flag: boolean; threshold?: number; } interface IllicitDrugs { id: 'illicit_drugs'; flag: boolean; threshold?: number; } interface IllicitAlcohol { id: 'illicit_alcohol'; flag: boolean; threshold?: number; } interface IllicitFirearms { id: 'illicit_firearms'; flag: boolean; threshold?: number; } interface IllicitTobacco { id: 'illicit_tobacco'; flag: boolean; threshold?: number; } interface IllicitGambling { id: 'illicit_gambling'; flag: boolean; threshold?: number; } interface Cannabis { id: 'cannabis'; flag: boolean; threshold?: number; } interface Adult { id: 'adult'; flag: boolean; threshold?: number; } interface Crypto { id: 'crypto'; flag: boolean; threshold?: number; } interface Sexual { id: 'sexual'; flag: boolean; threshold?: number; } interface SexualMinors { id: 'sexual_minors'; flag: boolean; threshold?: number; } interface Flirtation { id: 'flirtation'; flag: boolean; threshold?: number; } interface Profanity { id: 'profanity'; flag: boolean; threshold?: number; } interface Violence { id: 'violence'; flag: boolean; threshold?: number; } interface SelfHarm { id: 'self_harm'; flag: boolean; threshold?: number; } interface Spam { id: 'spam'; flag: boolean; threshold?: number; } interface LowQualityContent { id: 'low_quality'; flag: boolean; /** * Flag content with fewer than this many words as low-effort. Defaults to 3. Set * to disable by omitting. */ minWords?: number; threshold?: number; } interface FaceDetection { id: 'face_detection'; flag: boolean; /** * Flag images that contain "at least" or "fewer than" the configured number of * faces. Defaults to at_least. */ comparator?: 'at_least' | 'fewer_than'; /** * Number of faces the comparator applies to. Defaults to 1, so the default rule * flags any image containing a face. */ count?: number; threshold?: number; } interface SelfPromotion { id: 'self_promotion'; flag: boolean; threshold?: number; } interface Political { id: 'political'; flag: boolean; threshold?: number; } interface Religion { id: 'religion'; flag: boolean; threshold?: number; } interface CodeAbuse { id: 'code_abuse'; flag: boolean; threshold?: number; } interface UnicodeSpoofing { id: 'unicode_spoofing'; flag: boolean; /** * Per-signal flag toggles. Omitted spoofing signals are enabled; encoding_damage * defaults to off because decode damage (U+FFFD) marks a broken pipeline, not an * attack. A disabled signal is still detected and reported as a label, but does * not by itself flag the policy. */ signals?: { [key: string]: UnicodeSpoofing.Signals; }; threshold?: number; } namespace UnicodeSpoofing { interface Signals { flag?: boolean; } } interface PiiMasking { id: 'pii'; entities: { [key: string]: PiiMasking.Entities; }; } namespace PiiMasking { interface Entities { enable?: boolean; flag?: boolean; mask?: string; shouldMask?: boolean; [k: string]: unknown; } } interface URLMasking { id: 'url'; entities: { [key: string]: URLMasking.Entities; }; } namespace URLMasking { interface Entities { enable?: boolean; flag?: boolean; mask?: string; shouldMask?: boolean; [k: string]: unknown; } } interface URLRisk { id: 'url_risk'; flag: boolean; /** * IDs of wordlists whose entries are treated as allowed URL domains. Matches * short-circuit the risk model and are never flagged. */ allowlistWordlistIds?: Array; /** * IDs of wordlists whose entries are treated as blocked URL domains. Matches * short-circuit the risk model and are always flagged. Blocklists take precedence * over allowlists. */ blocklistWordlistIds?: Array; /** * When true, any URL detected as a free link shortener (bit.ly, t.co, tinyurl, * etc.) is always flagged regardless of risk score. Allowlist matches still win. */ flagLinkShorteners?: boolean; threshold?: number; } interface Guideline { id: 'guideline'; flag: boolean; guidelineKey: string; instructions: string; threshold?: number; } } export declare namespace Content { export { type ContentSubmitResponse as ContentSubmitResponse, type ContentStreamParams as ContentStreamParams, type ContentSubmitParams as ContentSubmitParams, }; } //# sourceMappingURL=content.d.mts.map