{
  "openapi": "3.1.0",
  "info": {
    "title": "WasItAIGenerated API",
    "version": "1.2.0",
    "summary": "Detect AI-generated text and images.",
    "description": "REST API for AI content detection. Text detection runs on tropa-2 and returns a calibrated 0–100 score, a verdict band, per-sentence scores, an optional 'possibly humanized' hint and a hidden-character warning. Image detection combines an AI-likelihood score with C2PA content-credential verification and provenance signals. Results are evidence, not proof: route `uncertain` verdicts to a human reviewer.",
    "termsOfService": "https://wasitaigenerated.com/terms",
    "contact": { "name": "WasItAIGenerated", "email": "patrick@wasitaigenerated.com", "url": "https://wasitaigenerated.com/contact" }
  },
  "externalDocs": { "description": "Human-readable API docs", "url": "https://wasitaigenerated.com/docs" },
  "servers": [{ "url": "https://wasitaigenerated.com" }],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "text", "description": "AI-generated text detection" },
    { "name": "image", "description": "AI-generated image detection and content credentials" }
  ],
  "paths": {
    "/api/v1/detect/text": {
      "post": {
        "operationId": "detectText",
        "tags": ["text"],
        "summary": "Detect whether a text was written by an AI model",
        "description": "Scores the text with tropa-2 and returns a document-level verdict, a calibrated 0–100 score and, with `mode: \"depth\"`, a score for every sentence. Costs 1 credit per word. Send at least ~50 words for a reliable result; allow a 30 s timeout.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TextDetectionRequest" },
              "example": { "content": "Paste the text you want to check here. At least fifty words gives a reliable score.", "mode": "depth" }
            }
          }
        },
        "responses": {
          "200": { "description": "Detection result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TextDetectionResult" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "413": { "$ref": "#/components/responses/TooLarge" },
          "502": { "$ref": "#/components/responses/Upstream" }
        }
      }
    },
    "/api/v1/detect/image": {
      "post": {
        "operationId": "detectImage",
        "tags": ["image"],
        "summary": "Detect whether an image was generated by AI",
        "description": "Returns an AI-likelihood verdict plus parsed C2PA content credentials when the file carries them (`verified` is true only when the signature validates). Costs 300 credits. PNG, JPG, GIF or WebP up to 4 MB.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": { "file": { "type": "string", "format": "binary", "description": "The image file (PNG, JPG, GIF, WebP; max 4 MB)." } }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Detection result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImageDetectionResult" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "413": { "$ref": "#/components/responses/TooLarge" },
          "502": { "$ref": "#/components/responses/Upstream" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "description": "API key from https://wasitaigenerated.com/dashboard. Keys start with `wai_`." }
    },
    "responses": {
      "BadRequest": { "description": "Missing or invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Unauthorized": { "description": "Missing or invalid API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "PaymentRequired": { "description": "Not enough credits", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreditError" } } } },
      "Forbidden": { "description": "The account's plan does not include API access", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "TooLarge": { "description": "Input too large", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Upstream": { "description": "Detector temporarily unavailable — retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "TextDetectionRequest": {
        "type": "object",
        "required": ["content"],
        "properties": {
          "content": { "type": "string", "description": "The text to analyse. `text` is accepted as an alias.", "maxLength": 100000 },
          "mode": { "type": "string", "enum": ["depth"], "description": "`depth` returns a real score for every sentence." },
          "model": { "type": "string", "enum": ["tropa-2", "tropa-1"], "default": "tropa-2", "description": "Pin the previous model generation while recalibrating thresholds. Same cost." }
        }
      },
      "Sentence": {
        "type": "object",
        "required": ["text", "isAI", "confidence", "scores"],
        "properties": {
          "text": { "type": "string" },
          "isAI": { "type": "boolean" },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
          "scores": { "type": "object", "properties": { "ai": { "type": "number" }, "human": { "type": "number" } } }
        }
      },
      "TextDetectionResult": {
        "type": "object",
        "required": ["isAI", "confidence", "score", "verdict", "model", "patterns", "analysis", "sentences"],
        "properties": {
          "isAI": { "type": "boolean", "description": "Document-level verdict: `score > 50`." },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1, "description": "How strongly the `isAI` verdict holds." },
          "score": { "type": "number", "minimum": 0, "maximum": 100, "description": "Calibrated probability (0–100) that the text is AI-generated." },
          "verdict": { "type": "string", "enum": ["human", "uncertain", "likely_ai", "ai"], "description": "`human` < 40, `uncertain` 40–69, `likely_ai` 70–89, `ai` ≥ 90." },
          "model": { "type": "string", "description": "The model that scored the text, e.g. `tropa-2`." },
          "patterns": { "type": "array", "items": { "type": "string" } },
          "analysis": { "type": "object", "properties": { "likelihood": { "type": "string" }, "reasoning": { "type": "string" } } },
          "sentences": { "type": "array", "items": { "$ref": "#/components/schemas/Sentence" } },
          "humanizedHint": { "type": "string", "enum": ["possibly_humanized"], "description": "Present only when the model attributes the AI signal mostly to humanizer post-processing. Never `false`; absence means nothing." },
          "inputAnomalies": {
            "type": "object",
            "description": "Present only when hidden characters were stripped before scoring.",
            "properties": { "homoglyph": { "type": "integer" }, "zero_width": { "type": "integer" }, "exotic_space": { "type": "integer" }, "fullwidth": { "type": "integer" }, "variation_selector": { "type": "integer" } }
          },
          "subclassProbs": {
            "type": "object",
            "description": "Class distribution. May be absent.",
            "properties": { "human": { "type": "number" }, "ai": { "type": "number" }, "ai_edited": { "type": "number" }, "humanized": { "type": "number" } }
          }
        }
      },
      "ImageDetectionResult": {
        "type": "object",
        "required": ["isAI", "confidence", "verified", "patterns", "analysis"],
        "properties": {
          "isAI": { "type": "boolean" },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
          "verified": { "type": "boolean", "description": "True only when a C2PA manifest is present and its signature validates." },
          "provenance": { "type": ["object", "null"], "properties": { "platform": { "type": ["string", "null"] }, "watermarks": { "type": "array", "items": { "type": "string" } }, "signals": { "type": "array", "items": { "type": "string" } }, "confidence": { "type": "string", "enum": ["high", "medium", "low", "none"] } } },
          "c2pa": { "type": ["object", "null"], "description": "Parsed content credentials, or null when the file carries none.", "properties": { "vendor": { "type": ["string", "null"] }, "generator": { "type": ["string", "null"] }, "issuer": { "type": ["string", "null"] }, "signedAt": { "type": ["string", "null"], "format": "date-time" }, "signatureValid": { "type": "boolean" }, "trusted": { "type": "boolean" }, "isAI": { "type": "boolean" }, "sourceType": { "type": ["string", "null"] } } },
          "patterns": { "type": "array", "items": { "type": "string" } },
          "analysis": { "type": "object", "properties": { "likelihood": { "type": "string", "enum": ["high", "moderate", "low"] }, "reasoning": { "type": "string" } } },
          "detailed": { "type": "object", "properties": { "scores": { "type": "object", "properties": { "ai": { "type": "number" }, "human": { "type": "number" } } }, "model": { "type": "string" } } }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": { "type": "string", "description": "Short error title." },
          "message": { "type": "string", "description": "What went wrong, in one sentence." },
          "hint": { "type": "string", "description": "How to resolve it." },
          "code": { "type": "string", "description": "Stable machine-readable code, e.g. `insufficient_credits`." }
        }
      },
      "CreditError": {
        "allOf": [
          { "$ref": "#/components/schemas/Error" },
          { "type": "object", "properties": { "required": { "type": "integer" }, "available": { "type": "integer" } } }
        ]
      }
    }
  }
}
