Bundles API
18 endpoints. Request and response schemas are described on the schemas page; the other tags are listed in the API index.
Endpoints
GET /api/v1/bundles
List bundles
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | query | string | no | - |
state | query | string | no | - |
page | query | string | no | - |
limit | query | string | no | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: object |
default | Error | application/json: Error |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
bundles | array of ReleaseBundle | no | - |
limit | integer | no | - |
page | integer | no | - |
total | integer | no | - |
POST /api/v1/bundles
Create bundle
Creates a draft bundle owned by the caller. Allowed for administrators and for any principal that can read at least one repository; the other bundle routes authorize per bundle (see the release bundles documentation).
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
description | string | no | - |
name | string | no | - |
pipeline | string | no | Name of the promotion pipeline; exclusive with pipeline_id. |
pipeline_id | string | no | - |
version | string | no | - |
Responses
| Status | Description | Body |
|---|---|---|
201 | Created | application/json: ReleaseBundle |
default | Error | application/json: Error |
GET /api/v1/bundles/{name}/{version}
Get bundle
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: ReleaseBundle |
default | Error | application/json: Error |
DELETE /api/v1/bundles/{name}/{version}
Delete bundle
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
204 | No content | - |
default | Error | application/json: Error |
POST /api/v1/bundles/{name}/{version}/archive
Archive bundle
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: ReleaseBundle |
default | Error | application/json: Error |
GET /api/v1/bundles/{name}/{version}/items
List bundle items
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: object |
default | Error | application/json: Error |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
items | array of ReleaseBundleItem | no | - |
POST /api/v1/bundles/{name}/{version}/items
Add bundle items (draft bundles only, atomic)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
items | array of object | no | - |
Responses
| Status | Description | Body |
|---|---|---|
201 | Created | application/json: object |
default | Error | application/json: Error |
Fields of the 201 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
items | array of ReleaseBundleItem | no | - |
DELETE /api/v1/bundles/{name}/{version}/items/{sha256}
Remove bundle item
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
sha256 | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
204 | No content | - |
default | Error | application/json: Error |
GET /api/v1/bundles/{name}/{version}/manifest
Get bundle manifest
The exact JSON document a bundle signature covers (admin only): bundle identity plus its items ordered by digest.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Manifest | application/json: object |
400 | Invalid request, including a NUL byte in the URL or the body | application/json: Error |
403 | Admin access required | - |
404 | Bundle not found | - |
GET /api/v1/bundles/{name}/{version}/manifest.asc
Get bundle manifest signature
Armored detached GPG signature of the manifest; 404 when the bundle was sealed without a key (admin only). Verify with gpg --verify manifest.json.asc manifest.json.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Armored signature | application/pgp-signature: string |
400 | Invalid request, including a NUL byte in the URL or the body | application/json: Error |
403 | Admin access required | - |
404 | Bundle not found or not signed | - |
POST /api/v1/bundles/{name}/{version}/promote
Promote bundle
Copies every item of a sealed bundle into target_repo and moves the bundle to to_stage (admin only). Items are copied as metadata that references the same stored blobs (no bytes are duplicated), in one transaction: either every item lands and the promotion is recorded, or nothing changes. The target's storage quota is charged, its license policies and immutable_releases setting are enforced, and quarantined source artifacts are refused. An artifact already present in the target with the same content counts as existing (so a retry is idempotent); different content at the same coordinates is a 409. Emits the bundle.promoted webhook event.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
force | query | boolean | no | Administrators only: true replaces content that the target already holds at the same coordinates, including released versions of a repository with immutable_releases, instead of answering 409. The replaced rows go to the target's trash. |
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
notes | string | no | - |
target_repo | string | no | Repository to promote into. May be omitted when the pipeline stage fixes a repository. |
to_stage | string | no | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Promoted | application/json: object |
400 | Invalid request, or an item's repository and the target are not hosted repositories of the same format | application/json: Error |
403 | Not an admin; an item is quarantined in its source (ARTIFACT_QUARANTINED); or a license policy of the target blocks it (LICENSE_BLOCKED) | application/json: Error |
404 | Bundle or target repository not found | application/json: Error |
409 | Bundle not sealed or changed concurrently; to_stage does not follow the current stage; an item no longer exists in its source repository (artifact_missing); the target holds different content at the same coordinates (artifact_conflict), or the target has immutable releases and the version is a release (immutable_release) | application/json: Error |
507 | The target repository's storage quota would be exceeded (quota_exceeded) | application/json: Error |
default | Error | application/json: Error |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
copied | integer | no | Artifacts newly written to the target |
existing | integer | no | Artifacts the target already held with the same content |
items | array of object | no | - |
items[].artifact_path | string | no | - |
items[].copied | array of object | no | - |
items[].copied[].name | string | no | - |
items[].copied[].path | string | no | - |
items[].copied[].sha256 | string | no | - |
items[].copied[].size | integer (int64) | no | - |
items[].copied[].version | string | no | - |
items[].existing | array of object | no | - |
items[].existing[].name | string | no | - |
items[].existing[].path | string | no | - |
items[].existing[].sha256 | string | no | - |
items[].existing[].size | integer (int64) | no | - |
items[].existing[].version | string | no | - |
items[].format | string | no | - |
items[].replaced | array of object | no | - |
items[].replaced[].name | string | no | - |
items[].replaced[].path | string | no | - |
items[].replaced[].sha256 | string | no | - |
items[].replaced[].size | integer (int64) | no | - |
items[].replaced[].version | string | no | - |
items[].sha256 | string | no | - |
promotion | object | no | The recorded bundle promotion (status success) |
replaced | integer | no | Artifacts a forced promotion moved to the target's trash because they held different content |
GET /api/v1/bundles/{name}/{version}/promotions
List promotions
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: object |
default | Error | application/json: Error |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
promotions | array of BundlePromotion | no | - |
POST /api/v1/bundles/{name}/{version}/seal
Seal bundle
Seals a draft bundle. With gpg_key_id (a key id from the admin GPG list, a fingerprint, or config) the bundle manifest is signed and the armored detached signature stored with the bundle (gpg_key_id = signer fingerprint, gpg_signature). An unknown key answers 400 validation_failed.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
version | path | string | yes | - |
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
gpg_key_id | string | no | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: ReleaseBundle |
default | Error | application/json: Error |
GET /api/v1/pipelines
List pipelines
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: object |
default | Error | application/json: Error |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
pipelines | array of PromotionPipeline | no | - |
POST /api/v1/pipelines
Create pipeline
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
description | string | no | - |
name | string | no | - |
stages | array of object | no | - |
Responses
| Status | Description | Body |
|---|---|---|
201 | Created | application/json: PromotionPipeline |
default | Error | application/json: Error |
GET /api/v1/pipelines/{name}
Get pipeline
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: PromotionPipeline |
default | Error | application/json: Error |
PATCH /api/v1/pipelines/{name}
Update pipeline
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
description | string | no | - |
stages | array of object | no | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Success | application/json: PromotionPipeline |
default | Error | application/json: Error |
DELETE /api/v1/pipelines/{name}
Delete pipeline
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
204 | No content | - |
default | Error | application/json: Error |