Texts
POST /v1/text checks one text and answers with the decision. One text is one check, whatever the number of categories it is checked against.
Request
Send JSON, with the header Content-Type: application/json. Without it the API answers 415 unsupported_media.
| Field | Required | Description |
|---|---|---|
text | Yes | The text, at most 20,000 characters (5,000 on the free plan). |
workflow | No | The workflow to check against. default when absent. |
ref | No | Your own id for the text, 1 to 128 characters, no control character. It is echoed in the answer and kept in the journal. |
context | No | Where the text comes from, in plain words, at most 2,000 characters: for example "a buyer writes to a seller on a marketplace that forbids sharing phone numbers". Paid plans read it in their advanced AI workflows; the free plan ignores it. It is not kept in the journal. |
curl -X POST "https://api.openshield.dev/v1/text" \
-H "Authorization: Bearer $OPENMOD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Write me at jane@example.com", "workflow": "default", "ref": "comment_9034"}'
const response = await fetch("https://api.openshield.dev/v1/text", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENMOD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text: "Write me at jane@example.com", ref: "comment_9034" }),
})
const answer = await response.json()
console.log(answer.summary.action)
What is checked
The categories of the workflow. The default workflow:
- Rejects unsafe text, violence, sexual content, hate, illegal activity and unethical content at a score of 0.8 (and sends them to review from 0.5), and bank account numbers, payment card numbers and unsafe links outright.
- Sends to review self-harm from 0.5, and email addresses, phone numbers, requests to continue on another messaging app, spam, scams, extremism and links to adult or gambling sites outright.
Some rules look at the text itself, such as personal data and links. Their score is 1 when they match, which is why their thresholds are 1. Workflows explains how to change all of this.
Answer
The answer has the shape described here. For a text that holds an email address:
{
"status": "success",
"workflow": "default",
"workflow_version": 1,
"summary": {
"action": "review",
"reject_prob": 0,
"reject_reason": [],
"review_reason": [
{
"id": "pii_email",
"text": "Email address",
"message": "This content contains an email address.",
"score": 1,
"threshold": 1,
"source": "rules"
}
]
},
"scores": { "pii_email": 1 },
"time_ms": 4,
"request_id": "0192b7c5-1d20-7b3a-8f61-5c9e2a7d4b10",
"ref": "comment_9034"
}
Advanced AI workflows
On Starter, Growth and Scale, a text that the first check sends to review gets a second, deeper reading by a more advanced AI model, with your context. It answers:
rejectwhen the text clearly breaks the policy on the points flagged, or on another point (then undertext_unsafe);acceptwhen the flag was a false alarm;reviewas before when it is not sure.
A reason it gives has "source": "advanced". It costs nothing more per check. When it is not available, or slower than 1.5 seconds, the first check's decision stands. Images are not concerned. The model runs at a sub-processor listed on the sub-processors page.
Errors
| Status | error.type | When |
|---|---|---|
| 400 | bad_request | The body is not JSON, or has no text, or ref is refused, or context has more than 2,000 characters. |
| 400 | unknown_workflow | There is no workflow of that name. |
| 413 | text_too_long | The text has more than 20,000 characters (5,000 on the free plan). |
| 413 | body_too_large | The body is over the size limit. |
| 415 | unsupported_media | The Content-Type is not application/json. |
| 503 | workflow_unavailable | The workflow has no rule for texts, or none this server can check. |
Authentication, rate limit and quota errors are in responses and errors.