Dashboard

Premex Artifacts - Package Registry

Feed this document to an AI assistant to enable it to integrate with the Artifacts package registry. It covers authentication, API usage, and complete publish/consume workflows for npm, Maven, Swift, Raw, and KMP packages.

Overview

Artifacts is a package registry supporting npm, Maven, Swift, Raw, and KMP (Kotlin Multiplatform) packages.

  • Base URL: https://artifacts.premex.se
  • Web UI: https://artifacts.premex.se — create accounts, manage repositories, and generate API tokens
  • Auth: API tokens (art_ prefix) for all CLI and API access
  • Protocols: Standard npm registry, Maven HTTP repository, Swift Package Registry (SE-0292), Raw file storage, and KMP build pipeline

1. Authentication

1.1 Token Types

Artifacts has three token types:

Type Prefix Scope Create location
Account art_ Acts as your user identity Settings > API Tokens
Organization org_ All repos in an org Org Settings > Organization Tokens
Repository rep_ A single repo Repo Settings > Repository Tokens

For quick CLI access, create an account token at Settings > API Tokens.

For CI/CD, use an org token (org_). For customer distribution, use a repo token (rep_).

Tokens look like: art_a1b2c3d4e5f6789012345678901234567890abcdef

The token is shown only once when created. Store it securely.

1.2 Auth Methods

All API routes accept these auth methods:

Method Format Used by
API token (Bearer) Authorization: Bearer art_|org_|rep_... npm CLI, Swift PM, curl
Basic auth Authorization: Basic base64(token:art_|org_|rep_...) Maven/Gradle

For Basic auth, the username can be anything (conventionally token), and the password is the API token.

1.3 Token Scopes

All three token types use the same hierarchical scopes:

Scope Level Grants
read 0 Download/list packages
write 1 Publish packages (includes read)
admin 2 Manage repos, tokens, members (includes write and read)

Scope enforcement: a token can only perform actions up to its highest scope level.

  • Account tokens (art_): scopes are checked on top of user membership roles
  • Org tokens (org_): scopes grant direct access to all repos in the org (no membership check)
  • Repo tokens (rep_): scopes grant direct access to the specific repo (no membership check)

1.4 Token Management API

Three endpoints manage the three token types:

Account tokensGET|POST|DELETE /api/auth/token

  • Auth: Firebase ID token only (web session)

Org tokensGET|POST|DELETE /api/orgs/{orgSlug}/tokens

  • Create: Firebase auth only (org admin+)
  • List/Delete: Firebase auth (org admin+) or org_ admin token

Repo tokensGET|POST|DELETE /api/repos/{repoId}/tokens

  • All operations: Firebase auth (repo admin+) or org_ admin token for the repo's org
# Create an org token (requires Firebase auth + org admin role)
curl -X POST "https://artifacts.premex.se/api/orgs/ORGSLUG/tokens" \
  -H "Authorization: Bearer $FIREBASE_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "CI Pipeline", "scopes": ["read", "write"]}'

# Create a repo token (org_ admin token can do this programmatically)
curl -X POST "https://artifacts.premex.se/api/repos/REPO_ID/tokens" \
  -H "Authorization: Bearer org_your_admin_token" \
  -H "Content-Type: application/json" \
  -d '{"name": "customer-readonly", "scopes": ["read"]}'

# List repo tokens
curl "https://artifacts.premex.se/api/repos/REPO_ID/tokens" \
  -H "Authorization: Bearer org_your_admin_token"

# Delete a token
curl -X DELETE "https://artifacts.premex.se/api/repos/REPO_ID/tokens?tokenId=TOKEN_ID" \
  -H "Authorization: Bearer org_your_admin_token"

Create token fields:

Field Type Required Description
name string Yes Human-readable label
scopes string[] No Default varies by endpoint
expiresInDays number No Days until expiration (omit for no expiry)

Response:

{
  "token": {
    "id": "token-id",
    "tokenType": "repo",
    "name": "customer-readonly",
    "tokenPrefix": "rep_a1b2c3d4",
    "scopes": ["read"],
    "expiresAt": "2027-02-26T00:00:00.000Z",
    "createdAt": "2026-02-26T12:00:00.000Z"
  },
  "rawToken": "rep_a1b2c3d4e5f6..."
}

rawToken is only returned at creation time. Subsequent GET calls return token metadata without the secret.


2. Repository Management

2.1 Creating a Repository

Repositories are polyglot — each repo supports one or more package types simultaneously. A single repo can serve npm, Maven, Swift, Raw, and/or KMP packages at the same time, with each protocol's proxy working independently. The packageTypes field is an array (e.g., ["npm", "maven"]).

Repositories can be created via the web UI or the API.

curl -s "https://artifacts.premex.se/api/repos" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "my-npm-repo",
    "packageTypes": ["npm"],
    "visibility": "private",
    "description": "Internal npm packages"
  }'
Field Type Required Values
name string Yes 2-64 chars, lowercase, numbers, hyphens only
packageTypes string[] Yes Non-empty array of: npm, maven, swift, raw, kmp
visibility string No private (default) or public
description string No Free text
kmpConfig object Only when packageTypes includes kmp See KMP Packages

Response (HTTP 201):

{
  "repo": {
    "id": "my-npm-repo",
    "name": "my-npm-repo",
    "packageTypes": ["npm"],
    "visibility": "private",
    "description": "Internal npm packages",
    "ownerId": "user123",
    "members": { "user123": "owner" },
    "memberUids": ["user123"],
    "packageCount": 0,
    "downloadCount": 0,
    "createdAt": "2026-02-16T10:30:00.000Z",
    "updatedAt": "2026-02-16T10:30:00.000Z"
  }
}

The id field is the repo ID used in all subsequent API calls and CLI URLs.

2.2 Listing Repositories

curl -s "https://artifacts.premex.se/api/repos" \
  -H "Authorization: Bearer $TOKEN"

Returns { "repos": [...] } — all repos the authenticated user is a member of.

2.3 Public Repository Discovery

List all public repositories (no authentication required):

curl -s "https://artifacts.premex.se/api/repos/public"

Returns repos with their packages embedded:

{
  "repos": [{
    "id": "my-public-repo",
    "name": "my-public-repo",
    "description": "Public packages",
    "packageTypes": ["npm"],
    "packageCount": 3,
    "downloadCount": 42,
    "createdAt": "2026-02-16T10:30:00.000Z",
    "updatedAt": "2026-02-16T14:30:00.000Z",
    "packages": [{
      "id": "pkg-id",
      "name": "@scope/package-name",
      "packageType": "npm",
      "latestVersion": "1.0.0",
      "description": "A package",
      "scope": "scope",
      "groupId": null,
      "artifactId": null,
      "downloadCount": 10,
      "versionCount": 3
    }]
  }]
}

2.4 Repository Details, Update, Delete

# Get details
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID" \
  -H "Authorization: Bearer $TOKEN"

# Update (requires admin role)
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID" \
  -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"description": "Updated description", "visibility": "public"}'

# Delete (requires owner role)
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID" \
  -X DELETE \
  -H "Authorization: Bearer $TOKEN"

2.5 Managing Members

# List members
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/members" \
  -H "Authorization: Bearer $TOKEN"

# Add member (requires admin role)
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/members" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"userId": "other-user-uid", "role": "write"}'

# Remove member (requires admin role)
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/members?userId=other-user-uid" \
  -X DELETE \
  -H "Authorization: Bearer $TOKEN"

List members response:

{
  "members": [
    {
      "uid": "user123",
      "role": "admin",
      "displayName": "Jane Smith",
      "email": "jane@example.com",
      "avatarUrl": "https://..."
    }
  ]
}

Role hierarchy: read < write < admin < owner

2.6 Listing Packages in a Repository

curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/packages" \
  -H "Authorization: Bearer $TOKEN"

Returns { "packages": [...] }.


3. npm Packages

3.1 Registry URL Pattern

https://artifacts.premex.se/api/npm/$REPO_ID/

Example: https://artifacts.premex.se/api/npm/my-npm-repo/

3.2 Publishing npm Packages

Option A: Using npm CLI

Configure .npmrc in your project directory:

# For scoped packages (@yourscope/*)
@yourscope:registry=https://artifacts.premex.se/api/npm/REPO_ID/
//artifacts.premex.se/api/npm/REPO_ID/:_authToken=art_your_token_here

# For unscoped packages
registry=https://artifacts.premex.se/api/npm/REPO_ID/
//artifacts.premex.se/api/npm/REPO_ID/:_authToken=art_your_token_here

Then publish:

npm publish --registry https://artifacts.premex.se/api/npm/REPO_ID/

Option B: Using the Upload API

curl -s "https://artifacts.premex.se/api/packages/upload" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -F "repoId=REPO_ID" \
  -F "packageName=@scope/package-name" \
  -F "version=1.0.0" \
  -F "packageType=npm" \
  -F "description=My package" \
  -F "file=@./my-package-1.0.0.tgz"

3.3 Installing npm Packages

Configure .npmrc:

@yourscope:registry=https://artifacts.premex.se/api/npm/REPO_ID/
//artifacts.premex.se/api/npm/REPO_ID/:_authToken=art_your_token_here

Then install normally:

npm install @yourscope/package-name

3.4 npm Search

npm search --registry https://artifacts.premex.se/api/npm/REPO_ID/ searchterm

Or via API:

curl -s "https://artifacts.premex.se/api/npm/REPO_ID/-/v1/search?text=hello" \
  -H "Authorization: Bearer $TOKEN"

3.5 npm API Endpoints Reference

Operation Method URL Pattern
Get packument GET /api/npm/{repoId}/{packageName}
Get packument (scoped) GET /api/npm/{repoId}/@{scope}/{name}
Download tarball GET /api/npm/{repoId}/-/tarball/{encodedPackageName}/{version}
Publish PUT /api/npm/{repoId}/{packageName}
Search GET /api/npm/{repoId}/-/v1/search?text={query}

3.6 Packument Response Format

{
  "_id": "@scope/package-name",
  "_rev": "1-0",
  "name": "@scope/package-name",
  "description": "Package description",
  "dist-tags": { "latest": "1.0.0" },
  "versions": {
    "1.0.0": {
      "name": "@scope/package-name",
      "version": "1.0.0",
      "description": "Package description",
      "dist": {
        "tarball": "https://artifacts.premex.se/api/npm/REPO_ID/-/tarball/%40scope%2Fpackage-name/1.0.0",
        "shasum": "hex-sha1-checksum",
        "integrity": "sha256-base64-checksum"
      },
      "_id": "@scope/package-name@1.0.0"
    }
  },
  "time": {
    "created": "2026-02-16T10:30:00.000Z",
    "modified": "2026-02-16T14:30:00.000Z",
    "1.0.0": "2026-02-16T14:30:00.000Z"
  }
}

4. Maven Packages

4.1 Repository URL Pattern

https://artifacts.premex.se/api/maven/$REPO_ID/

Example: https://artifacts.premex.se/api/maven/my-maven-repo/

4.2 Publishing Maven Packages with Gradle

build.gradle.kts:

plugins {
    `java-library`
    `maven-publish`
}

group = "com.example"
version = "1.0.0"

publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["java"])
        }
    }
    repositories {
        maven {
            name = "artifacts"
            url = uri(System.getenv("ARTIFACTS_URL") ?: "https://artifacts.premex.se/api/maven/REPO_ID/")
            credentials {
                username = "token"
                password = System.getenv("ARTIFACTS_TOKEN") ?: ""
            }
        }
    }
}

Publish:

export ARTIFACTS_URL="https://artifacts.premex.se/api/maven/REPO_ID/"
export ARTIFACTS_TOKEN="art_your_token_here"
./gradlew publishMavenPublicationToArtifactsRepository

4.3 Publishing Maven Packages with Maven CLI

~/.m2/settings.xml:

<settings>
  <servers>
    <server>
      <id>artifacts</id>
      <username>token</username>
      <password>art_your_token_here</password>
    </server>
  </servers>
</settings>

pom.xml:

<distributionManagement>
  <repository>
    <id>artifacts</id>
    <url>https://artifacts.premex.se/api/maven/REPO_ID/</url>
  </repository>
</distributionManagement>
mvn deploy

4.4 Consuming Maven Packages with Gradle

build.gradle.kts:

repositories {
    maven {
        url = uri(System.getenv("ARTIFACTS_URL") ?: "https://artifacts.premex.se/api/maven/REPO_ID/")
        credentials {
            username = "token"
            password = System.getenv("ARTIFACTS_TOKEN") ?: ""
        }
    }
}

dependencies {
    implementation("com.example:hello-lib:1.0.0")
}

4.5 Consuming Maven Packages with Maven CLI

~/.m2/settings.xml (same as publishing config above)

pom.xml:

<repositories>
  <repository>
    <id>artifacts</id>
    <url>https://artifacts.premex.se/api/maven/REPO_ID/</url>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>com.example</groupId>
    <artifactId>hello-lib</artifactId>
    <version>1.0.0</version>
  </dependency>
</dependencies>

4.6 Maven API Endpoints Reference

Operation Method URL Pattern
Download file GET /api/maven/{repoId}/{groupPath}/{artifactId}/{version}/{filename}
Get metadata GET /api/maven/{repoId}/{groupPath}/{artifactId}/maven-metadata.xml
Get checksum GET /api/maven/{repoId}/{groupPath}/{artifactId}/maven-metadata.xml.sha1
Check existence HEAD /api/maven/{repoId}/{groupPath}/{artifactId}/{version}/{filename}
Upload file PUT /api/maven/{repoId}/{groupPath}/{artifactId}/{version}/{filename}

Auth: Basic auth with username token and password art_....

4.7 Maven Metadata Response Format

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>com.example</groupId>
  <artifactId>hello-lib</artifactId>
  <versioning>
    <latest>1.0.0</latest>
    <release>1.0.0</release>
    <versions>
      <version>1.0.0</version>
    </versions>
    <lastUpdated>20260216143000</lastUpdated>
  </versioning>
</metadata>

4.8 Maven Path Conventions

Group ID maps to a directory path: com.example becomes com/example/.

Full artifact path: {groupPath}/{artifactId}/{version}/{filename}

Example: com/example/hello-lib/1.0.0/hello-lib-1.0.0.jar


5. Swift Packages

5.1 Registry URL Pattern

https://artifacts.premex.se/api/swift/$REPO_ID/

Example: https://artifacts.premex.se/api/swift/my-swift-repo/

5.2 Package Naming

Swift packages in Artifacts use a scope.name convention:

  • Scope: organization or namespace (e.g., myorg)
  • Name: package name (e.g., hello-lib)
  • Combined identifier: myorg.hello-lib

5.3 Publishing Swift Packages via API

Create a source archive (zip of the entire Swift package):

# In your Swift package directory
zip -r source-archive.zip Package.swift Sources/ Tests/ -x "*.DS_Store" ".build/*"

Publish the archive:

curl -s -X PUT \
  "https://artifacts.premex.se/api/swift/REPO_ID/SCOPE/PACKAGE_NAME/VERSION" \
  -H "Authorization: Bearer art_your_token_here" \
  -H "Content-Type: application/zip" \
  --data-binary "@source-archive.zip"

Example:

curl -s -X PUT \
  "https://artifacts.premex.se/api/swift/my-swift-repo/myorg/hello-lib/1.0.0" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/zip" \
  --data-binary "@source-archive.zip"

Response: HTTP 201 on success.

Optionally, also upload the Package.swift manifest separately (for serving via the manifest endpoint):

curl -s -X POST "https://artifacts.premex.se/api/packages/upload" \
  -H "Authorization: Bearer $API_TOKEN" \
  -F "repoId=REPO_ID" \
  -F "packageName=hello-lib" \
  -F "version=1.0.0" \
  -F "packageType=swift" \
  -F "scope=myorg" \
  -F "description=My Swift library" \
  -F "file=@Package.swift;type=text/x-swift"

5.4 Consuming Swift Packages

Configure Swift Package Manager to use the registry:

swift package-registry set https://artifacts.premex.se/api/swift/REPO_ID/
swift package-registry login https://artifacts.premex.se/api/swift/REPO_ID/ --token art_your_token_here

In your Package.swift:

dependencies: [
    .package(id: "myorg.hello-lib", from: "1.0.0"),
]

5.5 Swift Registry API Endpoints Reference

All responses include the Content-Version: 1 header.

Operation Method URL Pattern
List releases GET /api/swift/{repoId}/{scope}/{name}
Get release metadata GET /api/swift/{repoId}/{scope}/{name}/{version}
Download source archive GET /api/swift/{repoId}/{scope}/{name}/{version}.zip
Download Package.swift GET /api/swift/{repoId}/{scope}/{name}/{version}/Package.swift
Publish PUT /api/swift/{repoId}/{scope}/{name}/{version}

5.6 Swift Releases List Response

{
  "releases": {
    "1.0.0": {
      "url": "https://artifacts.premex.se/api/swift/REPO_ID/myorg/hello-lib/1.0.0"
    },
    "1.0.1": {
      "url": "https://artifacts.premex.se/api/swift/REPO_ID/myorg/hello-lib/1.0.1"
    }
  }
}

5.7 Swift Release Metadata Response

{
  "id": "myorg.hello-lib",
  "version": "1.0.0",
  "resources": [
    {
      "name": "source-archive",
      "type": "application/zip",
      "checksum": "sha256-hex-string"
    }
  ],
  "metadata": {
    "description": "Package description"
  }
}

5.8 Source Archive Download Headers

Content-Type: application/zip
Content-Disposition: attachment; filename="source-archive.zip"
Content-Version: 1
Digest: sha-256=hex-checksum

6. Raw Packages

Raw packages provide simple file storage with versioning. Any file type can be uploaded and downloaded using a straightforward path-based API.

6.1 URL Pattern

https://artifacts.premex.se/api/raw/$REPO_ID/{packageName}/{version}/{filename}

Example: https://artifacts.premex.se/api/raw/my-raw-repo/my-tool/1.0.0/my-tool-linux-amd64

6.2 Uploading Raw Files

Upload a file by PUTting the binary content directly:

curl -s -X PUT \
  "https://artifacts.premex.se/api/raw/REPO_ID/PACKAGE_NAME/VERSION/FILENAME" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/octet-stream" \
  --data-binary "@/path/to/file"

Example — upload a zip archive:

curl -s -X PUT \
  "https://artifacts.premex.se/api/raw/my-raw-repo/my-tool/1.0.0/my-tool.zip" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/zip" \
  --data-binary "@my-tool.zip"

Requires write role. Response: HTTP 201 { "ok": true }.

The upload automatically creates the package metadata if it doesn't exist. Multiple files can be uploaded under the same package name and version (e.g., platform-specific binaries).

6.3 Downloading Raw Files

curl -s -O \
  "https://artifacts.premex.se/api/raw/REPO_ID/PACKAGE_NAME/VERSION/FILENAME" \
  -H "Authorization: Bearer $TOKEN"

Requires read role. Public repos allow unauthenticated downloads.

The response includes a Content-Disposition: attachment header and a content type guessed from the file extension.

6.4 Listing Package Versions

curl -s "https://artifacts.premex.se/api/raw/REPO_ID/PACKAGE_NAME" \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "name": "my-tool",
  "latestVersion": "1.0.0",
  "versions": [
    {
      "version": "1.0.0",
      "publishedAt": "2026-02-16T14:30:00.000Z",
      "size": 12345
    }
  ]
}

6.5 Deleting Raw Files

curl -s -X DELETE \
  "https://artifacts.premex.se/api/raw/REPO_ID/PACKAGE_NAME/VERSION/FILENAME" \
  -H "Authorization: Bearer $TOKEN"

Requires admin role. Response: { "ok": true }.

6.6 Raw API Endpoints Reference

Operation Method URL Pattern Role
List versions GET /api/raw/{repoId}/{packageName} read
Download file GET /api/raw/{repoId}/{packageName}/{version}/{filename} read
Upload file PUT /api/raw/{repoId}/{packageName}/{version}/{filename} write
Delete file DELETE /api/raw/{repoId}/{packageName}/{version}/{filename} admin

6.7 Using the Upload API for Raw Files

Raw files can also be uploaded via the generic upload endpoint:

curl -s "https://artifacts.premex.se/api/packages/upload" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -F "repoId=REPO_ID" \
  -F "packageName=my-tool" \
  -F "version=1.0.0" \
  -F "packageType=raw" \
  -F "description=My tool binary" \
  -F "file=@./my-tool.zip"

7. Upload API

For all package types, there is a generic upload endpoint:

curl -s "https://artifacts.premex.se/api/packages/upload" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -F "repoId=REPO_ID" \
  -F "packageName=package-name" \
  -F "version=1.0.0" \
  -F "packageType=npm|maven|swift|raw" \
  -F "description=Optional description" \
  -F "file=@/path/to/file"

Additional fields by type:

Package Type Extra Fields File Type
npm .tgz
maven groupId, artifactId .jar, .pom
swift scope .zip, Package.swift
raw Any file

8. Error Responses

All errors return JSON:

{
  "error": "Human-readable error message",
  "code": "ERROR_CODE"
}
HTTP Status Code When
400 BAD_REQUEST Missing/invalid parameters
401 UNAUTHORIZED Missing, invalid, or expired auth
403 FORBIDDEN Insufficient role for the operation
404 NOT_FOUND Resource does not exist
409 CONFLICT Duplicate repository name
500 (none) Internal server error

9. KMP Packages (Kotlin Multiplatform)

KMP repos are a special type that don't receive direct uploads. Instead, they watch a Maven source for Kotlin Multiplatform libraries and automatically build JS (npm) and XCFramework (Swift) outputs via GitHub Actions.

9.1 Creating a KMP Repository

A KMP repo requires a kmpConfig field specifying the Maven source:

# Source from another Artifacts Maven repo
curl -s "https://artifacts.premex.se/api/repos" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "my-kmp-repo",
    "packageTypes": ["kmp"],
    "kmpConfig": {
      "sourceType": "artifacts",
      "sourceRepoId": "my-maven-repo"
    }
  }'

# Source from an external Maven repository
curl -s "https://artifacts.premex.se/api/repos" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "my-kmp-repo",
    "packageTypes": ["kmp"],
    "kmpConfig": {
      "sourceType": "external",
      "sourceUrl": "https://repo1.maven.org/maven2"
    }
  }'
kmpConfig Field Type Required Description
sourceType string Yes "artifacts" or "external"
sourceRepoId string If artifacts ID of the Artifacts Maven repo to watch
sourceUrl string If external URL of the external Maven repository

9.2 Watched Packages

Watched packages define which Maven coordinates to monitor for new versions.

# List watched packages
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/watched" \
  -H "Authorization: Bearer $TOKEN"

# Add a watched package
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/watched" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "groupId": "com.example",
    "artifactId": "my-library",
    "npmPackageName": "@my-kmp-repo/my-library",
    "swiftScope": "my-kmp-repo",
    "swiftName": "my-library",
    "enableNpm": true,
    "enableSwift": true,
    "appleTargets": ["iosArm64", "macosArm64"]
  }'

# Get a watched package
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/watched/$WATCHED_ID" \
  -H "Authorization: Bearer $TOKEN"

# Update a watched package
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/watched/$WATCHED_ID" \
  -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"enableSwift": false, "appleTargets": ["iosArm64"]}'

# Delete a watched package (requires admin)
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/watched/$WATCHED_ID" \
  -X DELETE \
  -H "Authorization: Bearer $TOKEN"

Add watched package fields:

Field Type Required Default
groupId string Yes
artifactId string Yes
enableNpm boolean No true
enableSwift boolean No true
npmPackageName string If enableNpm
swiftScope string If enableSwift
swiftName string If enableSwift
appleTargets string[] No []

Updatable fields: enableNpm, enableSwift, appleTargets, npmPackageName, swiftScope, swiftName.

9.3 Polling for New Versions

Trigger a poll to check the Maven source for new versions of all watched packages:

curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/poll" \
  -X POST \
  -H "Authorization: Bearer $TOKEN"

Requires write role. Response:

{
  "results": [
    {
      "watchedPackageId": "wp-id",
      "groupId": "com.example",
      "artifactId": "my-library",
      "newVersions": ["1.1.0"],
      "discoveredVersions": ["1.0.1", "1.0.0-beta1"],
      "buildsTriggered": 1,
      "errors": []
    }
  ]
}

Poll behavior: Only the latest stable version automatically triggers a build (status pending). Other new versions (older stable versions, pre-release versions) are recorded with status discovered and can be triggered manually.

Pre-release patterns detected: alpha, beta, rc, dev, snapshot, eap, experimental, m1/m2/etc.

9.4 Builds

Builds represent individual version build jobs.

# List builds
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/builds" \
  -H "Authorization: Bearer $TOKEN"

# List builds with filters
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/builds?status=pending,building&stableOnly=true&limit=50&counts=true" \
  -H "Authorization: Bearer $TOKEN"

# Get a single build
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/builds/$BUILD_ID" \
  -H "Authorization: Bearer $TOKEN"

# Manually trigger a build for a specific version
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/builds" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"watchedPackageId": "wp-id", "version": "1.0.0"}'

# Retry a failed or discovered build
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/builds/$BUILD_ID" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"action": "retry"}'

# Delete a single build (requires admin)
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/builds/$BUILD_ID" \
  -X DELETE \
  -H "Authorization: Bearer $TOKEN"

# Delete all builds in repo (requires admin)
curl -s "https://artifacts.premex.se/api/repos/$REPO_ID/kmp/builds" \
  -X DELETE \
  -H "Authorization: Bearer $TOKEN"

Build list query parameters:

Parameter Type Description
status string Comma-separated filter: discovered, pending, queued, building, success, failed
stableOnly boolean Only return stable (non-pre-release) versions
limit number Max results (default 200, max 500)
counts boolean Include statusCounts map in response

Build list response:

{
  "builds": [
    {
      "id": "build-id",
      "repoId": "my-kmp-repo",
      "watchedPackageId": "wp-id",
      "groupId": "com.example",
      "artifactId": "my-library",
      "version": "1.1.0",
      "isStable": true,
      "status": "success",
      "githubRunId": 12345,
      "githubRunUrl": "https://github.com/owner/repo/actions/runs/12345",
      "npmPublished": true,
      "swiftPublished": true,
      "error": null,
      "startedAt": "2026-02-16T14:30:00.000Z",
      "completedAt": "2026-02-16T14:45:00.000Z",
      "createdAt": "2026-02-16T14:30:00.000Z",
      "updatedAt": "2026-02-16T14:45:00.000Z"
    }
  ],
  "statusCounts": {
    "discovered": 5,
    "pending": 0,
    "queued": 0,
    "building": 1,
    "success": 10,
    "failed": 2
  }
}

Build statuses:

Status Meaning
discovered Version found but not auto-built (older or pre-release). Trigger manually with retry.
pending Build created, waiting for GitHub Actions dispatch
queued GitHub Actions workflow dispatched
building Build in progress
success Build completed successfully, packages published
failed Build failed (check error field)

Retry: Can only retry builds with status failed or discovered. Returns { "success": true, "status": "pending" } or HTTP 502 if GitHub dispatch fails.

9.5 KMP API Endpoints Reference

Operation Method URL Pattern Role
List watched packages GET /api/repos/{repoId}/kmp/watched read
Add watched package POST /api/repos/{repoId}/kmp/watched write
Get watched package GET /api/repos/{repoId}/kmp/watched/{watchedId} read
Update watched package PATCH /api/repos/{repoId}/kmp/watched/{watchedId} write
Delete watched package DELETE /api/repos/{repoId}/kmp/watched/{watchedId} admin
Poll for new versions POST /api/repos/{repoId}/kmp/poll write
List builds GET /api/repos/{repoId}/kmp/builds read
Trigger build POST /api/repos/{repoId}/kmp/builds write
Delete all builds DELETE /api/repos/{repoId}/kmp/builds admin
Get build GET /api/repos/{repoId}/kmp/builds/{buildId} read
Retry build POST /api/repos/{repoId}/kmp/builds/{buildId} write
Delete build DELETE /api/repos/{repoId}/kmp/builds/{buildId} admin

10. Role-Based Access Control

Each repository has a members map where each user has a role:

Role Level Can Do
read 0 List packages, download artifacts
write 1 All of read + publish packages
admin 2 All of write + manage members, update repo settings, delete files/builds
owner 3 All of admin + delete repository

Public repositories allow read access without any authentication. All other operations require auth.

API token scoping: Tokens can be restricted to specific scopes and repositories. A token can only perform actions within its scope and repo restrictions, up to the user's own role in each repo.