HTTP API

Hosted at https://navii-api.uxderrick.com. No auth, public CORS, fully cacheable. Plain text errors, image responses for everything else.

GET /avatar/:seed[.svg|.png]

Returns a deterministic mascot avatar for the given seed. Same seed → same avatar, byte-for-byte. Append .png to the seed to receive a rasterized PNG instead of SVG.

Path

ParamTypeDescription
:seedstringAny unique identifier. Use a stable user id, UUID, or email. Avoid display names — see the seed rule.

Query

ParamTypeDefaultDescription
sizeint96Output size in px. Clamped to 16–1024.
paletteenumseededForce a color family. See palette catalog.
backgroundenumseedednone · solid · ring.
tileBgcolornoneOpaque circular fill behind avatar. Any CSS color (URL-encoded, e.g. %23ffffff) or auto to use the palette accent.
titlestringnoneAccessible label. Adds role="img" + aria-label to the SVG root.
animated0 / 10Idle motion (float, blink, antenna sway, spark pulse, twinkle). SVG only — ignored for PNG. Honors prefers-reduced-motion.

Examples

https://navii-api.uxderrick.com/avatar/alice
https://navii-api.uxderrick.com/avatar/alice?palette=violet&animated=1
https://navii-api.uxderrick.com/avatar/alice?tileBg=%23ffffff
https://navii-api.uxderrick.com/avatar/alice.png?size=512&tileBg=auto

GET /group

Renders multiple seeded avatars as a single horizontally-stacked SVG with optional overlap and a +N counter tile for overflow.

Query

ParamTypeDefaultDescription
seedscsvComma-separated seeds (up to 50). Required.
sizeint64Per-tile size in px. Clamped to 16–256.
overlapfloat0.3Fraction each tile overlaps the previous. 0 = no overlap, 0.7 = heavy stack.
maxintallMax tiles to render. Extra seeds collapse into a +N tile.
ringcolor#ffffffBorder color around each tile.
tileBgcolor#ffffffOpaque fill behind each avatar (prevents overlap show-through).
animated0 / 10Per-avatar animation.

SDK-only: counterFill and counterInk (the +N tile's colors) are settable via GroupOptions in @usenavii/core but not yet wired to query params.

Utility endpoints

PathDescription
GET /Landing page with live playground.
GET /apiService metadata as JSON. Returns { "name": "navii", "version": "...", "endpoints": {...} }.
GET /healthzLiveness probe. Returns { "ok": true, "pngCacheSize": N }.
GET /galleryHTML grid of N seeded avatars (visual debug).
GET /favicon.svgBrand favicon. SVG.
GET /apple-touch-icon.png180×180 dark-tile icon for iOS home-screen.
GET /og.png1200×630 Open Graph image. No params.
GET /robots.txt, /sitemap.xmlSEO essentials.

Response headers

All image responses set:

  • cache-control: public, max-age=31536000, immutable — safe to cache forever (seed + params fully determine bytes).
  • access-control-allow-origin: * — embed anywhere, no preflight for GET.
  • content-type: image/svg+xml; charset=utf-8 for SVG, image/png for PNG, application/json for /api + /healthz.

Rate-limited routes additionally emit:

  • x-ratelimit-limit — max requests in the current window.
  • x-ratelimit-remaining — remaining requests.
  • x-ratelimit-reset — Unix epoch seconds when the window resets.
  • retry-after — only on 429 responses.

Errors

Plain-text bodies. Status codes:

StatusMeaningBody
400Bad requestseed required · seeds required (comma-separated)
429Rate limitedRate limit exceeded
501Not implementedPNG rasterization unavailable: ... — server missing @resvg/resvg-js. SVG endpoint still works.

Rate limits

/avatar/* is limited to 600 req/min/IP. Other routes are unlimited. Exceeded → HTTP 429 + Retry-After.

Full table, cache rationale, and self-hosting tuning live on the dedicated Rate limits page.

Seeds and URL encoding

Anything you can put in a URL path can be a seed. Seeds with @, ., or other URL-special chars work — just URL-encode them on the client (most browsers do this automatically inside <img src>).

raw:     alice@example.com
encoded: alice%40example.com

The server decodes back to the raw seed before hashing, so both URLs produce the same SVG. Empty seeds → 400.

Versioning and stability

The deterministic contract is scoped to a single release of the engine. A given seed + a given engine version → byte-identical SVG, forever. We won't silently change that.

What we promise to keep stable in patch + minor releases:

  • Existing seeds' part selections don't shift when new variants are added (new parts append to the PRNG stream, never insert).
  • Endpoint URLs, query params, and response headers stay backwards-compatible.
  • SVG markup may change in tiny non-visible ways (formatting, attribute order) — treat as text-content stable, not byte-stable across upgrades.

What can change in a major release:

  • Cast rebases (existing seeds get new combinations). Documented in the changelog.
  • Default option values.

If you need absolute byte-stability across engine upgrades, mirror the SVG bytes locally — see the caching recipe.

Authentication

None. Every endpoint is anonymous. CORS is wide open (access-control-allow-origin: *) — embed from anywhere, no token, no signup. If you need to lock down a self-hosted deployment, put it behind your own auth layer (Cloudflare Access, BasicAuth via Caddy, etc.).