Download a completed lockfile analysis
Download the completed document in the format selected at submission. Only state=succeeded indicates that the result is ready. The response format is determined by the upstream’s allowlisted media type; Accept does not select it. The document is checked using the same format-specific validation as synchronous /v1/experimental/sbom and is bounded to 16,777,216 bytes. Pending jobs return 409 ANALYSIS_PENDING. Failed jobs return 409 ANALYSIS_FAILED with an allowlisted failure_code and a fixed safe detail; backend diagnostics are not returned. Missing, expired and other-owner job IDs produce the same 404 response.
curl --request GET \
--url https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"bomFormat": "CycloneDX",
"components": [],
"compositions": [
{
"aggregate": "incomplete",
"assemblies": []
}
],
"metadata": {
"timestamp": "2026-09-09T00:00:00Z"
},
"properties": [
{
"name": "githits:completeness",
"value": "partial_manifest_inventory"
}
],
"serialNumber": "urn:uuid:00000000-0000-4000-8000-000000000001",
"specVersion": "1.7",
"version": 1
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
Optional client attribution: trimmed printable ASCII, at most 80 bytes. Invalid optional values are dropped.
Optional client-version attribution: trimmed printable ASCII, at most 80 bytes. Invalid optional values are dropped.
Optional agent attribution: trimmed printable ASCII, at most 160 bytes. Invalid optional values are dropped.
Optional caller-defined session ID: one to 64 ASCII letters, digits, underscores or hyphens, preserved exactly. Supply the header at most once. Invalid supplied IDs return 400 INVALID_SESSION_ID; no session is created.
1 - 64^[A-Za-z0-9_-]{1,64}$Path Parameters
Hyphenated UUID returned when the job was accepted.
^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$Response
The completed UTF-8 analysis document in the format selected at submission. The document has passed the same format-specific validation as the synchronous SBOM response and is at most 16,777,216 bytes.
Extensible CycloneDX 1.7 document. This schema describes a compatible subset, not the entire standard. Additional fields are allowed at every object level; clients must preserve or ignore unfamiliar data. Inventory and license completeness must be read from evidence, not inferred from this schema.
CycloneDX 1.7 Named project roots and dependency entries. Unresolved declarations remain in document properties rather than becoming package components. The array may be empty when no concrete packages or named roots are available. Separate lockfile occurrences may have the same name and version; do not deduplicate by those fields alone.
Show child attributes
Show child attributes
Completeness declaration for the listed component references.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Document evidence. githits:completeness distinguishes resolved_manifest_inventory, partial_manifest_inventory, recorded_lockfile_inventory and mixed_dependency_inventory; none guarantees that every license is known. githits:resolution_basis distinguishes manifest_resolution, lockfile_records and lockfile_records_and_manifest_resolution. Inspect githits:resolutions for per-manifest outcomes, githits:declarations for original requirements, and githits:lockfiles and githits:manifest_associations for lockfile coverage. githits:notice summarizes limitations.
Show child attributes
Show child attributes
Unique identifier for this generated document. This URN is not a retrieval URL.
^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$Document revision, not a package version.
x >= 1curl --request GET \
--url https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.githits.dev/v1/experimental/lockfile-jobs/{id}/result")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"bomFormat": "CycloneDX",
"components": [],
"compositions": [
{
"aggregate": "incomplete",
"assemblies": []
}
],
"metadata": {
"timestamp": "2026-09-09T00:00:00Z"
},
"properties": [
{
"name": "githits:completeness",
"value": "partial_manifest_inventory"
}
],
"serialNumber": "urn:uuid:00000000-0000-4000-8000-000000000001",
"specVersion": "1.7",
"version": 1
}