---
title: "Texts"
description: "Check a text with POST /v1/text, for comments, messages, names and bios."
canonical_url: "https://openshield.dev/docs/texts"
---
# Texts

> Check a text with POST /v1/text, for comments, messages, names and bios.

`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`.

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Required
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        text
      </code>
    </td>
    
    <td>
      Yes
    </td>
    
    <td>
      The text, at most 20,000 characters (5,000 on the free plan).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        workflow
      </code>
    </td>
    
    <td>
      No
    </td>
    
    <td>
      The <a href="https://openshield.dev/docs/workflows">
        workflow
      </a>
      
       to check against. <code>
        default
      </code>
      
       when absent.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ref
      </code>
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Your own id for the text, 1 to 128 characters, no control character. It is echoed in the answer and kept in the <a href="https://openshield.dev/docs/journal-and-ref">
        journal
      </a>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        context
      </code>
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Where the text comes from, in plain words, at most 2,000 characters: for example <code>
        "a buyer writes to a seller on a marketplace that forbids sharing phone numbers"
      </code>
      
      . Paid plans read it in their <a href="#advanced-ai-workflows">
        advanced AI workflows
      </a>
      
      ; the free plan ignores it. It is not kept in the journal.
    </td>
  </tr>
</tbody>
</table>

<code-group>

```bash [curl]
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"}'
```

```ts [TypeScript]
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)
```

</code-group>

## 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](https://openshield.dev/docs/workflows) explains how to change all of this.

## Answer

The answer has the [shape described here](https://openshield.dev/docs/responses-and-errors). For a text that holds an email address:

```json
{
  "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:

- `reject` when the text clearly breaks the policy on the points flagged, or on another point (then under `text_unsafe`);
- `accept` when the flag was a false alarm;
- `review` as 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 [list of sub-processors](https://openshield.dev/legal/dpa#annex-sub-processors).

## Errors

<table>
<thead>
  <tr>
    <th>
      Status
    </th>
    
    <th>
      <code>
        error.type
      </code>
    </th>
    
    <th>
      When
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      400
    </td>
    
    <td>
      <code>
        bad_request
      </code>
    </td>
    
    <td>
      The body is not JSON, or has no <code>
        text
      </code>
      
      , or <code>
        ref
      </code>
      
       is refused, or <code>
        context
      </code>
      
       has more than 2,000 characters.
    </td>
  </tr>
  
  <tr>
    <td>
      400
    </td>
    
    <td>
      <code>
        unknown_workflow
      </code>
    </td>
    
    <td>
      There is no workflow of that name.
    </td>
  </tr>
  
  <tr>
    <td>
      413
    </td>
    
    <td>
      <code>
        text_too_long
      </code>
    </td>
    
    <td>
      The text has more than 20,000 characters (5,000 on the free plan).
    </td>
  </tr>
  
  <tr>
    <td>
      413
    </td>
    
    <td>
      <code>
        body_too_large
      </code>
    </td>
    
    <td>
      The body is over the size limit.
    </td>
  </tr>
  
  <tr>
    <td>
      415
    </td>
    
    <td>
      <code>
        unsupported_media
      </code>
    </td>
    
    <td>
      The <code>
        Content-Type
      </code>
      
       is not <code>
        application/json
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      503
    </td>
    
    <td>
      <code>
        workflow_unavailable
      </code>
    </td>
    
    <td>
      The workflow has no rule for texts, or none this server can check.
    </td>
  </tr>
</tbody>
</table>

Authentication, rate limit and quota errors are in [responses and errors](https://openshield.dev/docs/responses-and-errors).


## Sitemap

See the full [sitemap](https://openshield.dev/sitemap.md) for all pages.
