Self-Built Software Discovery API: Asynchronous Processing of SBOM File Ingestions (April 7, 2025)

Learn what’s changing in the Self-Built Software Discovery API and how to prepare for these changes to avoid any issues with your integrations.

Overview

We're introducing enhancements to the Self-Built Software Discovery REST API to improve SBOM file ingestion and system performance for our customers. These changes will come into effect on April 7, 2025, following a transition period. During this period, you can test and familiarize yourself with the new behavior while continuing to use your current API implementation. However, after the transition period, only the new behavior will be supported.

  • Transition period: March 10, 2025 – April 6, 2025
  • Switchover date: April 7, 2025

📘

Note

If your current implementation of /factSheets/{factSheetId}/sboms does not rely on the HTTP status code or the payload, these changes will not affect you. Otherwise, you will need to update your integrations as detailed below.

During the transition period, you can try out the updated API to see how the behavior will change. For details, see Test the New API Behavior During the Transition Period.

To learn more about self-built software discovery and SBOMs, refer to:

Background

These API updates are designed to significantly improve SBOM file ingestion and enhance system efficiency. The changes are driven by two primary factors:

  • Scalability and resilience: While our systems can handle the current load, we anticipate increased SBOM traffic. To maintain optimal user experience and ensure our systems can manage this growth, we're transitioning to asynchronous processing of SBOM files. This shift will address potential hurdles and ensure continued high performance.
  • Extensibility: Currently, our system processes SBOM files to show library reuse in the wider business context (for example, the log4j case) and intelligently match technology stacks. Switching to asynchronous processing will allow us to add additional post-processing mechanisms in the future, such as vulnerability checks. Though there's no established timeline for these enhancements, we aim to have the right technical foundation in place for future implementation.

What’s Changing

The changes affect the following endpoint on the Self-Built Software Discovery API:

MethodEndpointSchema
POST/factSheets/{factSheetId}/sbomsReference

We're also adding a new endpoint for tracking the processing job status.

📘

Note

While the processing of SBOM files will be asynchronous, the validation of request payloads will remain unchanged. The API immediately validates payloads upon receiving requests.

Response Status Code

The HTTP response status code changes as follows:

  • Current code: 201 (Created)
  • New code: 202 (Accepted)

Enhanced Response Payload

The following fields are added to the data object in the response payload:

FieldDescription
jobIdIdentifier of the processing job.
workspaceIdIdentifier of the workspace.
statusCurrent status of the job.
errorMessageError message provided when the job fails.
created_atTimestamp indicating when the job was created.
plannedExecutionAtTimestamp indicating the scheduled execution time.
updatedAtTimestamp indicating when the job was last updated.

Current payload:

{
  "data": {
    "message": "SBOM file successfully processed"
  }
}

New payload:

{
  "data": {
    "jobId": "5e28492a-5d0e-4dfb-9935-503b0463d0c5",
    "workspaceId": "56f7d2ae-4b03-4c4d-bfbb-b6aae4aa1eb9",
    "status": "SCHEDULED",
    "errorMessage": null,
    "createdAt": "2025-01-28T07:53:25.358Z",
    "plannedExecutionAt": "2025-01-28T07:55:22.102Z",
    "updatedAt": "2025-01-28T07:53:25.358Z"
  }
}

New Endpoint for Tracking the Job Status

We’re introducing a new endpoint for tracking the processing job status using the jobId returned in the response payload. Job statuses are maintained for 48 hours after submitting SBOM files.

MethodEndpointSchema
GET/sboms/jobs/{jobId}Reference

Response payload:

{
  "data": {
    "id": "1a10138e-302b-4797-9038-058e14d1a0b6",
    "workspaceId": "56914519-c634-41bb-b163-866333b907ee",
    "status": "SUCCEEDED",
    "errorMessage": null,
    "createdAt": "2025-03-06T07:33:25.833318Z",
    "plannedExecutionAt": "2025-03-06T07:33:31.479195Z",
    "updatedAt": "2025-03-06T07:33:31.479195Z"
  }
}

What You Need to Do

If your current implementation of /factSheets/{factSheetId}/sboms does not rely on the HTTP status code or the payload, these changes will not affect you. Otherwise, you will need to update your integrations as detailed below.

Adjust Your Integrations for the New Response Code and Payload

Update your systems to recognize the new 202 HTTP response status code and parse additional response payload fields.

Pseudo code to handle the new status code:

function handleApiResponse(response):
  if response.statusCode == 202:
    print("Request accepted. Processing asynchronously.")
    jobId = response.payload.data.jobId
    jobStatus = response.payload.data.status
    jobCreationTime = response.payload.data.created_at
    print("Job ID:", jobId)
    print("Job Status:", jobStatus)
    print("Job Created At:", jobCreationTime)
    return jobId # Save Job ID for status checks
  elif response.statusCode == 201:
    print("Request processed successfully.")
  else:
  print("Error with request. Status Code:", response.statusCode)

# Example of using the function with a hypothetical API response
apiResponse = {
  "statusCode": 202,
  "payload": {
    "data": {
      "jobId": "5e28492a-5d0e-4dfb-9935-503b0463d0c5",
      "status": "In Progress",
      "created_at": "2021-07-01T12:00:00Z"
    }
  }
}
jobId = handleApiResponse(apiResponse)

Adapt Your Requests for Asynchronous Processing

Implement logic to periodically check the job status, accommodating the change from synchronous to asynchronous processing.

Pseudo code to handle the job status:

function checkJobStatus(jobId):
  statusEndpoint = "https://api.example.com/job/status/" + jobId
  response = makeHttpRequest(statusEndpoint)
  if response.statusCode == 200:
    jobStatus = response.payload.jobStatus
    print("Current Job Status:", jobStatus)
    return jobStatus
  else:
    print("Failed to retrieve job status. Status Code:", response.statusCode)

function periodicStatusCheck(jobId, interval):
  import time
  jobComplete = False
  while not jobComplete:
    jobStatus = checkJobStatus(jobId)
    if jobStatus == "SUCCEEDED" or jobStatus == "FAILED":
      jobComplete = True
      print("Final Job Status:", jobStatus)
    else:
      print("Continuing to monitor job status...")
      time.sleep(interval) # Delay next check by 'interval' seconds

# Example usage with a job ID and a check interval of 30 seconds
periodicStatusCheck(jobId, 30)

Test the New API Behavior During the Transition Period

During the transition period, which lasts until April 7, 2025, you can try out the new behavior. To do this, add the x-leanix-dev header set to dev to your current API requests.

Example request:

curl --request POST \
  --url https://{SUBDOMAIN}.leanix.net/services/technology-discovery/v1/factSheets/{factSheetId}/sboms \
  --header 'authorization: Bearer {API_TOKEN}' \
  --header 'content-type: multipart/form-data' \
  --header 'x-leanix-dev: dev' \
  --form sbom=<sbom file location>

For authentication details, see Authentication to SAP LeanIX Services.