{
  "openapi": "3.1.0",
  "info": {
    "title": "HumanGPT API",
    "version": "1.0.0",
    "summary": "Humanize AI text and detect AI writing over REST.",
    "description": "POST AI-generated text and get back text that reads like a person wrote it, with the real GPTZero score of the result. Free API key for any verified HumanGPT account (dashboard > API keys). API calls and the website share one word allowance. Docs: https://humangpt.io/developers and https://humangpt.io/api-docs",
    "contact": { "name": "HumanGPT", "email": "hello@humangpt.io", "url": "https://humangpt.io/developers" }
  },
  "servers": [
    { "url": "https://api.humangpt.io/v1", "description": "Primary" },
    { "url": "https://humangpt.io/api/v1", "description": "Same API on the main domain" }
  ],
  "security": [{ "bearerAuth": [] }, { "apiKeyHeader": [] }],
  "paths": {
    "/humanize": {
      "post": {
        "operationId": "humanize",
        "summary": "Humanize AI text",
        "description": "Rewrites AI-generated text so it reads like a person wrote it. Runs the same pipeline as the web tool under the key owner's plan. Free keys run the standard engine; Pro and Founder keys run the premium engine, which checks many candidate rewrites against GPTZero and retries once when the best still reads as AI.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HumanizeRequest" },
            "example": { "text": "Artificial intelligence has fundamentally transformed the way modern organizations approach content creation, enabling teams to produce more material in less time than ever before.", "mode": "medium" } } }
        },
        "responses": {
          "200": { "description": "The humanized text.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HumanizeResponse" } } } },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "402": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "413": { "$ref": "#/components/responses/Error" },
          "415": { "$ref": "#/components/responses/Error" },
          "422": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" },
          "500": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/detect": {
      "post": {
        "operationId": "detect",
        "summary": "Check text for AI writing",
        "description": "Runs the HumanGPT detector over the text. Up to 8,000 words per call. Also served at /check.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DetectRequest" } } }
        },
        "responses": {
          "200": { "description": "The verdict.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DetectResponse" } } } },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "402": { "$ref": "#/components/responses/Error" },
          "413": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" },
          "500": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/usage": {
      "get": {
        "operationId": "usage",
        "summary": "Your plan and remaining words",
        "description": "The key owner's current plan and allowance. API calls and the website draw on the same allowance.",
        "responses": {
          "200": { "description": "Usage.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageResponse" } } } },
          "401": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "hgpt_<40 hex>", "description": "Authorization: Bearer hgpt_..." },
      "apiKeyHeader": { "type": "apiKey", "in": "header", "name": "x-api-key" }
    },
    "responses": {
      "Error": {
        "description": "Error envelope. Free keys also get upgrade_url on plan-limit errors.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "HumanizeRequest": {
        "type": "object",
        "required": ["text"],
        "properties": {
          "text": { "type": "string", "description": "AI text to humanize. At least 15 words. Up to 1,500 words per call on a free key, 8,000 on Pro and Founder." },
          "mode": { "type": "string", "enum": ["light", "medium", "heavy", "subtle", "natural", "strong"], "default": "medium", "description": "Rewrite strength. subtle/natural/strong are aliases of light/medium/heavy." },
          "purpose": { "type": "string", "enum": ["general", "academic", "essay", "article", "cover letter", "marketing", "story", "report", "business", "legal"], "default": "general", "description": "Free keys: general, academic, essay. The rest are Pro." },
          "reading": { "type": "string", "enum": ["highschool", "university", "doctorate", "journalist"], "default": "university", "description": "Free keys: highschool, university. doctorate and journalist are Pro." },
          "freeze": { "type": "array", "items": { "type": "string" }, "description": "Words or phrases returned exactly as sent. A comma-separated string is also accepted." },
          "enhanced": { "type": "boolean", "default": false, "description": "Rewrite one step harder. Pro." },
          "language": { "type": "string", "default": "en", "enum": ["en", "es", "fr", "de", "it", "pt", "ru", "tr", "nl", "pl", "sv", "no", "da", "fi", "ja", "ko", "zh", "ar", "hi", "auto"], "description": "The engine is tuned for English, where results are best." },
          "use_voice": { "type": "boolean", "default": true, "description": "Apply the owner's saved Brand Voice (Pro)." },
          "premium": { "type": "boolean", "default": true, "description": "Pro and Founder: false skips the premium engine for this call." }
        }
      },
      "HumanizeResponse": {
        "type": "object",
        "properties": {
          "id": { "type": ["integer", "null"], "description": "Run id, also in the owner's history." },
          "object": { "type": "string", "const": "humanization" },
          "output": { "type": "string", "description": "The humanized text." },
          "words_in": { "type": "integer" },
          "words_out": { "type": "integer" },
          "ai_score": { "type": ["number", "null"], "minimum": 0, "maximum": 1, "description": "Real GPTZero probability that the output is AI, from the check run on this call. null when the check was skipped." },
          "engine": { "type": "string", "enum": ["premium", "standard"] },
          "resisted": { "type": "boolean", "description": "True when the text still read as AI after two full attempts. Not charged." },
          "message": { "type": ["string", "null"], "description": "Advice when resisted is true." },
          "degraded": { "type": "boolean", "description": "True if the rewrite engine was unavailable and the output is unlaundered." },
          "mode": { "type": "string" },
          "purpose": { "type": "string" },
          "reading": { "type": "string" },
          "enhanced": { "type": "boolean" },
          "plan": { "type": "string", "enum": ["free", "pro", "founder"] },
          "usage": {
            "type": "object",
            "properties": {
              "words_remaining": { "type": ["integer", "null"] },
              "words_limit": { "type": ["integer", "null"], "description": "null when the plan has no enforced cap." },
              "period": { "type": ["string", "null"], "enum": ["day", "month", null] },
              "resets_at": { "type": ["string", "null"], "format": "date-time" }
            }
          },
          "input_words": { "type": "integer", "description": "Same as words_in (original field name)." },
          "output_words": { "type": "integer", "description": "Same as words_out (original field name)." },
          "quota_remaining": { "type": ["integer", "null"], "description": "Same as usage.words_remaining (original field name)." }
        }
      },
      "DetectRequest": {
        "type": "object",
        "required": ["text"],
        "properties": {
          "text": { "type": "string", "description": "Text to check. Up to 8,000 words." },
          "language": { "type": "string", "default": "en" }
        }
      },
      "DetectResponse": {
        "type": "object",
        "properties": {
          "object": { "type": "string", "const": "detection" },
          "request_id": { "type": "string" },
          "verdict": { "type": "string", "enum": ["human", "ai", "mixed"] },
          "verdict_label": { "type": "string" },
          "score": { "type": "number", "minimum": 0, "maximum": 1, "description": "Probability the text is AI-written." },
          "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
          "abstain": { "type": "boolean", "description": "True when the signals disagree (verdict mixed)." },
          "signals": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "score": { "type": ["number", "null"] }, "weight": { "type": "number" } } } },
          "preprocessing": { "type": ["object", "null"], "description": "Evasion checks: unicode normalization, zero-width and homoglyph counts." },
          "model_versions": { "type": "object" },
          "plan": { "type": "string" },
          "total_latency_ms": { "type": "integer" }
        }
      },
      "UsageResponse": {
        "type": "object",
        "properties": {
          "object": { "type": "string", "const": "usage" },
          "plan": { "type": "string", "enum": ["free", "pro", "founder"] },
          "key": { "type": "object", "properties": { "prefix": { "type": "string" }, "label": { "type": ["string", "null"] } } },
          "period": { "type": ["string", "null"], "enum": ["day", "month", null] },
          "words_used": { "type": ["integer", "null"] },
          "words_limit": { "type": ["integer", "null"] },
          "words_remaining": { "type": ["integer", "null"] },
          "month": { "type": "object", "description": "Free only: the 30-day total.", "properties": { "words_used": { "type": ["integer", "null"] }, "words_limit": { "type": ["integer", "null"] } } },
          "runs_today": { "type": ["integer", "null"], "description": "Free only." },
          "max_words_per_request": { "type": "integer" },
          "requests_per_minute": { "type": "integer" },
          "engine": { "type": "string", "enum": ["standard", "premium"] }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "string", "enum": ["missing_api_key", "invalid_api_key", "endpoint_not_allowed", "invalid_json", "missing_text", "invalid_mode", "invalid_purpose", "invalid_reading", "invalid_request", "quota_exceeded", "monthly_limit", "exceeds_allowance", "plan_feature", "forbidden", "input_too_long", "unsupported_input", "declined", "rate_limited", "daily_run_limit", "engine_error", "detect_error"] },
              "message": { "type": "string" },
              "words_remaining": { "type": ["integer", "null"] },
              "max_words": { "type": ["integer", "null"] },
              "max_words_pro": { "type": ["integer", "null"] },
              "retry_after_seconds": { "type": "integer" },
              "upgrade_url": { "type": "string", "format": "uri" }
            }
          }
        }
      }
    }
  }
}
