Skip to content
ParaTrace

Unlimited free credit top-ups, for a limited time. Running low? Ask for more credits and we top you up, as often as you need. This offer ends soon, so catch it while it lasts.

For developers

The ParaTrace API

Check texts, or a PDF, .txt or .md file, from your own software. A key is free and comes with 1,000 credits.

How it works

  1. Sign in, or create a free account, and create your key on your account page. Your key comes with 1,000 free credits and stays on your account page whenever you need it. It is never emailed.
  2. Send it with every call, in the header Authorization: Bearer <key>. Keep it private. Anyone who has it can spend your credits.
  3. Send texts as JSON, or one file as multipart form data. A file can be a .pdf with selectable text, or a .txt or .md file. Sending a file shows how.
  4. Each text costs 1 credit per started 512 tokens, and at least 1. A credit covers about 400 English words, so a 1,000-word text costs 3 credits. Every answer gives each text's n_tokens, so you can check the charge. Invalid requests cost nothing, and a request that needs more credits than you have left is refused (402) without charging.
  5. Up to 10 texts or one file per request, and 200,000 characters per text, the text taken from a file included. English only. The accuracy limits in the benchmark report apply.
  6. Texts and files sent to the API are scored and not stored. Only your credit count is kept.

Fast or detailed

The two detect calls
CallAddressReturns
DetailedPOST /v1/api/detectVerdicts, windows and segments
FastPOST /v1/api/detect/fastVerdicts only

The fast call returns one verdict per text. The detailed call also returns windows, a score for each part of a long text with its character positions, and segments, the parts of the text labelled AI or human, so you can see which passages look AI-written. Both take the same request, texts as JSON or one file, cost the same and give exactly the same verdicts, and the fast call is quicker. Use it whenever you only need the overall result.

Detailed example

Two texts in one call. The first fits in one window. The second is long, so it is scored in five overlapping windows, and one of them scores much lower than the rest. So the end of the second text is labelled human, and it comes out partly AI-generated.

Request
curl -X POST https://test.api.paratrace.net/v1/api/detect \
  -H "Authorization: Bearer pt_..." \
  -H "Content-Type: application/json" \
  -d '{
    "texts": [
      "A first text, about 300 words long ...",
      "A second text, about 1,260 words long ..."
    ],
    "operating_point": "strict"
  }'
Response
{
  "detector_version": "v7",
  "documents": [
    {
      "document": "text_1",
      "credits": 1,
      "probability": 0.9731,
      "is_ai": true,
      "verdict": "ai",
      "ai_fraction": 1.0,
      "confidence": "high",
      "operating_point": "strict",
      "n_words": 312,
      "n_tokens": 389,
      "n_windows": 1,
      "windows": [
        { "start": 0, "end": 1874, "probability": 0.9731 }
      ],
      "segments": [
        { "start": 0, "end": 1874, "label": "ai", "probability": 0.9731 }
      ],
      "warnings": []
    },
    {
      "document": "text_2",
      "credits": 4,
      "probability": 0.9996,
      "is_ai": true,
      "verdict": "mixed",
      "ai_fraction": 0.97,
      "confidence": "medium",
      "operating_point": "strict",
      "n_words": 1260,
      "n_tokens": 1790,
      "n_windows": 5,
      "windows": [
        { "start": 0, "end": 2286, "probability": 1.0 },
        { "start": 1739, "end": 4019, "probability": 1.0 },
        { "start": 3418, "end": 5893, "probability": 1.0 },
        { "start": 5249, "end": 7675, "probability": 0.9982 },
        { "start": 7136, "end": 7944, "probability": 0.1349 }
      ],
      "segments": [
        { "start": 0, "end": 7675, "label": "ai", "probability": 0.9996 },
        { "start": 7675, "end": 7944, "label": "human", "probability": 0.1349 }
      ],
      "warnings": []
    }
  ],
  "credits_charged": 5,
  "credits_remaining": 995
}

Fast example

The second text from above, sent alone to the fast call. The verdict is the same. Each document has no windows or segments key at all, not an empty list, and n_windows still says how many windows were scored.

Fast request
curl -X POST https://test.api.paratrace.net/v1/api/detect/fast \
  -H "Authorization: Bearer pt_..." \
  -H "Content-Type: application/json" \
  -d '{"text": "A text, about 1,260 words long ...", "operating_point": "strict"}'
Fast response
{
  "detector_version": "v7",
  "documents": [
    {
      "document": "text",
      "probability": 0.9996,
      "is_ai": true,
      "verdict": "mixed",
      "ai_fraction": 0.97,
      "confidence": "medium",
      "operating_point": "strict",
      "n_words": 1260,
      "n_tokens": 1790,
      "n_windows": 5,
      "warnings": [],
      "credits": 4
    }
  ],
  "credits_charged": 4,
  "credits_remaining": 996
}

Sending a file

Both detect calls take a file as well. Instead of JSON, send one file as multipart form data in the field files, to POST /v1/api/detect or POST /v1/api/detect/fast.

File request
curl -X POST https://test.api.paratrace.net/v1/api/detect \
  -H "Authorization: Bearer pt_..." \
  -F "files=@paper.pdf"
  • The file can be a .pdf with selectable text, or a .txt or .md file in UTF-8, UTF-16 or Windows-1252.
  • You may add the form fields text and operating_point.
  • The answer is the same JSON as for a text, with the document named by its file name, such as "document": "paper.pdf". Credits are counted on the text taken from the file.
  • One file per request. A second file, a scanned PDF without a text layer, or a password-protected or broken PDF is refused with 422, and nothing is charged.
  • Files, like texts, are scored and not stored.

Fields

Fields of each document in the answer
FieldMeaning
documentWhich text this is. A single text is answered as text, a list as text_1, text_2 and so on in the same order, and a file by its file name.
probabilityHow likely the text is to be AI-generated, from 0 to 1. null when nothing was left after cleaning. For a text in more than one window it doesn't decide the verdict.
is_aiFor a text in one window, true when probability is at or above threshold. For a longer one, true unless verdict is human, so a partly AI-generated text counts.
verdictai, human or mixed, which means partly AI-generated. null when nothing was left after cleaning.
ai_fractionHow much of the text is labelled AI, from 0 to 1. null as for verdict.
confidenceHow sure the verdict is, low, medium or high, by cut-offs set from our tests. null as for verdict.
thresholdThe cut-off that was applied. At strict it flags about 1 in 100 human texts, and at lenient about 1 in 20. For a text in more than one window it is each window's cut-off, so don't compare it with probability.
n_wordsWords in the text as sent, or as taken from the file.
n_tokensTokens in the text as sent, or as taken from the file, counted with the detector's own tokenizer. The text costs 1 credit per started 512 of them.
n_windowsHow many 512-token windows were scored. Long texts have several, and the probability combines them. Windows overlap, but you pay for the text's tokens, not for each window.
windowsDetailed call only. Each window with its own probability, and its start and end in the text you sent, or the text taken from the file, counted in Unicode code points with end excluded. Neighbouring windows overlap.
segmentsDetailed call only. The parts of the text in order, without overlap, each with its label, ai or human, its start and end counted like the windows', and its mean probability. Where a part starts and ends is approximate. An empty list when nothing was scored.
warningsNotes on reliability, for a short text or a text left empty after cleaning.
creditsWhat this text cost, 1 credit per started 512 tokens and at least 1.

Beside documents, every answer has detector_version, which names the detector that scored the request so you can tell when a newer one takes over, and credits_charged and credits_remaining.

Errors

Both calls answer errors the same way, with these statuses.

Error statuses
StatusWhen
401The key is missing or invalid.
402Not enough credits left. Nothing is charged.
403The key has been deactivated.
413A text, or the text taken from a file, is over 200,000 characters.
415A file of another type than .pdf, .txt or .md.
422No text, an empty text, more than 10 texts, a second file, a PDF without a text layer, a password-protected or broken PDF, or an invalid field.
503The detector is unavailable. Your credits are refunded.

More options

  • Send up to 10 texts as "texts": [...], a single one as "text": "...", or one file as multipart form data.
  • operating_point is strict, the default, or lenient. The operating points explain the difference.
  • GET https://test.api.paratrace.net/v1/api/account with the same header returns the credits you have left, in credits_available. The key spends your account's credits, shared with the website.