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
| Param | Type | Description |
|---|---|---|
:seed | string | Any unique identifier. Use a stable user id, UUID, or email. Avoid display names — see the seed rule. |
Query
| Param | Type | Default | Description |
|---|---|---|---|
size | int | 96 | Output size in px. Clamped to 16–1024. |
palette | enum | seeded | Force a color family. See palette catalog. |
background | enum | seeded | none · solid · ring. |
tileBg | color | none | Opaque circular fill behind avatar. Any CSS color (URL-encoded, e.g. %23ffffff) or auto to use the palette accent. |
title | string | none | Accessible label. Adds role="img" + aria-label to the SVG root. |
animated | 0 / 1 | 0 | Idle 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
| Param | Type | Default | Description |
|---|---|---|---|
seeds | csv | — | Comma-separated seeds (up to 50). Required. |
size | int | 64 | Per-tile size in px. Clamped to 16–256. |
overlap | float | 0.3 | Fraction each tile overlaps the previous. 0 = no overlap, 0.7 = heavy stack. |
max | int | all | Max tiles to render. Extra seeds collapse into a +N tile. |
ring | color | #ffffff | Border color around each tile. |
tileBg | color | #ffffff | Opaque fill behind each avatar (prevents overlap show-through). |
animated | 0 / 1 | 0 | Per-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
| Path | Description |
|---|---|
GET / | Landing page with live playground. |
GET /api | Service metadata as JSON. Returns { "name": "navii", "version": "...", "endpoints": {...} }. |
GET /healthz | Liveness probe. Returns { "ok": true, "pngCacheSize": N }. |
GET /gallery | HTML grid of N seeded avatars (visual debug). |
GET /favicon.svg | Brand favicon. SVG. |
GET /apple-touch-icon.png | 180×180 dark-tile icon for iOS home-screen. |
GET /og.png | 1200×630 Open Graph image. No params. |
GET /robots.txt, /sitemap.xml | SEO 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 forGET.content-type: image/svg+xml; charset=utf-8for SVG,image/pngfor PNG,application/jsonfor/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 on429responses.
Errors
Plain-text bodies. Status codes:
| Status | Meaning | Body |
|---|---|---|
| 400 | Bad request | seed required · seeds required (comma-separated) |
| 429 | Rate limited | Rate limit exceeded |
| 501 | Not implemented | PNG 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.).