Skip to content

Reference: Artifact Keeper API calls used

Base https://ak.internal. Verified on backend main (5e351fc). Authorization: Bearer <token> unless noted.

Conda channel

Call Notes
GET /conda/{repo}/{subdir}/repodata.json (.zst, .bz2) hosted, remote and virtual
GET /conda/{repo}/{subdir}/repodata_shards.msgpack.zst, .../shards/{hash} CEP-16, hosted only
GET /conda/{repo}/{subdir}/{file} download
PUT /conda/{repo}/{subdir}/{file} upload, body = package; 201, 409 if it exists (what rattler-build upload artifactory sends)
POST /conda/{repo}/upload raw body + X-Package-Filename; optional X-Conda-Subdir
PUT /conda/{repo}/{subdir}/{file}/attestation CEP-27 Sigstore bundle (JSON); write:artifacts
GET /conda/{repo}/{subdir}/{file}/attestation stored bundle
DELETE /conda/{repo}/{subdir}/{file} withdraw (CEP-6)
GET /conda/{repo}/notices.json, channeldata.json
GET /conda/t/{token}/{repo}/... token-in-URL form (Artifact Keeper layout)

Repositories and tokens

Call Body
POST /api/v1/repositories {"key","name","format":"conda","repo_type":"local\|remote\|virtual\|staging","visibility":"public\|internal\|private","upstream_url","promotion_only","member_repos":[{"repo_key","priority"}]}
PATCH /api/v1/repositories/{key} e.g. {"promotion_only":false}
PUT /api/v1/repositories/{key}/cache-ttl {"cache_ttl_seconds": 300} (remote)
PUT /api/v1/repositories/{key}/security {"scan_enabled":true,"scan_on_upload":true}
GET /api/v1/repositories/{key}/artifacts?per_page=N rows with id, path, quarantine_status, last_promotion
DELETE /api/v1/repositories/{key}/artifacts/{path}
POST /api/v1/repositories/{key}/tokens {"name","scopes":["read:artifacts","write:artifacts"],"expires_in_days"}; scoped to that one repository
POST /api/v1/auth/tokens the caller's own token; repo_selector: {"match_repos":[uuid...]} narrows it to several repositories
POST /api/v1/auth/login {"username","password"}; 10 per username and IP per 15 min (shared with /v2/token)
PUT /api/v1/repositories/{key}/artifacts/{path} generic repositories (the trust repo); read anonymously at GET /api/v1/repositories/{key}/download/{path}

Release gate

Call Body
POST /api/v1/security/policies {"name","repository_id":<staging repo id>,"max_severity":"high","block_unscanned":true,"block_on_fail":true,"predicates":{"conda":{"min_attestation_state":"verified","denied_licenses":[...],"denied_license_families":[...],"block_install_scripts":true}}}
PUT /api/v1/promotion/repositories/{staging}/release-target {"release_repository_key":"conda-internal"}
POST /api/v1/promotion/repositories/{staging}/artifacts/{id}/promote {"target_repository":"conda-internal","skip_policy_check":false,"notes"} -> {"promoted", "policy_violations":[{"rule","severity","message"}]}
POST /api/v1/security/scan {"artifact_id"}
GET /api/v1/security/artifacts/{id}/scans per scanner status and counts

SBOM and environments

Call Notes
POST /api/v1/sbom/environment?filename=pixi.lock[&format=spdx] body = lockfile; CycloneDX per (environment, platform), nothing stored
POST /api/v1/repositories/{key}/environments?filename=pixi.lock&name=N store the graph; re-ingest replaces
GET /api/v1/environments/lookup?purl=pkg:conda/openssl@3.6.4 environments containing it, with inclusion paths
GET /api/v1/admin/downloads download records (hosted downloads only on main)

OCI

Pull and push at /v2/{repo}/{image}, e.g. ak.internal/oci-ghcr/prefix-dev/pixi:0.81.0 through a docker remote repository with upstream https://ghcr.io. Token exchange at /v2/token.