Skip to content
StatusSupportDashboard

Classify content

POST/v1/content

Classify a piece of content synchronously. Send text and image parts and receive per-label results in the response. Any metadata you send is echoed back on the response, so a decision can be matched to your own request without a side lookup. Requests have a maximum size of 6MB. API version 2026-08-11; see the API versioning guide for superseded versions.

Errors: 400 for an invalid body or images, with the failing field in the message. 401 for a missing or invalid API key. 413 for requests over 6MB. 429 when too many requests are in flight for your account, with a Retry-After header. 503 when classification is temporarily unavailable. In both cases the request was not processed and is safe to retry.

Header ParametersExpand Collapse
"SafetyKit-Version": optional "2026-08-11"

The API version this operation is defined against.

Body ParametersJSONExpand Collapse
content: array of object { text, type, key } or object { source, type, key }

Content parts to classify together. At most 20 images. Text parts may total 128,000 characters. Text is classified in overlapping windows and a label matches when any window matches.

One of the following:
object { text, type, key }
text: string

User-authored text to classify. At most 16,000 characters per part.

maxLength16000
type: "text"
key: optional string

Your name for where this part came from.

maxLength256
object { source, type, key }
source: object { data, type }
data: string

Base64-encoded image bytes, raw or as a data URI. At most 5MB.

minLength1
type: "base64"
type: "image"
key: optional string

Your name for where this part came from.

maxLength256
user_id: string

Your stable identifier for the user this content belongs to.

minLength1
maxLength512
content_id: optional string

Your content identifier.

minLength1
maxLength512
metadata: optional map[unknown]

Additional product context for this content, echoed back unchanged on the response. At most 8KB when serialized.

ReturnsExpand Collapse
content_id: string

SafetyKit identifier for the classified content.

labels: array of object { decision, escalation, label, 2 more } or object { decision, escalation, label, 3 more }

Per-label results for the submitted content.

One of the following:
object { decision, escalation, label, 2 more }
decision: "match" or "not_match" or "review"

Whether the submitted content matches the label.

One of the following:
"match"
"not_match"
"review"
escalation: "none" or "completed" or "error"

Escalation outcome for this label.

One of the following:
"none"
"completed"
"error"
label: string

Label identifier.

score: number

Classifier score between 0 and 1. Higher means more likely matching. Null when no classifier scored the label.

type: "classifier"
object { decision, escalation, label, 3 more }
decision: "match" or "not_match" or "review"

Whether the submitted content matches the label.

One of the following:
"match"
"not_match"
"review"
escalation: "none" or "completed" or "error"

Escalation outcome for this label.

One of the following:
"none"
"completed"
"error"
label: "reference_set_match"
score: number

Similarity between the submitted content and the matched entry.

set_id: string

Identifier of the matched reference set.

type: "similarity"
user_id: string

The user_id from the request.

version: string

The API version that served this request.

metadata: optional map[unknown]

The metadata from the request, echoed back unchanged. Absent when the request sent none.

Classify content

curl https://api.safetykit.com/v1/content \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $SAFETYKIT_API_KEY" \
    -d '{
          "content": [
            {
              "text": "Hey, is this still available?",
              "type": "text"
            }
          ],
          "user_id": "user_123",
          "content_id": "post_42",
          "metadata": {
            "channel": "bar"
          }
        }'
{
  "content_id": "post_42",
  "labels": [
    {
      "decision": "not_match",
      "escalation": "none",
      "label": "hate_speech",
      "score": 0.12,
      "type": "classifier"
    }
  ],
  "user_id": "user_123",
  "version": "2026-08-11",
  "metadata": {
    "channel": "bar"
  }
}
Returns Examples
{
  "content_id": "post_42",
  "labels": [
    {
      "decision": "not_match",
      "escalation": "none",
      "label": "hate_speech",
      "score": 0.12,
      "type": "classifier"
    }
  ],
  "user_id": "user_123",
  "version": "2026-08-11",
  "metadata": {
    "channel": "bar"
  }
}