---
title: "Audit an SBOM or AI-BOM: resolve every component by package URL or model id and score it - or return the document enriched"
method: POST
path: "/v1/sbom"
---

# Audit an SBOM or AI-BOM: resolve every component by package URL or model id and score it - or return the document enriched

`POST /v1/sbom`

## Request

- Base URL: `https://api.endoflife.ai`
- URL: `https://api.endoflife.ai/v1/sbom`
- Auth: one of:
  - none
  - API key in header `X-API-Key`
  - HTTP bearer

Body: a CycloneDX JSON or SPDX JSON document, either as the whole body or under a top-level "sbom" key. Limits: 5 MB body, 5,000 components, 32 levels of nesting (413 above any of them). Components carrying a purl resolve only by purl (exact, via endoflife.ai/purl-map.json); components without one resolve by name. Unmatched components are listed with a reason, never guessed. Resolution and counts cover the whole document; scoring is capped at the tier's batch size (anonymous 3, free key 5, Starter 25, Pro 50). With ?enrich=1 (or "enrich": true beside "sbom") the response is the SAME document with lifecycle facts written onto every component: CycloneDX gets properties in the endoflife: namespace (status, product, cycle, eol_date, days_until_eol / days_past_eol, matched_by, score_url; risk_score, risk_grade, risk_band and kev_exposed on the scored subset; status=not-tracked with a reason otherwise) plus a metadata summary and a tools entry; SPDX gets one annotation per package from "Tool: endoflife.ai API" and one document-level annotation. Idempotent - re-enriching replaces earlier endoflife entries. Content-Type is application/vnd.cyclonedx+json or application/spdx+json; the X-Endoflife-Summary header carries the counts.

## Query parameters

- `enrich` '1'
- `strict` '1'
- `warn_days` integer

## Request body

- object: CycloneDX or SPDX JSON, or { sbom: <document> }

## Response `200`

format, component/matched/scored counts, matched_by {purl,cpe,name,model}, low_confidence_matches, summary {past_eol, kev_exposed}, results (Score objects + component + matched_by; match_confidence 'low' and match_note on name-only matches of library-type components), unmatched [{component, reason}]

## Other responses

- `400`: Not a CycloneDX/SPDX JSON document
- `401`: No valid X-API-Key, from 2026-11-16T00:00:00Z (keyless access ends then). The body says how to get a free key (https://endoflife.ai/api#free-key); X-EOL-Key-Status names why a sent key was not honoured.
- `413`: Body over 5 MB, more than 5,000 components, or nesting deeper than 32 levels
- `429`: Daily quota exhausted for this tier (anonymous per IP, keyed per key). Retry-After says when the counter resets (next UTC midnight).

---

[API](https://skmtc.dev/endoflife/apis/endoflife-ai-api.md) · [All operations](https://skmtc.dev/endoflife/apis/endoflife-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/endoflife/apis/endoflife-ai-api/revisions/266133050383?raw)
