CI guides
Each guide makes the SBOM in your build, then uploads it to Declarable with the GitHub Action, the GitLab job or a shell script.
Uploading from CI or the API is part of the Maker plan and the ones above it. On the Free plan the Settings page shows no key form. Without a key you can still run the free SBOM check and upload a release by hand in the app.
Sign in, open your product, then Settings → API keys. Create a key there — it is shown once. That same page shows these steps again with your product id already filled in, so once the key exists you may not need this page at all.
- Zephyr
Run west spdx after the build, then upload the files in build/spdx.
- nRF Connect SDK
Nordic’s version of Zephyr: the same west spdx steps, started from the sdk-nrf manifest.
- Yocto
Turn on create-spdx, run bitbake, then upload the SBOM it writes — one .spdx.json document from Yocto 5.1 on, a .spdx.tar.zst archive before that.
- ESP-IDF
Run idf.py build, create the SBOM with esp-idf-sbom, then upload it.
- Buildroot
Run make show-info into a file, then upload that JSON.
- PlatformIO
Install one environment’s libraries, then upload platformio.ini and their manifests with their paths. One upload per environment.
- Arduino
Save the library list that arduino-cli compile prints as JSON, then upload that one file.
The pipelines on these pages are examples to copy, not a view of your own CI files. The files they tell you to copy into your repository are on the files page. The upload itself is described in the API reference.
Sending the same files to Dependency-Track
For teams that already run Dependency-Track: keep using it, and add the decisions you recorded here. You upload two files yourself. This is Dependency-Track’s own API, called by you. Declarable does not connect to your Dependency-Track server.
Download the two files
The inventory can be fetched with an API key that has the
products:readscope; the API reference describes the route. The VEX has no key route yet: download it from the product’s Vulnerabilities page while signed in, and save it asvex.cdx.json.shcurl -sS -o inventory.cdx.json \ -H "Authorization: Bearer $DECLARABLE_API_KEY" \ "$DECLARABLE_URL/api/v1/products/<product-id>/releases/<release-id>/sbom?format=cyclonedx" # <release-id> is the "id" of a release in GET /api/v1/products/<product-id>/releases.Upload the inventory
Needs the
BOM_UPLOADpermission, plusPROJECT_CREATION_UPLOADbecause the command creates the project if it is missing. Use our inventory, not your raw build SBOM: the VEX points at component references that exist in our inventory of that release.shcurl -sS -X POST "$DT_URL/api/v1/bom" \ -H "X-Api-Key: $DT_API_KEY" \ -F "autoCreate=true" \ -F "projectName=$DT_PROJECT" \ -F "projectVersion=$DT_VERSION" \ -F "bom=@inventory.cdx.json" # The answer is {"token":"<uuid>"}. Keep the uuid as DT_TOKEN.Wait until Dependency-Track has processed it
Same
BOM_UPLOADpermission. This matters: a VEX sent before the inventory is processed has no effect (reported in Dependency-Track issue #2596).shcurl -sS "$DT_URL/api/v1/bom/token/$DT_TOKEN" -H "X-Api-Key: $DT_API_KEY" # Repeat until it answers {"processing":false}.Upload the VEX
Needs the
VULNERABILITY_ANALYSISpermission. Dependency-Track applies a VEX only to findings that already exist; it never creates them, and it skips a statement with nothing to apply to. Its docs say statements are matched to components “by identity rather than by identifier” and to findings by vulnerability ID, so uploading our inventory first is the safe order; we have not confirmed what happens with a different inventory.shcurl -sS -X POST "$DT_URL/api/v1/vex" \ -H "X-Api-Key: $DT_API_KEY" \ -F "projectName=$DT_PROJECT" \ -F "projectVersion=$DT_VERSION" \ -F "vex=@vex.cdx.json"
Set DT_URL (your server), DT_API_KEY (a team key in Dependency-Track, never committed), DT_PROJECT and DT_VERSION first. Source: Dependency-Track’s CI/CD page and VEX page, read 9 October 2026; the token and VEX endpoints from its source code. Not run; read from Dependency-Track’s docs.