Introduction
The registry for AI agent skills (SKILL.md bundles) — browse them, download them as a zip, or install them via the revenexx CLI into any supported agent; sourced from connected Git repositories. Agent-agnostic, not Claude-only.
The public Skill Registry API lets clients browse skills, fetch their details and versions,
and download a skill bundle as a zip.
All endpoints require a Zitadel-issued OIDC JWT, sent as a bearer token. Authorization is by
**Zitadel project roles** mapped to API planes (`require.plane` middleware). The public API
(`/v1`) requires any role in the Revenue Cloud project (read access: browse, view detail,
download).
**Visibility is scoped to the caller's Zitadel organization:** public skills are visible to
every organization, while private skills are only visible to the owning organization. A
skill's visibility is derived from its manifest during a repo scan and cannot be changed
through the API. There is no `X-Tenant-Id` header in this service — the organization is
resolved from the token.
First-party UI endpoints (GitHub connection, repository management) live in the **internal**
plane (`/v1/internal`) and are documented in a separate spec. Platform-operator endpoints
live in the **admin** plane (`/v1/admin`).
**Base URL:** `/v1`
**Versioning:** URL path prefix per [ADR-0036](https://atlas.revenexx.dev/adr/adr-0036-api-versioning-strategy).
Authenticating requests
To authenticate requests, include an Authorization header with the value "Bearer {ZITADEL_JWT}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
Authenticate with a Zitadel-issued OIDC JWT as a bearer token. The public plane (/v1) requires any role in the Revenue Cloud project (read access). A skill's visibility is resolved against the caller's Zitadel organization.
Skills
List skills visible to the calling organisation.
requires authentication
Optional ?q= filters by name/title/description/tags. Visibility is scoped to
the caller's Zitadel organization: public skills are returned to everyone,
private skills only to the owning organization.
Example request:
curl --request GET \
--get "https://skills.revenexx.ai/api/v1/skills?q=invoice&category=finance&tags=erp%2Cinvoice" \
--header "Authorization: Bearer {ZITADEL_JWT}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://skills.revenexx.ai/api/v1/skills"
);
const params = {
"q": "invoice",
"category": "finance",
"tags": "erp,invoice",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ZITADEL_JWT}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"vendor": "revenexx",
"name": "invoice-sync",
"slug": "revenexx/invoice-sync",
"title": "Invoice Sync",
"description": "Sync invoices between Business Central and the data warehouse.",
"visibility": "public",
"category": "finance",
"tags": [
"invoice",
"erp"
],
"latest_version": "1.2.0",
"latest_download_url": "https://skills.rvnxx.test/api/v1/skills/revenexx/skills-catalog/invoice-sync/versions/1.2.0/download"
}
]
}
Example response (401, Missing or invalid token):
{
"message": "Unauthenticated."
}
Example response (403, No role in the public plane):
{
"message": "Token carries no roles in the public project."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List the distinct, non-empty skill categories visible to the caller's organisation. Powers the category filter on the browse page.
requires authentication
Example request:
curl --request GET \
--get "https://skills.revenexx.ai/api/v1/skills/categories" \
--header "Authorization: Bearer {ZITADEL_JWT}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://skills.revenexx.ai/api/v1/skills/categories"
);
const headers = {
"Authorization": "Bearer {ZITADEL_JWT}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
"data",
"devops",
"finance"
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List the distinct tags across skills visible to the caller's organisation.
requires authentication
Powers the multi-select tag filter on the browse page.
Show a single skill (by vendor + name) with its versions.
requires authentication
Example request:
curl --request GET \
--get "https://skills.revenexx.ai/api/v1/skills/revenexx/skills-catalog/invoice-sync" \
--header "Authorization: Bearer {ZITADEL_JWT}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://skills.revenexx.ai/api/v1/skills/revenexx/skills-catalog/invoice-sync"
);
const headers = {
"Authorization": "Bearer {ZITADEL_JWT}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"vendor": "revenexx",
"repo": "skills-catalog",
"name": "invoice-sync",
"slug": "revenexx/skills-catalog/invoice-sync",
"title": "Invoice Sync",
"description": "Sync invoices between Business Central and the data warehouse.",
"visibility": "public",
"category": "finance",
"tags": [
"invoice",
"erp"
],
"keywords": [
"invoice",
"business-central"
],
"authors": [
{
"name": "Jane Doe",
"email": "jane@revenexx.com"
}
],
"homepage": "https://docs.revenexx.com/skills/invoice-sync",
"license": "MIT",
"targets": [
"claude-code",
"cursor"
],
"allowed_tools": [
"Bash",
"Read"
],
"latest_version": "1.2.0",
"readme": "# Invoice Sync\n\nSyncs invoices…",
"latest_download_url": "https://skills.rvnxx.test/api/v1/skills/revenexx/skills-catalog/invoice-sync/versions/1.2.0/download",
"versions": [
{
"version": "1.2.0",
"description": "Sync invoices between Business Central and the data warehouse.",
"artifact_hash": "sha256:7f3b1c9a2e4d5f6071829304a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5c6d7e",
"artifact_bytes": 20480,
"registered_at": "2026-06-20T09:12:00Z"
}
]
}
}
Example response (404, Skill not found or not visible to caller):
{
"message": "Not Found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Stream the zip artifact for a specific version of a skill.
requires authentication
Serves both the CLI install and a direct zip download for any AI chat/agent
(the registry is agent-agnostic, not Claude-only). The response body is the
raw skill bundle streamed as an application/zip attachment named
{name}-{version}.zip — it is not a JSON document.
Example request:
curl --request GET \
--get "https://skills.revenexx.ai/api/v1/skills/revenexx/skills-catalog/invoice-sync/versions/1.2.0/download" \
--header "Authorization: Bearer {ZITADEL_JWT}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://skills.revenexx.ai/api/v1/skills/revenexx/skills-catalog/invoice-sync/versions/1.2.0/download"
);
const headers = {
"Authorization": "Bearer {ZITADEL_JWT}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Skill bundle):
Binary `application/zip` stream (Content-Disposition: attachment; filename="{name}-{version}.zip"). Not a JSON document.
Example response (404, Skill or version not found / not visible to caller):
{
"message": "Not Found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show a single version of a skill, including that version's README.
requires authentication
Unlike the skill detail endpoint (whose readme is always the latest
version's), this returns the README and metadata of the exact version
requested, plus parent-skill context (title, latest_version,
is_latest) so the UI can flag when an older version is being viewed.
Example request:
curl --request GET \
--get "https://skills.revenexx.ai/api/v1/skills/revenexx/skills-catalog/invoice-sync/versions/1.2.0" \
--header "Authorization: Bearer {ZITADEL_JWT}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://skills.revenexx.ai/api/v1/skills/revenexx/skills-catalog/invoice-sync/versions/1.2.0"
);
const headers = {
"Authorization": "Bearer {ZITADEL_JWT}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"version": "1.2.0",
"description": "Sync invoices between Business Central and the data warehouse.",
"readme": "# Invoice Sync\n\nSyncs invoices…",
"visibility": "public",
"allowed_tools": [
"Bash",
"Read"
],
"artifact_hash": "sha256:7f3b1c9a2e4d5f6071829304a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5c6d7e",
"artifact_bytes": 20480,
"source_ref": "refs/tags/v1.2.0",
"registered_at": "2026-06-20T09:12:00Z",
"title": "Invoice Sync",
"latest_version": "1.2.0",
"is_latest": true
}
}
Example response (404, Skill or version not found / not visible to caller):
{
"message": "Not Found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.