{
  "openapi": "3.1.1",
  "info": {
    "title": "SBOM Explorer API",
    "version": "1.0.0",
    "summary": "Open a CycloneDX or SPDX SBOM: components, licences, dependency tree and known vulnerabilities.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://sbomexplorer.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Open a CycloneDX or SPDX SBOM: components, licences, dependency tree and known vulnerabilities.",
        "description": "Upload or paste a CycloneDX JSON or SPDX 2.x JSON software bill of materials. Lists every component with version, purl and type, classifies licences (permissive, weak / strong / network copyleft, unknown), draws the dependency tree when the SBOM records one, and checks every versioned purl against OSV.dev for known vulnerabilities.\n\nMethodology:\n- CycloneDX: components (including nested ones), metadata.component as root and the dependencies graph. SPDX 2.x: packages, purls from externalRefs, licenseConcluded (else licenseDeclared) and DEPENDS_ON / *_DEPENDENCY_OF / CONTAINS relationships.\n- Licences are classified from SPDX ids and expressions: for \"A OR B\" the more permissive option counts, for \"A AND B\" the more restrictive. NOASSERTION, missing and LicenseRef-* licences are reported as unknown. This flags review needs; it is not legal advice.\n- Dependency depth is the shortest path from the root component (breadth-first); components not reachable from the root are listed as unattached.\n- Vulnerabilities: every versioned purl (qualifiers stripped) is sent to the OSV.dev querybatch API; up to 50 advisories are expanded via /v1/vulns/{id} for severity and the nearest fixed version. Components without a purl cannot be checked.",
        "tags": [
          "security"
        ],
        "x-mcp-tool": "sbom_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SbomExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "CycloneDX app SBOM, licences + tree only (offline)",
                  "value": {
                    "sbom": "{\n \"bomFormat\": \"CycloneDX\",\n \"specVersion\": \"1.5\",\n \"version\": 1,\n \"metadata\": {\n  \"component\": {\n   \"type\": \"application\",\n   \"bom-ref\": \"app\",\n   \"name\": \"demo-web-app\",\n   \"version\": \"1.0.0\"\n  }\n },\n \"components\": [\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/express@4.17.1\",\n   \"name\": \"express\",\n   \"version\": \"4.17.1\",\n   \"purl\": \"pkg:npm/express@4.17.1\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"MIT\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/lodash@4.17.20\",\n   \"name\": \"lodash\",\n   \"version\": \"4.17.20\",\n   \"purl\": \"pkg:npm/lodash@4.17.20\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"MIT\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/body-parser@1.19.0\",\n   \"name\": \"body-parser\",\n   \"version\": \"1.19.0\",\n   \"purl\": \"pkg:npm/body-parser@1.19.0\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"MIT\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/node-forge@0.10.0\",\n   \"name\": \"node-forge\",\n   \"version\": \"0.10.0\",\n   \"purl\": \"pkg:npm/node-forge@0.10.0\",\n   \"licenses\": [\n    {\n     \"expression\": \"(BSD-3-Clause OR GPL-2.0)\"\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/sharp@0.32.0\",\n   \"name\": \"sharp\",\n   \"version\": \"0.32.0\",\n   \"purl\": \"pkg:npm/sharp@0.32.0\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"Apache-2.0\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/%40demo/native-image-lib@8.14.2\",\n   \"name\": \"@demo/native-image-lib\",\n   \"version\": \"8.14.2\",\n   \"purl\": \"pkg:npm/%40demo/native-image-lib@8.14.2\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"LGPL-2.1-or-later\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/internal-utils@2.0.0\",\n   \"name\": \"internal-utils\",\n   \"version\": \"2.0.0\",\n   \"purl\": \"pkg:npm/internal-utils@2.0.0\"\n  }\n ],\n \"dependencies\": [\n  {\n   \"ref\": \"app\",\n   \"dependsOn\": [\n    \"pkg:npm/express@4.17.1\",\n    \"pkg:npm/lodash@4.17.20\",\n    \"pkg:npm/sharp@0.32.0\",\n    \"pkg:npm/internal-utils@2.0.0\"\n   ]\n  },\n  {\n   \"ref\": \"pkg:npm/express@4.17.1\",\n   \"dependsOn\": [\n    \"pkg:npm/body-parser@1.19.0\"\n   ]\n  },\n  {\n   \"ref\": \"pkg:npm/sharp@0.32.0\",\n   \"dependsOn\": [\n    \"pkg:npm/%40demo/native-image-lib@8.14.2\"\n   ]\n  },\n  {\n   \"ref\": \"pkg:npm/internal-utils@2.0.0\",\n   \"dependsOn\": [\n    \"pkg:npm/node-forge@0.10.0\"\n   ]\n  }\n ]\n}",
                    "checkVulnerabilities": false
                  }
                },
                "example2": {
                  "summary": "SPDX 2.3 Python service (offline)",
                  "value": {
                    "sbom": "{\n \"spdxVersion\": \"SPDX-2.3\",\n \"dataLicense\": \"CC0-1.0\",\n \"SPDXID\": \"SPDXRef-DOCUMENT\",\n \"name\": \"demo-python-service\",\n \"documentNamespace\": \"https://example.com/spdx/demo-python-service-1.0\",\n \"creationInfo\": {\n  \"created\": \"2026-10-01T00:00:00Z\",\n  \"creators\": [\n   \"Tool: example\"\n  ]\n },\n \"packages\": [\n  {\n   \"SPDXID\": \"SPDXRef-root\",\n   \"name\": \"demo-python-service\",\n   \"versionInfo\": \"1.0\",\n   \"primaryPackagePurpose\": \"APPLICATION\",\n   \"licenseConcluded\": \"NOASSERTION\",\n   \"licenseDeclared\": \"NOASSERTION\"\n  },\n  {\n   \"SPDXID\": \"SPDXRef-requests\",\n   \"name\": \"requests\",\n   \"versionInfo\": \"2.19.0\",\n   \"licenseConcluded\": \"Apache-2.0\",\n   \"externalRefs\": [\n    {\n     \"referenceCategory\": \"PACKAGE-MANAGER\",\n     \"referenceType\": \"purl\",\n     \"referenceLocator\": \"pkg:pypi/requests@2.19.0\"\n    }\n   ]\n  },\n  {\n   \"SPDXID\": \"SPDXRef-urllib3\",\n   \"name\": \"urllib3\",\n   \"versionInfo\": \"1.23\",\n   \"licenseConcluded\": \"MIT\",\n   \"externalRefs\": [\n    {\n     \"referenceCategory\": \"PACKAGE-MANAGER\",\n     \"referenceType\": \"purl\",\n     \"referenceLocator\": \"pkg:pypi/urllib3@1.23\"\n    }\n   ]\n  },\n  {\n   \"SPDXID\": \"SPDXRef-psycopg2\",\n   \"name\": \"psycopg2\",\n   \"versionInfo\": \"2.9.9\",\n   \"licenseDeclared\": \"LGPL-3.0-or-later\",\n   \"externalRefs\": [\n    {\n     \"referenceCategory\": \"PACKAGE-MANAGER\",\n     \"referenceType\": \"purl\",\n     \"referenceLocator\": \"pkg:pypi/psycopg2@2.9.9\"\n    }\n   ]\n  }\n ],\n \"relationships\": [\n  {\n   \"spdxElementId\": \"SPDXRef-DOCUMENT\",\n   \"relationshipType\": \"DESCRIBES\",\n   \"relatedSpdxElement\": \"SPDXRef-root\"\n  },\n  {\n   \"spdxElementId\": \"SPDXRef-root\",\n   \"relationshipType\": \"DEPENDS_ON\",\n   \"relatedSpdxElement\": \"SPDXRef-requests\"\n  },\n  {\n   \"spdxElementId\": \"SPDXRef-root\",\n   \"relationshipType\": \"DEPENDS_ON\",\n   \"relatedSpdxElement\": \"SPDXRef-psycopg2\"\n  },\n  {\n   \"spdxElementId\": \"SPDXRef-urllib3\",\n   \"relationshipType\": \"DEPENDENCY_OF\",\n   \"relatedSpdxElement\": \"SPDXRef-requests\"\n  }\n ]\n}",
                    "checkVulnerabilities": false
                  }
                },
                "example3": {
                  "summary": "CycloneDX with OSV vulnerability check",
                  "value": {
                    "sbom": "{\n \"bomFormat\": \"CycloneDX\",\n \"specVersion\": \"1.5\",\n \"version\": 1,\n \"metadata\": {\n  \"component\": {\n   \"type\": \"application\",\n   \"bom-ref\": \"app\",\n   \"name\": \"demo-web-app\",\n   \"version\": \"1.0.0\"\n  }\n },\n \"components\": [\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/express@4.17.1\",\n   \"name\": \"express\",\n   \"version\": \"4.17.1\",\n   \"purl\": \"pkg:npm/express@4.17.1\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"MIT\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/lodash@4.17.20\",\n   \"name\": \"lodash\",\n   \"version\": \"4.17.20\",\n   \"purl\": \"pkg:npm/lodash@4.17.20\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"MIT\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/body-parser@1.19.0\",\n   \"name\": \"body-parser\",\n   \"version\": \"1.19.0\",\n   \"purl\": \"pkg:npm/body-parser@1.19.0\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"MIT\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/node-forge@0.10.0\",\n   \"name\": \"node-forge\",\n   \"version\": \"0.10.0\",\n   \"purl\": \"pkg:npm/node-forge@0.10.0\",\n   \"licenses\": [\n    {\n     \"expression\": \"(BSD-3-Clause OR GPL-2.0)\"\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/sharp@0.32.0\",\n   \"name\": \"sharp\",\n   \"version\": \"0.32.0\",\n   \"purl\": \"pkg:npm/sharp@0.32.0\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"Apache-2.0\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/%40demo/native-image-lib@8.14.2\",\n   \"name\": \"@demo/native-image-lib\",\n   \"version\": \"8.14.2\",\n   \"purl\": \"pkg:npm/%40demo/native-image-lib@8.14.2\",\n   \"licenses\": [\n    {\n     \"license\": {\n      \"id\": \"LGPL-2.1-or-later\"\n     }\n    }\n   ]\n  },\n  {\n   \"type\": \"library\",\n   \"bom-ref\": \"pkg:npm/internal-utils@2.0.0\",\n   \"name\": \"internal-utils\",\n   \"version\": \"2.0.0\",\n   \"purl\": \"pkg:npm/internal-utils@2.0.0\"\n  }\n ],\n \"dependencies\": [\n  {\n   \"ref\": \"app\",\n   \"dependsOn\": [\n    \"pkg:npm/express@4.17.1\",\n    \"pkg:npm/lodash@4.17.20\",\n    \"pkg:npm/sharp@0.32.0\",\n    \"pkg:npm/internal-utils@2.0.0\"\n   ]\n  },\n  {\n   \"ref\": \"pkg:npm/express@4.17.1\",\n   \"dependsOn\": [\n    \"pkg:npm/body-parser@1.19.0\"\n   ]\n  },\n  {\n   \"ref\": \"pkg:npm/sharp@0.32.0\",\n   \"dependsOn\": [\n    \"pkg:npm/%40demo/native-image-lib@8.14.2\"\n   ]\n  },\n  {\n   \"ref\": \"pkg:npm/internal-utils@2.0.0\",\n   \"dependsOn\": [\n    \"pkg:npm/node-forge@0.10.0\"\n   ]\n  }\n ]\n}",
                    "checkVulnerabilities": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SbomExplorerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "SbomExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "sbom": {
            "title": "SBOM (CycloneDX or SPDX JSON)",
            "type": "string",
            "maxLength": 5000000
          },
          "sbomFile": {
            "title": "Or upload an SBOM file",
            "type": "object",
            "description": "Upload as {filename, contentType?, contentBase64}. Max 4883 KiB. Accepts .json,.cdx.json,.spdx.json,application/json.",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "checkVulnerabilities": {
            "title": "Check vulnerabilities on OSV.dev",
            "description": "Sends the component purls (not the SBOM) to api.osv.dev.",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "SbomExplorerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "format",
              "specVersion",
              "documentName",
              "root",
              "componentCount",
              "components",
              "licenseSummary",
              "licenseClassCounts",
              "copyleftComponents",
              "unknownLicenseComponents",
              "dependencyEdges",
              "directDependencies",
              "maxDepth",
              "vulnerabilityCheck",
              "vulnerabilities",
              "severityCounts"
            ],
            "properties": {
              "format": {
                "type": "string",
                "enum": [
                  "CycloneDX",
                  "SPDX"
                ]
              },
              "specVersion": {
                "type": "string"
              },
              "documentName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "root": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "componentCount": {
                "type": "integer"
              },
              "components": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "ref",
                    "name",
                    "version",
                    "purl",
                    "type",
                    "licenses",
                    "licenseClass"
                  ],
                  "properties": {
                    "ref": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "purl": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "type": {
                      "type": "string"
                    },
                    "licenses": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "licenseClass": {
                      "type": "string",
                      "enum": [
                        "permissive",
                        "weak-copyleft",
                        "strong-copyleft",
                        "network-copyleft",
                        "public-domain",
                        "proprietary",
                        "unknown"
                      ]
                    }
                  }
                }
              },
              "licenseSummary": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "license",
                    "class",
                    "count"
                  ],
                  "properties": {
                    "license": {
                      "type": "string"
                    },
                    "class": {
                      "type": "string",
                      "enum": [
                        "permissive",
                        "weak-copyleft",
                        "strong-copyleft",
                        "network-copyleft",
                        "public-domain",
                        "proprietary",
                        "unknown"
                      ]
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                }
              },
              "licenseClassCounts": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "copyleftComponents": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "unknownLicenseComponents": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "dependencyEdges": {
                "type": "integer"
              },
              "directDependencies": {
                "type": "integer"
              },
              "maxDepth": {
                "type": "integer"
              },
              "vulnerabilityCheck": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "status",
                  "purlsChecked",
                  "detail"
                ],
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "performed",
                      "skipped",
                      "failed"
                    ]
                  },
                  "purlsChecked": {
                    "type": "integer"
                  },
                  "detail": {
                    "type": "string"
                  }
                }
              },
              "vulnerabilities": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "component",
                    "version",
                    "purl",
                    "id",
                    "aliases",
                    "severity",
                    "summary",
                    "fixedIn"
                  ],
                  "properties": {
                    "component": {
                      "type": "string"
                    },
                    "version": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "purl": {
                      "type": "string"
                    },
                    "id": {
                      "type": "string"
                    },
                    "aliases": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "severity": {
                      "type": "string",
                      "enum": [
                        "CRITICAL",
                        "HIGH",
                        "MODERATE",
                        "LOW",
                        "UNKNOWN"
                      ]
                    },
                    "summary": {
                      "type": "string"
                    },
                    "fixedIn": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "severityCounts": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}