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

# API Overview

> Base URL, authentication, and error handling for the Pangram REST API

## Base URLs

AI detection and bulk AI detection use the following base URL:

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

File uploads use the following base URL:

```
https://file-external.api.pangram.com
```

The plagiarism detection endpoint uses a separate base URL:

```
https://plagiarism.api.pangram.com
```

## Authentication

All API requests must include your API key in the `x-api-key` header.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://text.external-api.pangram.com/task \
      -H "Content-Type: application/json" \
      -H "x-api-key: <your-api-key>" \
      -d '{"text": "Your text here"}'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    response = requests.post(
        "https://text.external-api.pangram.com/task",
        headers={
            "Content-Type": "application/json",
            "x-api-key": "<your-api-key>",
        },
        json={"text": "Your text here"},
    )
    task_id = response.json()["task_id"]

    result = requests.get(
        f"https://text.external-api.pangram.com/task/{task_id}",
        headers={"x-api-key": "<your-api-key>"},
    )
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const submitResponse = await fetch("https://text.external-api.pangram.com/task", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": "<your-api-key>"
      },
      body: JSON.stringify({ text: "Your text here" })
    });

    const { task_id } = await submitResponse.json();

    const resultResponse = await fetch(`https://text.external-api.pangram.com/task/${task_id}`, {
      headers: {
        "x-api-key": "<your-api-key>"
      }
    });
    ```
  </Tab>
</Tabs>

## Async Task Flow

Submit text with `POST /task`, then poll `GET /task/{task_id}` until the returned `stage` is `STAGE_SUCCESS` or `STAGE_FAILED`.

## Bulk Flow

Submit many texts with `POST /bulk`, poll `GET /bulk/{bulk_id}` until the returned `status` is `succeeded`, `failed`, or `partial`, then page through `GET /bulk/{bulk_id}/results`.

Bulk completion time depends on the number and length of submitted items and current system load. Use `GET /bulk/{bulk_id}` to monitor progress.

Bulk metadata and results are retained for 48 hours after terminal completion. Bulk `created_at` and `completed_at` values are Unix epoch seconds encoded as strings.

## File Upload Flow

Submit documents as `multipart/form-data` to `https://file-external.api.pangram.com`. Include one or more `files` fields and set `public_dashboard_link=true` when you need a shareable result link.

## Error Codes

| Status Code                 | Description                                              |
| --------------------------- | -------------------------------------------------------- |
| `400 Bad Request`           | The request body is not properly formatted.              |
| `401 Unauthorized`          | The `x-api-key` is missing or invalid.                   |
| `402 Payment Required`      | The account has insufficient credits.                    |
| `403 Forbidden`             | The API key does not own the requested task or bulk job. |
| `404 Not Found`             | The requested task or bulk job does not exist.           |
| `413 Payload Too Large`     | The bulk request exceeds the maximum billable units.     |
| `422 Unprocessable Entity`  | The input text is invalid.                               |
| `429 Too Many Requests`     | The API key exceeds its configured rate limit.           |
| `500 Internal Server Error` | There was an error processing the request.               |

If you are running into errors, please reach out at [support@pangram.com](mailto:support@pangram.com).
