API & publishing from the command line

Everything the website does is available over a JSON API, so you can publish from scripts and CI.

Authentication

Create a token under Settings → API tokens and send it as a bearer token. Tokens are shown once; keep them secret and revoke any you lose.

export C3PKG_TOKEN=c3p_…
curl -H "Authorization: Bearer $C3PKG_TOKEN" https://www.c3pkg.eu/api/v1/me

Errors are JSON: {"error": "…", "errors": {"field": "message"}}. Requests are rate limited; on 429 wait for the Retry-After seconds.

Publish a library

A .c3l is a zip with manifest.json at its root. The package name is the manifest's provides, and it must match the name in the URL. Versions are semver (1.2.3 or 1.2.3-rc.1) and can never be changed once published.

# new package: description is required the first time
curl -X PUT -H "Authorization: Bearer $C3PKG_TOKEN" \
  -F file=@vk.c3l -F c3_version=0.7.5 \
  -F description="Vulkan bindings for C3" -F tags="gpu,vulkan" -F license=MIT \
  https://www.c3pkg.eu/api/v1/packages/vk/versions/1.0.0

# a new version of a package you own
curl -X PUT -H "Authorization: Bearer $C3PKG_TOKEN" \
  -F file=@vk.c3l -F c3_version=0.7.5 \
  https://www.c3pkg.eu/api/v1/packages/vk/versions/1.0.1

Optional form fields for a new package: license, docs_url, git_url and a readme file. Success returns 201 with {"name", "version", "created", "url"}.

Endpoints

Method and pathWhat it doesAuth
GET /api/v1/packagesList or search. Query: q, tag, sort (latest, downloads, stars), page, per_page (max 100)–
GET /api/v1/packages/{name}Metadata, README (Markdown) and all versions–
GET /api/v1/packages/{name}/versionsVersions with checksums, sizes and yank state–
GET /api/v1/packages/{name}/{version}/downloadThe .c3l file (counts as a download)–
PUT /api/v1/packages/{name}/versions/{version}Publish a version (multipart, see above)token
PUT / DELETE …/versions/{version}/yankYank or restore a versionowner
PATCH /api/v1/packages/{name}JSON with any of description, tags[], license, docs_url, git_urlowner
PUT /api/v1/packages/{name}/readmeBody: the README as Markdown (max 512 KB)owner
PUT / DELETE /api/v1/packages/{name}/starStar or unstar; returns the new counttoken
GET /api/v1/users/{login}Public profile and packages–
GET / PATCH /api/v1/meYour account; patch name, bio, githubtoken

Package index (for build tools)

Plain, cache-friendly endpoints a package manager can use to resolve and fetch versions, in the style of the Go module proxy.

GET /index/{name}/listOne version per line, newest first, yanked versions left out
GET /index/{name}/{version}.jsonC3 version, platforms, size, checksums, yanked flag
GET /index/{name}/{version}.c3lThe library file

Yanked versions are not listed but can still be fetched by exact version, so existing builds keep working.

Checksums

Each version has two SHA-256 values. sha256_file is the hash of the uploaded .c3l. sha256_tree hashes the contents, ignoring zip metadata, so a zipped library and its unpacked directory give the same value:

cd unpacked-library
find . -type f | sed 's|^\./||' | LC_ALL=C sort \
  | while read f; do echo "$(sha256sum "$f" | cut -c1-64)  $f"; done \
  | sha256sum