API

Public endpoints return JSON unless noted. No authentication required. All theme endpoints support ETag-based caching via If-None-Match.

Themes

GET /api/themes

List all available themes.

ETag reflects the entire manifest. Changes when any theme is updated.

Parameters
q Search by name, description, or tags
tags Comma-separated tag filter (AND logic)
core_version Filter to themes compatible with this pure-admin-core version (e.g. 2.0.0)
GET /api/themes/:slug

Get metadata for a single theme. Response includes content_sha which matches the ETag header.

ETag is the theme's content_sha — only changes when this specific theme is updated.

GET /api/themes/:slug/download

Download the theme as a ZIP package. Contains CSS, SCSS, fonts, theme.json (with integrity checksums), and README. Defaults to the latest version.

Parameters
version Specific version to download (e.g. 2.0.2). Omit for latest.
Response: application/zip
GET /api/bundle

Download a ZIP bundle of multiple themes, structured for the Pure Admin demo server. Includes a generated themes.json with correct paths.

Parameters
themes Comma-separated theme slugs. Omit to include all themes.
Response: application/zip

Tools

GET /api/tools

List available development tools with their current versions.

GET /api/tools/:name

Download a specific tool script. Returns the X-Tool-Version header for update checking.

Scripts include self-update: set PUREADMIN_AUTO_UPDATE=1 to auto-update on run.

Response: application/javascript
GET /api/tools/template

Download a theme repository template as a ZIP. Contains theme.json, starter SCSS, package.json with build/pack/publish scripts, .gitignore, and README.

Parameters
id Theme slug (lowercase, hyphens). Used in filenames and package name. Default: my-theme
name Display name for the theme. Default: humanized id
Response: application/zip

Caching & Integrity

All theme API responses include an ETag header. Send If-None-Match with the ETag value to receive 304 Not Modified when content hasn't changed.

Endpoint ETag source Changes when
/api/themes Manifest etag Any theme is updated
/api/themes/:slug Theme's content_sha Only when that specific theme changes

Theme package integrity

Each theme ZIP contains a theme.json with SHA-256 checksums for every file in the package, a metadata hash, and a content_sha that matches the ETag returned by the API. Clients can verify downloads by comparing the checksums.content_sha in theme.json against the ETag they received.

// theme.json inside the ZIP
{
  "checksums": {
    "files": {
      "css/audi.css": "sha256:bead...",
      "assets/fonts/FiraSans.woff2": "sha256:ab12..."
    },
    "metadata": "sha256:ef56...",
    "content_sha": "sha256:9a53..."  // matches ETag
  },
  "external_domains": ["fonts.googleapis.com"],
  "scripts": []
}

Usage Examples

Download a single theme

curl -fsSL -o audi.zip https://pureadmin.io/api/themes/audi/download

Conditional fetch with ETag

# First request — save the ETag
curl -sI https://pureadmin.io/api/themes/audi | grep etag
# etag: "sha256:61df..."

# Subsequent requests — 304 if unchanged
curl -s -o /dev/null -w "%{http_code}" \
  -H 'If-None-Match: "sha256:61df..."' \
  https://pureadmin.io/api/themes/audi
# 304

Download all themes as a bundle

curl -fsSL -o themes.zip https://pureadmin.io/api/bundle\nunzip themes.zip -d themes/

Dockerfile

ARG THEMES_URL=https://pureadmin.io/api/bundle
RUN curl -fsSL -o /tmp/themes.zip "${THEMES_URL}" && \
    unzip -o /tmp/themes.zip -d themes/ && \
    rm /tmp/themes.zip

Fetch theme list (JavaScript)

const res = await fetch('https://pureadmin.io/api/themes');\nconst etag = res.headers.get('etag');\nconst { themes } = await res.json();\n\n// Later: skip if unchanged\nconst res2 = await fetch('https://pureadmin.io/api/themes', {\n  headers: { 'If-None-Match': etag }\n});\nif (res2.status === 304) console.log('No changes');

Bootstrap a new theme project

# Scaffold a new theme project with the CLI
npx @keenmate/pureadmin init my-theme "My Theme"
cd my-theme && npm install

# Build, pack, publish
npx @keenmate/pureadmin build
npx @keenmate/pureadmin pack
npx @keenmate/pureadmin publish --api-key KEY

Verify download integrity

# Get the ETag from the API
ETAG=$(curl -sI https://pureadmin.io/api/themes/audi | grep -i etag | awk '{print $2}' | tr -d '"\r')

# Download and extract content_sha from the ZIP
curl -fsSL -o audi.zip https://pureadmin.io/api/themes/audi/download
SHA=$(unzip -p audi.zip theme.json | python3 -c "import sys,json; print(json.load(sys.stdin)['checksums']['content_sha'])")

# Compare
[ "$ETAG" = "$SHA" ] && echo 'Integrity OK' || echo 'MISMATCH'