> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pangram.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Detection

> Detect AI-generated and AI-assisted text using the async inference API

For more information on billing units and pricing, check our [pricing page for developers](https://www.pangram.com/pricing?category=developers).

<Badge color="green">Current</Badge>

<Update label="Async inference API" description="Current version">
  The current AI detection API creates an async task and returns a task ID. Poll the task endpoint until it reaches `STAGE_SUCCESS` or `STAGE_FAILED`.
</Update>

Use the [Bulk API](/api-reference/bulk-api) when you need to analyze many texts as one asynchronous job.

Use [`GET /models`](/api-reference/models) to discover the selectors available to your API key. The REST API temporarily accepts an omitted `model` for backward compatibility and resolves it to `"default"`. New integrations should always send a selector explicitly.

## POST /task

Create an async AI detection task.

```
POST https://text.external-api.pangram.com/task
```

### Request

<ParamField body="text" type="string" required>
  The input text to analyze.
</ParamField>

<ParamField body="model" type="string" default="default">
  A model selector returned by [`GET /models`](/api-reference/models).
</ParamField>

<ParamField body="public_dashboard_link" type="boolean" default="false">
  Whether to include a public dashboard link in the completed response.
</ParamField>

### Response

<ResponseField name="task_id" type="string">
  The ID of the async inference task.
</ResponseField>

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://text.external-api.pangram.com/task \
    -H "Content-Type: application/json" \
    -H "x-api-key: your_api_key_here" \
    -d '{
      "text": "AI-assisted passage. Human passage.",
      "model": "pangram-4",
      "public_dashboard_link": false
    }'
  ```

  ```python Python SDK theme={null}
  from pangram import Pangram

  pangram_client = Pangram()
  result = pangram_client.predict(
      "AI-assisted passage. Human passage.",
      model="pangram-4",
  )
  ```
</CodeGroup>

**Example Response**

```json theme={null}
{
  "task_id": "123e4567-e89b-12d3-a456-426614174000"
}
```

### Model selection errors

| Status Code                | Description                                         |
| -------------------------- | --------------------------------------------------- |
| `403 Forbidden`            | The requested model is not enabled for the API key. |
| `422 Unprocessable Entity` | The model selector is malformed or unknown.         |
| `503 Service Unavailable`  | The requested model is temporarily unavailable.     |

***

## GET /task/{task_id}

Fetch the current status or completed result for an AI detection task.

```
GET https://text.external-api.pangram.com/task/{task_id}
```

### Request

<ParamField path="task_id" type="string" required>
  The task ID returned by `POST /task`.
</ParamField>

### Response

<ResponseField name="task_id" type="string">
  The ID of the async inference task. Present while the task is in progress.
</ResponseField>

<ResponseField name="stage" type="string">
  Current task stage. Terminal stages are `STAGE_SUCCESS` and `STAGE_FAILED`.
</ResponseField>

<ResponseField name="text" type="string">
  The analyzed text returned by the model. Pangram 4 may normalize the submitted text before inference; window offsets refer to this returned value. Present on success.
</ResponseField>

<ResponseField name="version" type="string">
  The API version identifier (e.g., `"4.0"` for Pangram 4). Present on success.
</ResponseField>

<ResponseField name="headline" type="string">
  Classification headline summarizing the result. Present on success.
</ResponseField>

<ResponseField name="prediction" type="string">
  Long-form prediction string describing the classification. Present on success.
</ResponseField>

<ResponseField name="prediction_short" type="string">
  Short-form prediction string. Pangram 4 returns `"AI"`, `"Human"`, or `"Mixed"`. Present on success.
</ResponseField>

<ResponseField name="fraction_ai" type="float">
  Fraction of text classified as AI-written (0.0–1.0). Present on success.
</ResponseField>

<ResponseField name="fraction_ai_assisted" type="float">
  Fraction of text classified as AI-assisted (0.0–1.0). Present on success.
</ResponseField>

<ResponseField name="fraction_human" type="float">
  Fraction of text classified as human-written (0.0–1.0). Present on success.
</ResponseField>

<ResponseField name="num_ai_segments" type="integer">
  Number of text segments classified as AI. Present on success.
</ResponseField>

<ResponseField name="num_ai_assisted_segments" type="integer">
  Number of text segments classified as AI-assisted. Present on success.
</ResponseField>

<ResponseField name="num_human_segments" type="integer">
  Number of text segments classified as human. Present on success.
</ResponseField>

<ResponseField name="dashboard_link" type="string">
  A link to the dashboard page containing the full classification result. Present on success when `public_dashboard_link` is `true`.
</ResponseField>

<ResponseField name="windows" type="array">
  List of text segments (<Tooltip tip="The text is divided into overlapping segments (windows) that are each classified independently, enabling granular detection across long documents.">windows</Tooltip>) analyzed individually. Present on success.

  <Expandable title="Window object properties">
    <ResponseField name="text" type="string">
      The window text.
    </ResponseField>

    <ResponseField name="label" type="string">
      Descriptive classification label. Pangram 4 returns `"AI-Generated"`, `"AI-Assisted"`, or `"Human Written"`.
    </ResponseField>

    <ResponseField name="ai_assistance_score" type="float">
      <Tooltip tip="A continuous score from 0 to 1, where 0 means entirely human-written and 1 means fully AI-generated. Values in between indicate varying degrees of AI assistance.">AI assistance score</Tooltip> detailing the level of AI assistance (0.0–1.0).
    </ResponseField>

    <ResponseField name="confidence" type="string">
      <Tooltip tip="High = strong signal, the model is very sure. Medium = moderate signal. Low = weak signal, treat with caution.">Confidence level</Tooltip> for the classification (`"High"`, `"Medium"`, `"Low"`).
    </ResponseField>

    <ResponseField name="start_index" type="integer">
      Starting character index in the returned top-level `text`.
    </ResponseField>

    <ResponseField name="end_index" type="integer">
      End-exclusive character index in the returned top-level `text`.
    </ResponseField>

    <ResponseField name="word_count" type="integer">
      Number of words in the window.
    </ResponseField>

    <ResponseField name="token_length" type="integer">
      Token length of the window.
    </ResponseField>

    <ResponseField name="is_humanized" type="boolean">
      Whether Pangram 4's humanizer head classified the window as humanized. Present on every Pangram 4 window.
    </ResponseField>

    <ResponseField name="humanizer_score" type="float">
      Pangram 4 humanizer-head score from 0.0–1.0. Present on every Pangram 4 window.
    </ResponseField>
  </Expandable>
</ResponseField>

### Example

```bash cURL theme={null}
curl -X GET https://text.external-api.pangram.com/task/123e4567-e89b-12d3-a456-426614174000 \
  -H "x-api-key: your_api_key_here"
```

**In-Progress Response**

```json theme={null}
{
  "task_id": "123e4567-e89b-12d3-a456-426614174000",
  "stage": "STAGE_PREPROCESSING"
}
```

**Success Response**

This example shows a Pangram 4 result. Pangram 4 returns `version: "4.0"`, uses `"AI-Assisted"` instead of lightly or moderately assisted window labels, and keeps `confidence` as `"Low"`, `"Medium"`, or `"High"`.

```json theme={null}
{
  "stage": "STAGE_SUCCESS",
  "text": "AI-assisted passage. Human passage.",
  "version": "4.0",
  "headline": "AI Assisted",
  "prediction": "We believe that this text is a mix of AI-assisted and human-written content.",
  "prediction_short": "Mixed",
  "fraction_ai": 0.0,
  "fraction_ai_assisted": 0.6,
  "fraction_human": 0.4,
  "num_ai_segments": 0,
  "num_ai_assisted_segments": 1,
  "num_human_segments": 1,
  "windows": [
    {
      "text": "AI-assisted passage. ",
      "label": "AI-Assisted",
      "ai_assistance_score": 0.55,
      "confidence": "High",
      "start_index": 0,
      "end_index": 21,
      "word_count": 2,
      "token_length": 5,
      "is_humanized": true,
      "humanizer_score": 0.91
    },
    {
      "text": "Human passage.",
      "label": "Human Written",
      "ai_assistance_score": 0.02,
      "confidence": "Medium",
      "start_index": 21,
      "end_index": 35,
      "word_count": 2,
      "token_length": 4,
      "is_humanized": false,
      "humanizer_score": 0.0
    }
  ]
}
```

**Failed Response**

```json theme={null}
{
  "stage": "STAGE_FAILED",
  "text": "",
  "version": "",
  "headline": "preprocessing: Input text contains no valid text after preprocessing",
  "prediction": "",
  "prediction_short": "",
  "fraction_ai": 0.0,
  "fraction_ai_assisted": 0.0,
  "fraction_human": 0.0,
  "num_ai_segments": 0,
  "num_ai_assisted_segments": 0,
  "num_human_segments": 0,
  "windows": []
}
```
