{
  "openapi": "3.1.0",
  "info": {
    "title": "JavaScript Obfuscator HTTP API",
    "summary": "Protect JavaScript source over HTTP and read the resulting build report.",
    "description": "The protection endpoint takes a project of one or more JavaScript files plus a set of protection options, and returns the protected code with a machine-readable report.\n\nCredentials are optional. A request with no `APIKey` and no `APIPwd` runs on the anonymous free tier, which is rate limited per IP address; supplying a key and password from the dashboard raises the ceiling and unlocks the paid option set. Rate-limited requests return HTTP 429 with `ErrorCode: \"RateLimited\"` and a `Retry-After` header.\n\nThe full protection option catalogue is documented at https://javascriptobfuscator.com/docs/npmoptions.aspx and is deliberately modelled here as free-form properties on the request body, because it evolves independently of this document.",
    "version": "1.0.1",
    "termsOfService": "https://javascriptobfuscator.com/terms.aspx",
    "contact": {
      "name": "JavaScript Obfuscator",
      "url": "https://javascriptobfuscator.com/contact.aspx"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://javascriptobfuscator.com/terms.aspx"
    }
  },
  "externalDocs": {
    "description": "HTTP API and CLI documentation",
    "url": "https://javascriptobfuscator.com/docs/npmcli.aspx"
  },
  "servers": [
    {
      "url": "https://javascriptobfuscator.com",
      "description": "Production. Use the apex host exactly as written - a POST to the www host or to a differently-cased path is answered with a permanent redirect, and a redirected POST becomes a GET."
    }
  ],
  "tags": [
    {
      "name": "protection",
      "description": "Protect JavaScript source."
    },
    {
      "name": "service",
      "description": "Service health."
    }
  ],
  "paths": {
    "/HttpApi.ashx": {
      "post": {
        "tags": [
          "protection"
        ],
        "operationId": "protectProject",
        "summary": "Protect a project of JavaScript files",
        "description": "Sends one or more files and returns the protected output.\n\nWithout credentials the request runs on the anonymous free tier: batched files, a per-request size ceiling, no VM protection, and a per-IP rate limit. Note that the limiter keys on IP alone, so shared build egress (hosted CI runners, corporate NAT) shares one budget.",
        "security": [
          {
            "projectCredentials": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Project"
              },
              "examples": {
                "anonymous": {
                  "summary": "Free tier, no credentials",
                  "value": {
                    "Items": [
                      {
                        "FileName": "app.js",
                        "FileCode": "function greet(n){var m='hello '+n;console.log(m);return m;}"
                      }
                    ]
                  }
                },
                "authenticated": {
                  "summary": "With dashboard credentials and options",
                  "value": {
                    "APIKey": "<key from the dashboard>",
                    "APIPwd": "<password from the dashboard>",
                    "Name": "checkout-bundle",
                    "ReleaseLabel": "release-2026-Q3",
                    "ReplaceNames": true,
                    "EncodeStrings": true,
                    "Items": [
                      {
                        "FileName": "dist/app.js",
                        "FileCode": "/* ... */"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request was processed. Inspect `Type` - it is `Succeed` on success and `Error`, `Exception`, `SourceError` or `LoginFailed` otherwise. A non-success `Type` is still returned with HTTP 200.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                },
                "examples": {
                  "succeed": {
                    "summary": "Protected output",
                    "value": {
                      "Type": "Succeed",
                      "Items": [
                        {
                          "FileName": "app.js",
                          "FileCode": "function greet(b){var a=\"\\x68\\x69 \"+b;console.log(a);return a}"
                        }
                      ],
                      "ErrorCode": null,
                      "Message": null,
                      "Report": {
                        "InputBytes": 61,
                        "OutputBytes": 74,
                        "InputFiles": 1,
                        "OutputFiles": 1
                      }
                    }
                  },
                  "missingItems": {
                    "summary": "Rejected before any work is done",
                    "value": {
                      "Type": "Error",
                      "ErrorCode": "ArgumentError",
                      "Message": "Require Items"
                    }
                  },
                  "badCredentials": {
                    "summary": "Rejected key/password pair",
                    "value": {
                      "Type": "Error",
                      "ErrorCode": "ArgumentError",
                      "Message": "Invalid APIKey or APIPwd"
                    }
                  },
                  "sourceError": {
                    "summary": "Input did not parse",
                    "value": {
                      "Type": "SourceError",
                      "ErrorCode": "SourceError",
                      "FileName": "0:app.js",
                      "LineNumber": null,
                      "Message": "Error parsing app.js , Unexpected Token : None"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The request body exceeds the 256 MB API limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                },
                "example": {
                  "Type": "Error",
                  "ErrorCode": "RequestTooLarge",
                  "Message": "The request body exceeds the 256 MB API limit."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Anonymous requests are capped per IP address; signing in raises the ceiling substantially.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                },
                "example": {
                  "Type": "Error",
                  "ErrorCode": "RateLimited",
                  "Message": "Free anonymous runs are rate limited per IP address. Retry after 3600 seconds, or sign in with `javascriptobfuscator login`."
                }
              }
            }
          }
        }
      }
    },
    "/v1/health.ashx": {
      "get": {
        "tags": [
          "service"
        ],
        "operationId": "getHealth",
        "summary": "Service health",
        "description": "Unauthenticated liveness check returning a small JSON document.",
        "security": [
          {}
        ],
        "responses": {
          "200": {
            "description": "The service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "service": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "uptimeSeconds": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                },
                "example": {
                  "ok": true,
                  "service": "javascriptobfuscator",
                  "version": "0.0.0.0",
                  "uptimeSeconds": 12345
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "projectCredentials": {
        "type": "apiKey",
        "in": "cookie",
        "name": "APIKey",
        "description": "Credentials are NOT sent as a header or cookie despite the transport hint this field requires. They travel as the `APIKey` and `APIPwd` properties of the JSON request body, obtained from the javascriptobfuscator.com dashboard. Omit both to run on the anonymous free tier. This scheme is declared only so generated clients surface the credential pair; treat the request body as authoritative."
      }
    },
    "schemas": {
      "Project": {
        "type": "object",
        "description": "A protection request. Protection options are supplied as additional top-level properties - see https://javascriptobfuscator.com/docs/npmoptions.aspx for the catalogue and which plan each one requires.",
        "required": [
          "Items"
        ],
        "properties": {
          "Items": {
            "type": "array",
            "description": "The files to protect. Files are batched into a single request.",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/FileItem"
            }
          },
          "APIKey": {
            "type": "string",
            "description": "Dashboard API key. Omit for the anonymous free tier."
          },
          "APIPwd": {
            "type": "string",
            "description": "Dashboard API password. Omit for the anonymous free tier."
          },
          "Name": {
            "type": "string",
            "description": "Project name recorded against the run."
          },
          "ReleaseLabel": {
            "type": "string",
            "description": "Groups dashboard audit entries, so a caller can retrieve every build tagged with a branch or commit."
          },
          "MixedServer": {
            "type": "boolean",
            "description": "Treat input as mixed server-script and JavaScript rather than plain JavaScript."
          },
          "AnalyzeOnly": {
            "type": "boolean",
            "description": "Run compatibility analysis and reporting without producing protected output or consuming a protection run."
          }
        },
        "additionalProperties": {
          "description": "Any documented protection option, for example ReplaceNames, EncodeStrings, SelfDefending, TargetVersion."
        }
      },
      "FileItem": {
        "type": "object",
        "required": [
          "FileName",
          "FileCode"
        ],
        "properties": {
          "FileName": {
            "type": "string",
            "description": "Path-like name. The extension selects how the file is treated (.js, .jsx, .html and others).",
            "examples": [
              "dist/app.js"
            ]
          },
          "FileCode": {
            "type": "string",
            "description": "The file's source. On a successful response the same property carries the protected output."
          }
        }
      },
      "Result": {
        "type": "object",
        "description": "Returned for every request, including failures. `Type` is the outcome; the HTTP status is not the whole story.",
        "required": [
          "Type"
        ],
        "properties": {
          "Type": {
            "type": "string",
            "enum": [
              "Succeed",
              "Error",
              "Exception",
              "SourceError",
              "LoginFailed"
            ],
            "description": "`Succeed` means `Items` carries protected output. `SourceError` means the submitted JavaScript could not be parsed - `FileName` and `Message` say where. A rejected credential pair is returned as `Type: \"Error\"` with `ErrorCode: \"ArgumentError\"` and `Message: \"Invalid APIKey or APIPwd\"` (measured 2026-09-02); the `LoginFailed` value exists in the enum but is not what this endpoint emits for bad credentials."
          },
          "Items": {
            "type": [
              "array",
              "null"
            ],
            "description": "Protected files, present when `Type` is `Succeed`.",
            "items": {
              "$ref": "#/components/schemas/FileItem"
            }
          },
          "ErrorCode": {
            "type": [
              "string",
              "null"
            ],
            "examples": [
              "ArgumentError",
              "RateLimited",
              "RequestTooLarge"
            ]
          },
          "Message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Human-readable explanation, safe to show a developer."
          },
          "FileName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The file a source error came from. May be prefixed with the item's index, e.g. `\"0:a.js\"`."
          },
          "LineNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "The line a source error came from, when the parser can attribute one; null otherwise."
          },
          "ExceptionToString": {
            "type": [
              "string",
              "null"
            ]
          },
          "Report": {
            "$ref": "#/components/schemas/Report"
          }
        }
      },
      "Report": {
        "type": [
          "object",
          "null"
        ],
        "description": "Build report for the run. Additional properties are added over time; treat it as open.",
        "properties": {
          "InputBytes": {
            "type": "integer"
          },
          "OutputBytes": {
            "type": "integer"
          },
          "InputFiles": {
            "type": "integer"
          },
          "OutputFiles": {
            "type": "integer"
          },
          "InputLines": {
            "type": "integer"
          },
          "OutputLines": {
            "type": "integer"
          },
          "GeneratedUtc": {
            "type": "string",
            "format": "date-time"
          },
          "EnabledOptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "CompatibilityWarnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "EngineWarnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "Warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": true
      }
    }
  }
}
