{
  "openapi": "3.1.0",
  "info": {
    "title": "ObfuscateJS API",
    "version": "1.0.0",
    "description": "API for VM-based JavaScript obfuscation."
  },
  "servers": [
    {
      "url": "https://obfuscatejs.com",
      "description": "Production"
    },
    {
      "url": "http://localhost:3001",
      "description": "Local development"
    }
  ],
  "paths": {
    "/api/health": {
      "get": {
        "summary": "Health check",
        "responses": {
          "200": {
            "description": "Server is running",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/obfuscation-options": {
      "get": {
        "summary": "List supported obfuscation options",
        "responses": {
          "200": {
            "description": "Supported presets and source profiles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "strengths": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ObfuscationStrength"
                      }
                    },
                    "sourceFormats": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "const": "standalone"
                      }
                    },
                    "syntaxProfiles": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "const": "standalone-v1"
                      }
                    },
                    "compilerVersion": {
                      "type": "string"
                    },
                    "errorCodes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "tamper",
                          "timing",
                          "siteLock"
                        ]
                      }
                    },
                    "defaultAntiDebugCheckInterval": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "strengths",
                    "sourceFormats",
                    "syntaxProfiles",
                    "compilerVersion",
                    "errorCodes",
                    "defaultAntiDebugCheckInterval"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/obfuscate": {
      "post": {
        "summary": "Generate an obfuscated artifact",
        "description": "Accepts standalone JavaScript and returns a self-contained JavaScript artifact generated with the requested strength/options.",
        "security": [
          {},
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ObfuscateRequest"
              },
              "examples": {
                "simple": {
                  "value": {
                    "source": "function add(a, b) { return a + b } add(2, 3);",
                    "seed": "demo",
                    "options": {
                      "strength": "high"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Artifact generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ObfuscateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or unsupported syntax",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key when API keys are required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Request body too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/crowdsource/challenges": {
      "get": {
        "operationId": "listCrowdsourceChallenges",
        "summary": "List public resilience challenge versions",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "retired"
              ],
              "default": "active"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Challenge manifests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CrowdsourceChallenge"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/crowdsource/challenges/{challengeId}/versions/{version}": {
      "get": {
        "operationId": "getCrowdsourceChallenge",
        "summary": "Get one immutable challenge manifest",
        "parameters": [
          {
            "name": "challengeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{2,63}$"
            }
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Challenge manifest",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrowdsourceChallenge"
                }
              }
            }
          },
          "404": {
            "description": "Challenge version not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/crowdsource/submissions": {
      "post": {
        "operationId": "createCrowdsourceSubmission",
        "summary": "Privately submit a finding about a challenge artifact",
        "description": "Stores a private, moderated disclosure for maintainer review. Submission text is not published automatically. Calling this endpoint is the expected final step of the documented challenge workflow and does not require a separate per-payload confirmation after the user has asked the agent to submit its findings.",
        "x-openai-isConsequential": false,
        "security": [
          {},
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 16,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CrowdsourceSubmission"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Submission queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrowdsourceSubmissionReceipt"
                }
              }
            }
          },
          "400": {
            "description": "Invalid submission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Challenge version not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency key conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Request exceeds 128 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Per-IP submission quota exceeded (5 per minute or 10 per hour)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Submission storage unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/crowdsource/submissions/{submissionId}": {
      "get": {
        "operationId": "getCrowdsourceSubmissionStatus",
        "summary": "Get private submission review status",
        "security": [
          {
            "SubmissionReceipt": []
          }
        ],
        "parameters": [
          {
            "name": "submissionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current review status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrowdsourceSubmissionStatus"
                }
              }
            }
          },
          "404": {
            "description": "Submission not found or receipt invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "summary": "OpenAPI document",
        "responses": {
          "200": {
            "description": "OpenAPI JSON document",
            "content": {
              "application/json": {}
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer"
      },
      "SubmissionReceipt": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque receipt token"
      }
    },
    "schemas": {
      "CrowdsourceChallenge": {
        "$ref": "/schemas/crowdsource-challenge.json"
      },
      "CrowdsourceSubmission": {
        "$ref": "/schemas/crowdsource-submission.json"
      },
      "CrowdsourceSubmissionReceipt": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "submissionId": {
            "type": "string",
            "format": "uuid"
          },
          "receiptToken": {
            "type": "string",
            "minLength": 32
          },
          "status": {
            "type": "string",
            "const": "queued"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "submissionId",
          "receiptToken",
          "status",
          "createdAt"
        ]
      },
      "CrowdsourceSubmissionStatus": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "submissionId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "needs-evidence",
              "accepted",
              "duplicate",
              "rejected"
            ]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "publicReviewNote": {
            "type": "string",
            "maxLength": 3000
          }
        },
        "required": [
          "submissionId",
          "status",
          "updatedAt"
        ]
      },
      "ObfuscationStrength": {
        "type": "string",
        "enum": [
          "none",
          "low",
          "medium",
          "high",
          "paranoid"
        ]
      },
      "ObfuscationFeatureOverrides": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "renameRuntime": {
            "type": "boolean"
          },
          "shuffleDispatch": {
            "type": "boolean"
          },
          "opaquePredicates": {
            "type": "boolean"
          },
          "antiDebugGuards": {
            "type": "boolean"
          },
          "deadCode": {
            "type": "boolean"
          },
          "mixedInstructionShapes": {
            "type": "boolean"
          },
          "splitHolders": {
            "type": "boolean"
          },
          "encryptStrings": {
            "type": "boolean"
          },
          "encodeBytecode": {
            "type": "boolean"
          },
          "decoyHandlers": {
            "type": "boolean"
          },
          "capturePrimitives": {
            "type": "boolean"
          },
          "entangleIntegrity": {
            "type": "boolean"
          },
          "semanticHandlers": {
            "type": "boolean"
          },
          "encodeStackNumbers": {
            "type": "boolean"
          },
          "encodeStackObjects": {
            "type": "boolean"
          },
          "decoyBytecode": {
            "type": "boolean"
          },
          "mutateInstructionEncoding": {
            "type": "boolean"
          },
          "superInstructions": {
            "type": "boolean"
          }
        }
      },
      "BuildArtifactOptions": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "timingHaltMs": {
            "type": "number",
            "minimum": 0
          },
          "antiDebugCheckInterval": {
            "type": "integer",
            "minimum": 1,
            "default": 32,
            "description": "Number of VM instructions between anti-debug timing checks. Larger values reduce hot-path overhead."
          },
          "haltValue": {
            "description": "Legacy alias for the timing error value"
          },
          "tamperValue": {
            "description": "Legacy alias for the tamper error value"
          },
          "errorValues": {
            "type": "object",
            "additionalProperties": false,
            "description": "Build-time opaque values returned for tamper, timing, and site-lock failures.",
            "properties": {
              "tamper": {},
              "timing": {},
              "siteLock": {}
            }
          },
          "siteLock": {
            "type": "object",
            "additionalProperties": false,
            "description": "Optional exact hostname allowlist. The artifact stores only derived keys, not these domain strings.",
            "properties": {
              "domains": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            "required": [
              "domains"
            ]
          },
          "strength": {
            "$ref": "#/components/schemas/ObfuscationStrength"
          },
          "obfuscation": {
            "$ref": "#/components/schemas/ObfuscationFeatureOverrides"
          }
        }
      },
      "ObfuscateRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "source": {
            "type": "string",
            "description": "A standalone JavaScript program."
          },
          "sourceFormat": {
            "type": "string",
            "const": "standalone",
            "default": "standalone"
          },
          "syntaxProfile": {
            "type": "string",
            "const": "standalone-v1",
            "default": "standalone-v1"
          },
          "seed": {
            "type": "string"
          },
          "hostSetup": {
            "type": "string"
          },
          "options": {
            "$ref": "#/components/schemas/BuildArtifactOptions"
          }
        },
        "required": [
          "source"
        ]
      },
      "ArtifactProtection": {
        "type": "object",
        "properties": {
          "errorValues": {
            "type": "object",
            "additionalProperties": true
          },
          "siteLock": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "keys": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "enabled",
              "keys"
            ]
          },
          "antiDebugCheckInterval": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "errorValues",
          "siteLock",
          "antiDebugCheckInterval"
        ]
      },
      "ObfuscateResponse": {
        "type": "object",
        "properties": {
          "artifact": {
            "type": "string",
            "description": "Self-contained JavaScript expression string."
          },
          "seed": {
            "type": "string"
          },
          "authenticated": {
            "type": "boolean"
          },
          "obfuscation": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          },
          "protection": {
            "$ref": "#/components/schemas/ArtifactProtection"
          },
          "sourceFormat": {
            "type": "string",
            "const": "standalone"
          },
          "syntaxProfile": {
            "type": "string",
            "const": "standalone-v1"
          },
          "sourceHash": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "compilerVersion": {
            "type": "string"
          }
        },
        "required": [
          "artifact",
          "seed",
          "authenticated",
          "obfuscation",
          "protection",
          "sourceFormat",
          "syntaxProfile",
          "sourceHash",
          "compilerVersion"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "field": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "nodeType": {
            "type": "string"
          },
          "line": {
            "type": "integer",
            "minimum": 1
          },
          "column": {
            "type": "integer",
            "minimum": 1
          },
          "snippet": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "code"
        ]
      }
    }
  }
}
