Content Intelligence
Evaluate user-generated content against your platform rules and get a structured moderation recommendation.
Endpoint
POST https://kovca.io/api/v1/content/moderateAuthenticate with your API key in the Authorization: Bearer header. Send JSON with Content-Type: application/json; bodies are limited to 16 KB.
The API evaluates one piece of content against a small set of default categories and the rules you send. It blocks only when your own rules or block_categories support it; default categories alone never block. A category describes the text, never the author's intent or real-world behavior. Content is not stored, and the API never publishes, deletes, or suspends anything.
Request body
| Field | Type | Description |
|---|---|---|
| content | string, required | The text to evaluate, up to 5,000 characters. Treated as data: instructions inside it are ignored. |
| content_type, context | string, optional | For example product_review and "Marketplace product reviews". |
| categories | string[], optional | Which default categories to check. Defaults to all: spam, harassment, threats, sexual_content, violent_content, prohibited_promotion. |
| policy.disallowed | string[], optional | Up to 20 rules in plain language. |
| policy.allowed | string[], optional | Up to 20 things explicitly permitted, such as "Negative reviews of products". Considered for every check. |
| policy.block_categories | string[], optional | Default categories that should block when likely. Others are held for review. |
Example request
{
"content": "Great blender but you can get it 40% cheaper at bestdeals-example.shop, just message me on WhatsApp +1 555 0100.",
"content_type": "product_review",
"context": "Marketplace product reviews",
"policy": {
"disallowed": [
"Links or contact details that take buyers off the platform",
"Reviews of a different product than the one listed"
],
"allowed": [
"Negative reviews and criticism of products or service"
],
"block_categories": [
"spam",
"threats",
"harassment"
]
}
}Response
200 OK
{
"request_id": "req_Lt6qN3wRv8KzM1pY",
"decision": "block",
"recommended_action": "block_submission",
"categories": [
{
"category": "spam",
"assessment": "likely"
},
{
"category": "policy_violation",
"assessment": "likely"
}
],
"policy_matches": [
{
"rule": "Links or contact details that take buyers off the platform",
"source": "policy.disallowed[0]",
"assessment": "likely"
}
],
"signals": [
"custom_rule_matched"
]
}| Field | Type | Description |
|---|---|---|
| request_id | string | Unique ID for this request. |
| decision | "allow" | "review" | "block" | "insufficient_information" | See below. |
| recommended_action | "publish" | "hold_for_review" | "block_submission" | "request_information" | publish, hold_for_review, block_submission, or request_information. |
| categories | object[] | { category ("spam" | "harassment" | "threats" | "sexual_content" | "violent_content" | "prohibited_promotion" | "policy_violation" | "other"), assessment ("likely" | "possible") }. policy_violation is added when a disallowed rule matches. |
| policy_matches | object[] | Your disallowed rules that matched: { rule (quoted exactly), source, assessment }. |
| signals | "default_criteria_only" | "custom_rule_matched" | "ambiguous" | "too_short_to_evaluate"[] | default_criteria_only means no custom rules or block_categories were sent. |
Decisions (first match wins)
insufficient_information: Fewer than 3 letters or digits. Action: request_information.block: A likely match on a concrete disallowed rule, or a likely category listed in block_categories. Action: block_submission.review: Any other match, including likely default categories you didn't list in block_categories, and any possible match. Action: hold_for_review.allow: Nothing matched. Action: publish.
Default categories
spam: Unsolicited bulk or repetitive promotion, link bait, scams, or text unrelated to the context posted to drive traffic.harassment: Personal attacks, slurs, or degrading language aimed at someone.threats: A statement of intent to hurt, attack, or damage, including veiled threats.sexual_content: Explicit sexual descriptions or solicitation.violent_content: Graphic descriptions of injury or death, or praise of violent acts.prohibited_promotion: It offers, advertises, or solicits illegal goods or services.
Criticism without a policy
Request
{
"content": "This company's support team is useless. I waited three weeks and nobody fixed my account. Avoid.",
"content_type": "product_review"
}Code
curl https://kovca.io/api/v1/content/moderate \
-H "Authorization: Bearer $KOVCA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Great blender but you can get it 40% cheaper at bestdeals-example.shop, just message me on WhatsApp +1 555 0100.",
"content_type": "product_review",
"context": "Marketplace product reviews",
"policy": {
"disallowed": [
"Links or contact details that take buyers off the platform",
"Reviews of a different product than the one listed"
],
"allowed": [
"Negative reviews and criticism of products or service"
],
"block_categories": [
"spam",
"threats",
"harassment"
]
}
}'Errors
400 INVALID_REQUEST: a field is missing, too long, the wrong type, or not allowed. The message names the field.413 PAYLOAD_TOO_LARGE: the body is larger than 16 KB.401 UNAUTHORIZED,429 RATE_LIMITED,503 SERVICE_UNAVAILABLE,504 TIMEOUT: see Errors and limits.
Limitations
- Default criteria are limited to the six categories below. Anything else needs your rules.
- Subjective rules such as 'off-topic' or 'inappropriate' can send content to review but never block it on their own.
- Text only; no images, audio, or links are followed.
- Advisory: it recommends an action and never enforces it.
- Request data is processed to produce the result and is not stored by Kovca.