Inference API

The Inference API accepts text, creates a task, and returns a task ID. Poll the task endpoint until the stage is STAGE_SUCCESS or STAGE_FAILED.

POST https://text.external-api.pangram.com/task
Request JSON Object:
  • text (string) – The input text to analyze with Pangram.

  • public_dashboard_link (boolean) – Whether to include a public dashboard link in the completed response. Defaults to false.

Response JSON Object:
  • task_id (string) – The ID of the async inference task.

Request Headers

{
  "Content-Type": "application/json",
  "x-api-key": "<api-key>"
}

Request Body

{
  "text": "<text>",
  "public_dashboard_link": false
}

Example Request

POST https://text.external-api.pangram.com/task HTTP/1.1
Content-Type: application/json
x-api-key: your_api_key_here

{
  "text": "The text to analyze",
  "public_dashboard_link": true
}

Example Response

{
  "task_id": "123e4567-e89b-12d3-a456-426614174000"
}
GET https://text.external-api.pangram.com/task/(string: task_id)
Response JSON Object:
  • task_id (string) – The ID of the async inference task. Present while the task is in progress.

  • stage (string) – Current task stage. Terminal stages are STAGE_SUCCESS and STAGE_FAILED.

  • text (string) – The input text that was analyzed. Present on success.

  • version (string) – The API version identifier. Present on success.

  • headline (string) – Classification headline summarizing the result. Present on success.

  • prediction (string) – Long-form prediction string representing the classification. Present on success.

  • prediction_short (string) – Short-form prediction string. Present on success.

  • fraction_ai (float) – Fraction of text classified as AI-written (0.0-1.0). Present on success.

  • fraction_ai_assisted (float) – Fraction of text classified as AI-assisted (0.0-1.0). Present on success.

  • fraction_human (float) – Fraction of text classified as human-written (0.0-1.0). Present on success.

  • num_ai_segments (int) – Number of text segments classified as AI. Present on success.

  • num_ai_assisted_segments (int) – Number of text segments classified as AI-assisted. Present on success.

  • num_human_segments (int) – Number of text segments classified as human. Present on success.

  • windows (array) – List of analyzed text windows. Each window includes text, label, ai_assistance_score, confidence, start_index, end_index, word_count, and token_length. Present on success.

  • dashboard_link (string) – A link to the dashboard page containing the full classification result. Present on success when public_dashboard_link is true.

Request Headers

{
  "x-api-key": "<api-key>"
}

In-Progress Response

{
  "task_id": "123e4567-e89b-12d3-a456-426614174000",
  "stage": "STAGE_PREPROCESSING"
}

Success Response

{
  "stage": "STAGE_SUCCESS",
  "text": "The text to analyze",
  "version": "3.0",
  "headline": "AI Detected",
  "prediction": "We are confident that this document contains AI-generated or AI-assisted content.",
  "prediction_short": "Mixed",
  "fraction_ai": 0.70,
  "fraction_ai_assisted": 0.20,
  "fraction_human": 0.10,
  "num_ai_segments": 7,
  "num_ai_assisted_segments": 2,
  "num_human_segments": 1,
  "dashboard_link": "https://www.pangram.com/history/123e4567-e89b-12d3-a456-426614174000",
  "windows": [
    {
      "text": "The text to analyze",
      "label": "AI-Generated",
      "ai_assistance_score": 0.85,
      "confidence": "High",
      "start_index": 0,
      "end_index": 19,
      "word_count": 4,
      "token_length": 5
    },
    {
      "text": "with classification",
      "label": "Moderately AI-Assisted",
      "ai_assistance_score": 0.45,
      "confidence": "Medium",
      "start_index": 20,
      "end_index": 49,
      "word_count": 2,
      "token_length": 3
    }
  ]
}

Failed Response

{
  "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": []
}

Bulk API

The Bulk API accepts many texts, queues them as asynchronous AI detection work, and returns a bulk job ID. Poll the bulk status endpoint until the status is succeeded, failed, or partial.

Completion time depends on the number and length of submitted items and current system load. Use the bulk status endpoint to monitor progress.

Bulk metadata and results are retained for 48 hours after the job reaches a terminal status. created_at and completed_at are returned as Unix epoch seconds encoded as strings, such as "1760000000.0".

The launch bulk limit is 1,000 billable units per request. A billable unit is one started 1,000-word block per valid item, with a minimum of one unit per item. There is no separate item-count limit, but normal request-body limits still apply.

POST https://text.external-api.pangram.com/bulk
Request JSON Object:
  • text (array) – A list of input texts. Provide either text or items.

  • items (array) – A list of objects with text and optional id fields. Provide either items or text.

Response JSON Object:
  • bulk_id (string) – The ID of the bulk job.

  • status (string) – Initial status, usually queued or failed if every item failed immediate validation.

  • total_items (int) – Total number of submitted items.

  • accepted_items (array) – Items accepted for processing. Each item includes index, optional id, and task_id.

  • failed_items (array) – Items that failed immediate validation. Each item includes index, optional id, stage, and error.

Request Headers

{
  "Content-Type": "application/json",
  "x-api-key": "<api-key>"
}

Request Body

{
  "items": [
    {"id": "row-001", "text": "First text to analyze"},
    {"id": "row-002", "text": "Second text to analyze"}
  ]
}

Example Response

{
  "bulk_id": "blk_123",
  "status": "queued",
  "total_items": 2,
  "accepted_items": [
    {"index": 0, "id": "row-001", "task_id": "123e4567-e89b-12d3-a456-426614174000"},
    {"index": 1, "id": "row-002", "task_id": "223e4567-e89b-12d3-a456-426614174000"}
  ],
  "failed_items": []
}
GET https://text.external-api.pangram.com/bulk/(string: bulk_id)
Response JSON Object:
  • bulk_id (string) – The ID of the bulk job.

  • status (string) – One of queued, running, succeeded, failed, or partial.

  • total_items (int) – Total number of submitted items.

  • accepted (int) – Number of items accepted for processing.

  • succeeded (int) – Number of items that completed successfully.

  • failed (int) – Number of items that failed.

  • created_at (string) – Job creation timestamp as Unix epoch seconds encoded as a string.

  • completed_at (string) – Job completion timestamp as Unix epoch seconds encoded as a string, or null while non-terminal.

Example Response

{
  "bulk_id": "blk_123",
  "status": "partial",
  "total_items": 3,
  "accepted": 2,
  "succeeded": 2,
  "failed": 1,
  "created_at": "1760000000.0",
  "completed_at": "1760000030.0"
}
GET https://text.external-api.pangram.com/bulk/(string: bulk_id)/items
Query Parameters:
  • offset (int) – Zero-based item offset. Defaults to 0.

  • limit (int) – Maximum number of items to return. Defaults to 100 and can be at most 1000.

Response JSON Object:
  • bulk_id (string) – The ID of the bulk job.

  • offset (int) – The returned page offset.

  • limit (int) – The returned page limit.

  • total_items (int) – Total number of submitted items.

  • items (array) – Item metadata. Each item includes index, optional id, task_id, stage, and optional error.

Example Response

{
  "bulk_id": "blk_123",
  "offset": 0,
  "limit": 100,
  "total_items": 2,
  "items": [
    {
      "index": 0,
      "id": "row-001",
      "task_id": "123e4567-e89b-12d3-a456-426614174000",
      "stage": "STAGE_SUCCESS",
      "error": null
    }
  ]
}
GET https://text.external-api.pangram.com/bulk/(string: bulk_id)/results
Query Parameters:
  • offset (int) – Zero-based item offset. Defaults to 0.

  • limit (int) – Maximum number of items to return. Defaults to 100 and can be at most 1000.

Response JSON Object:
  • bulk_id (string) – The ID of the bulk job.

  • offset (int) – The returned page offset.

  • limit (int) – The returned page limit.

  • total_items (int) – Total number of submitted items.

  • items (array) – Result items. Successful completed items include result with the same shape returned by the task endpoint. In-progress items have result set to null.

  • failed_items (array) – Failed item metadata for the requested page.

Example Response

{
  "bulk_id": "blk_123",
  "offset": 0,
  "limit": 100,
  "total_items": 2,
  "items": [
    {
      "index": 0,
      "id": "row-001",
      "task_id": "123e4567-e89b-12d3-a456-426614174000",
      "stage": "STAGE_SUCCESS",
      "error": null,
      "result": {
        "text": "First text to analyze",
        "version": "3.3",
        "prediction": "We believe this is human-written",
        "prediction_short": "Human",
        "fraction_ai": 0.0,
        "fraction_ai_assisted": 0.0,
        "fraction_human": 1.0,
        "headline": "Human Written",
        "num_ai_segments": 0,
        "num_ai_assisted_segments": 0,
        "num_human_segments": 1,
        "windows": []
      }
    }
  ],
  "failed_items": []
}

File Upload API

The File Upload API accepts one or more files as multipart/form-data and returns one result object per uploaded file. Use this endpoint when you want Pangram to extract text from .docx, .pdf, or .rtf documents and create AI detection results. Each result uses the same prediction schema as the text API, with the extracted text and uploaded filename included. When public_dashboard_link is true, each result also includes a dashboard_link.

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

Request Headers

Do not set Content-Type manually for multipart requests. HTTP clients add the multipart boundary automatically.

{
  "x-api-key": "<api-key>"
}

Multipart Form Fields

Field

Type

Required

Description

files

file[]

Yes

.docx, .pdf, or .rtf files to analyze. Include this form field once per uploaded file.

public_dashboard_link

boolean

No

Whether to create and return a dashboard_link for each uploaded file. Defaults to false.

Example Request

POST https://file-external.api.pangram.com/ HTTP/1.1
x-api-key: your_api_key_here
Content-Type: multipart/form-data; boundary=...

--...
Content-Disposition: form-data; name="files"; filename="document.docx"
Content-Type: application/octet-stream

<file bytes>
--...
Content-Disposition: form-data; name="public_dashboard_link"

true
--...--

Example cURL

curl -s -X POST https://file-external.api.pangram.com \
  -H "x-api-key: $PANGRAM_API_KEY" \
  -F "files=@path/to/first.docx" \
  -F "files=@path/to/second.pdf" \
  -F "public_dashboard_link=true"

Example Response

[
  {
    "filename": "document.docx",
    "text": "Extracted document text...",
    "version": "3.3",
    "headline": "Human Written",
    "prediction": "We believe this is human-written",
    "prediction_short": "Human",
    "fraction_ai": 0.0,
    "fraction_ai_assisted": 0.0,
    "fraction_human": 1.0,
    "num_ai_segments": 0,
    "num_ai_assisted_segments": 0,
    "num_human_segments": 1,
    "windows": [],
    "dashboard_link": "https://www.pangram.com/history/123e4567-e89b-12d3-a456-426614174000"
  }
]

Errors

  • 400 Bad Request - The multipart request is missing a file or includes invalid form data.

  • 401 Unauthorized - The x-api-key is missing or invalid.

  • 402 Payment Required - The account has insufficient credits.

  • 413 Payload Too Large - The upload exceeds the maximum supported file size.

  • 415 Unsupported Media Type - The uploaded file type is not supported.

  • 422 Unprocessable Entity - The files field is missing, the form data is invalid, or Pangram could not extract valid text from the uploaded file.

  • 500 Internal Server Error - There was an error processing the upload.

Plagiarism Detection API

The Plagiarism Detection API checks text for potential plagiarism by comparing it against online content.

POST https://plagiarism.api.pangram.com
Request JSON Object:
  • text (string) – The input text to check for plagiarism.

Response JSON Object:
  • text (string) – The input text that was checked.

  • plagiarism_detected (bool) – Whether plagiarism was detected in the text.

  • plagiarized_content (array) – A list of detected plagiarized content, including source URLs and matched text.

  • total_sentences (int) – Total number of sentences in the input text.

  • plagiarized_sentences (array) – List of sentences that were detected as plagiarized.

  • percent_plagiarized (float) – Percentage of the text that was detected as plagiarized.

Request Headers

{
  "Content-Type": "application/json",
  "x-api-key": "<api-key>"
}

Request Body

{
  "text": "<text>"
}

Example Request

POST https://plagiarism.api.pangram.com HTTP/1.1
Content-Type: application/json
x-api-key: your_api_key_here

{
  "text": "The text to check for plagiarism"
}

Example Response

{
  "text": "The text to check for plagiarism",
  "plagiarism_detected": true,
  "plagiarized_content": [
    {
      "source_url": "https://example.com/source",
      "matched_text": "The text to check for plagiarism",
      "similarity_score": 0.95
    }
  ],
  "total_sentences": 1,
  "plagiarized_sentences": 1,
  "percent_plagiarized": 100.0
}

Errors

The API may return the following error codes:

  • 400 Bad Request - If the request body is not properly formatted.

  • 401 Unauthorized - If the x-api-key is missing or invalid.

  • 402 Payment Required - If the account has insufficient credits.

  • 403 Forbidden - If the API key does not own the requested task.

  • 404 Not Found - If the requested task does not exist.

  • 422 Unprocessable Entity - If the input text is invalid.

  • 429 Too Many Requests - If the API key exceeds its configured rate limit.

  • 500 Internal Server Error - If there is an error processing the request.

Please reach out at support@pangram.com if you are running into errors with your requests.