Reference

API

Stronghold holds fonts, gradients, palettes, icons, textures, HDRIs, models, packs, patterns, audio, shaders, curves and LUTs. The API exists so they can leave the browser — converted into the formats your actual tools read, or bundled as one archive.

Recipes

Find assets

curl 'https://stronghold.manganum.com/api/palettes?q=sunset&limit=5'

Every list endpoint takes q, page and limit. Icons, palettes, shaders and patterns also take sort=random with a stable seed.

A palette for Illustrator

curl -OJ 'https://stronghold.manganum.com/api/export/palettes/<id>?format=ase'

-OJ keeps the filename the server sends. Double-click the .ase to load it as a colour group.

A whole icon set as one sprite

curl -OJ 'https://stronghold.manganum.com/api/export/icons?format=bundle&iconSet=lucide&limit=500'

Gives you sprite.svg, a CSS mask sheet, an Iconify collection and every individual SVG.

Selected icons as React components

curl -OJ -X POST 'https://stronghold.manganum.com/api/export/icons' \
  -H 'content-type: application/json' \
  -d '{"format":"react","ids":["<id>","<id>"]}'

POST when the id list would overflow a URL. Up to 2000 ids per request.

A gradient as a colour-grading LUT

curl -OJ 'https://stronghold.manganum.com/api/export/gradients/<id>?format=cube'

A 33³ 3D LUT mapping input luma onto the gradient. Load it in Resolve, Premiere, Final Cut or OBS.

A complete font family

curl -OJ 'https://stronghold.manganum.com/api/export/fonts/<id>?format=zip'

Every weight, @font-face CSS pointing at the bundled files, and a specimen page you can open offline.

A mixed selection as a style kit

curl -OJ -X POST 'https://stronghold.manganum.com/api/export/kit' \
  -H 'content-type: application/json' \
  -d '{"name":"Landing page","items":[
    {"type":"fonts","id":"<id>"},
    {"type":"palettes","id":"<id>"},
    {"type":"gradients","id":"<id>"}
  ]}'

One archive with each asset in its native format, plus a combined kit.css and an index.html overview.

Use a font on any web page

<link rel="stylesheet" href="https://stronghold.manganum.com/api/fonts/css?ids=<id>">
<style>body { font-family: 'Family Name', sans-serif; }</style>

Ready-made @font-face rules; the font files answer any origin, so this works from any site.

A PBR material straight into Blender

curl -OJ 'https://stronghold.manganum.com/api/export/textures/<id>?format=blender&resolution=4k'
blender --python <the downloaded script>.py

The script fetches the maps from the source CDN and builds the node tree. three.js, Godot and Unity forms exist too — and `&dry=1` on any export URL validates without downloading.

Scripted access with an API key

curl 'https://stronghold.manganum.com/api/collections' \
  -H 'X-API-Key: ak_...' \
  -H 'X-Stronghold-User: <user uuid>'

An Alexandria key scoped to the stronghold app. The user header is only needed for per-user routes. Keys never grant admin.

Browsing

EndpointNotes
GET /api/fontsq, category, page, limit
GET /api/gradientsq, type, source
GET /api/palettesq, source, colors, sort, seed
GET /api/iconsq, set, sort, seed
GET /api/shadersq, source, type, language, sort
GET /api/patternsq, type, tile, source, sort (incl. tile-asc)
GET /api/assetsCounts of every type; with ?type=, a page of the eight types that have no endpoint of their own
GET /api/assets/{id}One asset, whichever type it belongs to
GET /api/fonts/css?ids=@font-face rules, or an @import for Google-hosted families
POST /api/uploadMultipart image or font, private to you; the bytes decide the type
GET /api/collectionsRequires a caller identity
POST /api/collections/{id}One { assetType, assetId }, or an items array of up to 200
GET /api/collections/{id}/exportThe whole collection as one style kit

Responses are { items, total, page, limit, pages }. limit is capped at 100. sort=random is seeded, so paging a shuffled list never repeats or skips an item — pass back the seed from filters to keep the same shuffle.

Exporting

EndpointNotes
GET /api/export/formatsThe catalog. Read this instead of hard-coding format ids.
GET /api/export/{type}/{id}?format=One asset
GET /api/export/{type}?format=&ids=Several assets merged into one file
GET /api/export/icons?format=&iconSet=A whole icon set, without listing ids
POST /api/export/{type}Same as GET, for id lists too long for a URL
POST /api/export/kitA mixed selection as one style-kit archive
GET /api/collections/{id}/exportA saved collection as a style kit

Raster and sampling parameters: width and height for PNG targets, steps when a gradient is reduced to discrete swatches. At most 2000 assets per request. Formats marked batch below can merge a selection; the rest handle one asset at a time.

Formats

Palettes

Design tools

formatfilewhat it isreads itbatch
ase.aseSwatch group for the Adobe appsIllustrator, Photoshop, InDesign, Affinityyes
aco.acoNamed swatches for the Swatches panelPhotoshopyes
act.actIndexed-colour table, capped at 256 entriesPhotoshop, GIF pipelinesyes
gpl.gplDrop into the palettes folderGIMP, Inkscape, Krita, MyPaintyes
pal.palClassic pixel-art palette formatPaint Shop Pro, Aseprite, GrafX2yes
soc.socCustom colour table for the Office suiteLibreOffice, OpenOfficeyes
sketchpalette.sketchpaletteFor the Sketch Palettes pluginSketchyes
procreate.swatchesSplits into palettes of 30, the Procreate limitProcreateyes

Code

formatfilewhat it isreads itbatch
css.cssCustom properties plus an all-stops list—yes
scss.scssVariables plus a Sass map—yes
tailwind.jstheme.extend.colors blockTailwind CSS 3yes
tailwind4.css@theme block with --color-* tokensTailwind CSS 4yes
tokens.jsonW3C design-tokens draft formatTokens Studio, Style Dictionaryyes
swift.swiftColor extensionXcodeyes
kotlin.ktJetpack Compose Color valuesAndroid Studioyes

Image

formatfilewhat it isreads itbatch
svg.svgLabelled grid, for presentations——
png.pngProportional bands, no text——

Data

formatfilewhat it isreads itbatch
json.jsonHex, RGB, HSB and Lab for every colour—yes
txt.txtOne hex value per line—yes

Gradients

Design tools

formatfilewhat it isreads itbatch
ggr.ggrSegment-based, keeps midpoints and alphaGIMP, Inkscape, Krita—
ase.aseSampled into discrete swatchesIllustrator, Photoshopyes
gpl.gplSampled into 16 swatchesGIMP, Kritayes
cube.cube3D LUT mapping luma onto the gradientDaVinci Resolve, Premiere, Final Cut, OBS—

Code

formatfilewhat it isreads itbatch
css.cssCustom property plus a utility class—yes
tailwind.cssv4 @theme entry, with the v3 config in a commentTailwind CSSyes
blender.pyScript that builds the node, in linear colourBlender—
swiftui.swiftGradient stops plus the matching shapeXcode—
glsl.glslvec3 ramp(float t) for shadersShadertoy, TouchDesigner, WebGL—
android.xmlShape drawable with start/center/endAndroid Studio—

Image

formatfilewhat it isreads itbatch
svg.svgVector gradient, editable after importFigma, Illustrator, Inkscape—
png.pngRendered raster, exact at both ends——

Data

formatfilewhat it isreads itbatch
json.jsonStops, angle, interpolation space and CSS—yes

Icons

Code

formatfilewhat it isreads itbatch
datauri.txtPercent-encoded, for CSS url()——
datauri-base64.txtFor tools that reject percent-encoding——
css.cssOne class per icon, recoloured by currentColor—yes
css-bg.cssKeeps the icon’s own colours, for logos—yes
react.zipOne .tsx per icon plus a barrel indexReact, Next.jsyes
svelte.zipOne .svelte per icon plus a barrel indexSvelte 5yes
vue.zipOne SFC per icon plus a barrel indexVue 3, Nuxtyes

Image

formatfilewhat it isreads itbatch
svg.svgSingle normalized iconFigma, Illustrator, Sketch—

Bundles

formatfilewhat it isreads itbatch
sprite.svg<symbol> sheet for <use href="#id">—yes
zip.zipIndividual files, grouped by set—yes
bundle.zipSprite, CSS, Iconify JSON and every SVG—yes

Data

formatfilewhat it isreads itbatch
iconify.jsonCollection JSON with shared dimensionsIconify, unplugin-icons, Figma Iconifyyes

Fonts

Code

formatfilewhat it isreads itbatch
css.cssPoints at this server; @import for Google families—yes

Bundles

formatfilewhat it isreads itbatch
zip.zipEvery weight, @font-face CSS and a specimen—yes
specimen.htmlSelf-contained weights and sizes preview——

Data

formatfilewhat it isreads itbatch
json.jsonMetadata, weights, axes and file list—yes

Shaders

Design tools

formatfilewhat it isreads itbatch
isf.fsInteractive Shader Format with a JSON headerVDMX, Resolume, CoGe, Millumin—

Code

formatfilewhat it isreads itbatch
frag.fragStored code with a provenance header——
standalone.fragUniform block and a real main()glslViewer, Bonzomatic, WebGL—
shadertoy.glslPaste-ready; host uniforms strippedShadertoy—

Bundles

formatfilewhat it isreads itbatch
html.htmlWebGL harness with no dependencies——
zip.zipEvery host format plus a preview page——

Data

formatfilewhat it isreads itbatch
json.jsonCode plus declared uniforms—yes

patterns

Code

formatfilewhat it isreads itbatch
css.cssTile inlined as a data URI, recoloured by currentColor—yes
tailwind.cssv4 @theme background-image entryTailwind CSSyes

Image

formatfilewhat it isreads itbatch
svg.svgReal <pattern> element, so it stays a repeat after importFigma, Illustrator, Inkscape—
tile.svgOne tile at its natural size, to build a pattern fill fromFigma, Illustrator, Sketch—

Bundles

formatfilewhat it isreads itbatch
sheet.htmlEvery pattern tiling, with a colour picker—yes
zip.zipTiles, tiling SVGs, CSS and a review sheet—yes

Data

formatfilewhat it isreads itbatch
json.jsonTile size, markup and ready-made CSS—yes

curves

Design tools

formatfilewhat it isreads itbatch
blender.pyScript that sets the keyframe Bezier handlesBlender—
aftereffects.jsxEvaluates the real curve; AE influences cannotAfter Effects—

Code

formatfilewhat it isreads itbatch
css.cssCustom property, or @keyframes for a spring—yes
tailwind.css@theme --ease-* tokenTailwind CSSyes
js.tsStandalone easing function, no dependencies——
swiftui.swifttimingCurve, or an exact interpolatingSpringXcode—
flutter.dartCubic, or an exact SpringDescriptionFlutter—
unity.csKeyframe tangents derived from the control handlesUnity—
glsl.glslShader-friendly, fixed iteration countShadertoy, TouchDesigner, WebGL—

Image

formatfilewhat it isreads itbatch
svg.svgThe curve drawn in its unit box, for docs——

Bundles

formatfilewhat it isreads itbatch
sheet.htmlEvery selected curve plotted side by side—yes
zip.zipEvery dialect plus a plot and a readme——

Data

formatfilewhat it isreads itbatch
json.jsonDefinition, CSS value and sampled points—yes
csv.csv64 x,y pairs for spreadsheets and scripts——

textures

Design tools

formatfilewhat it isreads itbatch
blender.pyBuilds the node graph, with correct colour spacesBlender—

Code

formatfilewhat it isreads itbatch
three.jsMeshStandardMaterial with the maps loadedthree.js—
godot.tresStandardMaterial3D resourceGodot 4—
unity.csEditor script that sets import settings tooUnity—

Bundles

formatfilewhat it isreads itbatch
download.shcurl with resume and checksum verification—yes
zip.zipEvery engine, the download script and a readme——

Data

formatfilewhat it isreads itbatch
markdown.mdMaps, sizes, colour spaces and credits——
json.jsonCanonical map names and download URLs—yes

luts

Design tools

formatfilewhat it isreads itbatch
cube.cube33³ by default; verified in ffmpeg, and what every NLE readsDaVinci Resolve, Premiere, Final Cut, OBS, ffmpeg—

Image

formatfilewhat it isreads itbatch
hald.png512×512 image describing a 64³ cubeffmpeg, ImageMagick—
preview.pngReference image, ungraded above and graded below——

Bundles

formatfilewhat it isreads itbatch
sheet.htmlEvery selected LUT applied to the same inputs—yes
zip.zipCube, 3DL, Hald, preview, recipe and a readme——

Data

formatfilewhat it isreads itbatch
json.jsonThe operation stack, for computing the cube yourself—yes

hdris

Design tools

formatfilewhat it isreads itbatch
blender.pyWorld node graph with rotation and strength exposedBlender—

Code

formatfilewhat it isreads itbatch
three.jsRight loader, equirectangular mapping, scene.environmentthree.js—
godot.tresEnvironment with a panorama sky, lighting and reflections onGodot 4—
unity.csEditor script: import settings, skybox material, ambient sourceUnity—

Bundles

formatfilewhat it isreads itbatch
download.shcurl with resume and checksum verification—yes
zip.zipEvery engine, the download script and a readme——

Data

formatfilewhat it isreads itbatch
markdown.mdResolutions, dynamic range, white balance and credits——
json.jsonEvery resolution and format, with download URLs—yes

models

Design tools

formatfilewhat it isreads itbatch
blender.pyRight operator per format; .blend is appended, not importedBlender—

Code

formatfilewhat it isreads itbatch
three.jsGLTFLoader, added to the scene, shadows enabledthree.js—
godot.tscnNode3D with the imported model instanced under itGodot 4—
unity.csEditor script: FBX scale, normal maps, URP materialUnity—

Bundles

formatfilewhat it isreads itbatch
download.shRebuilds the exact file tree the model references—yes
zip.zipEvery engine, the download script and a readme——

Data

formatfilewhat it isreads itbatch
markdown.mdFormats, polycount, real-world size and the file list——
json.jsonEvery format and resolution, with relative paths—yes

packs

Design tools

formatfilewhat it isreads itbatch
blender.py3D kits: imports every model, laid out in a gridBlender—

Code

formatfilewhat it isreads itbatch
unity.csFixes scale, point filtering and colour space across the packUnity—
three.js3D kits: load a piece by name, cloned and cachedthree.js—

Bundles

formatfilewhat it isreads itbatch
download.shFetches, unpacks, and prints an inventory of what arrived—yes
zip.zipEverything that applies to this pack, plus a readme——

Data

formatfilewhat it isreads itbatch
markdown.mdContents, layout and what to watch for per category——
json.jsonMetadata and the archive URL—yes

audio

Bundles

formatfilewhat it isreads itbatch
download.shcurl with resume, and writes the credits beside the files—yes
convert.shMono OGG and WAV at 44.1 kHz, which is what engines wantffmpeg, Unity, Godotyes
zip.zipCredits, scripts, playlist and manifest — no audio—yes

Data

formatfilewhat it isreads itbatch
credits.mdTitle, creator, licence and source per track — what CC-BY requires—yes
attribution.txtOne line per track, for a credits screen or a video description—yes
m3u.m3uStreams from the source; titles are the credit linesVLCyes
json.jsonMetadata, stream URLs and the composed credit line—yes

Integrating

The read surface is built to be consumed by other software — editors, engines, build steps, plugins, agents. Three properties make that dependable:

Open to any origin
Every public read — listings, single assets, files, exports, this spec — answers cross-origin requests with an uncredentialed Access-Control-Allow-Origin: *, so a browser-based tool calls the API directly from its own origin. A cross-origin caller is always anonymous; per-user routes and every write stay same-origin.
Validate before downloading
Any export URL plus &dry=1 runs the full server-side validation and answers 204 — or the readable error — without the body. Use it before handing a URL to a download manager, or to check a model really has the FBX its Unity export needs.
Machine-readable everything
The OpenAPI 3.1 description and the format catalogue are generated from the same definitions the endpoints use, and contract tests hold them together. Format ids and response shapes are stable; new ones are added without renaming existing ones.
MCP for agents
POST /api/mcp speaks the Model Context Protocol: search_assets, get_asset, list_export_formats, export_asset, list_collections, export_collection. Text exports come back inline; binaries as a download link. Anonymous callers search and export the public library; an API key adds collections.

Authentication

Browsing is public. Anything belonging to a user — collections, favourites — needs a caller identity. Three credentials work:

Session cookie
Alexandria SSO. Sign in at /login; the jwt cookie is verified locally against Alexandria's JWKS. Access also requires an assignment to the stronghold app.
API key
An Alexandria ak_… key scoped to stronghold, for scripts, CI and MCP clients. Send it as X-API-Key or Authorization: Bearer ak_…. Add X-Stronghold-User: <uuid> for per-user routes. An API key never grants admin, so scraper control stays session-only.
Alexandria JWT
Your own Alexandria JWT as Authorization: Bearer <jwt>, for a service acting on behalf of a signed-in user. It is scoped exactly like the cookie.

A key that is present but invalid returns 401 rather than falling back to anonymous access, so a broken credential surfaces instead of quietly degrading.

Uploading

Two shelves accept your own files: Images and Fonts. Both need a caller identity. A session cookie always has one. An API key only does where the deployment enables X-Stronghold-User; otherwise POST /api/upload answers 401, because an upload has to belong to somebody.

Everything else — textures, HDRIs, models, packs, palettes, gradients, icons, shaders, patterns, curves, LUTs, audio — is either scraped from a source with a stated licence or generated here (the cosine gradients, the easing curves, the generated patterns and LUTs). Neither has an upload path, and that is deliberate: every row in the public library has a licence someone can point at. A licence you type on the upload form is recorded as given — trimmed, never checked and never guessed — which is why an upload stays private to you instead of joining that library. Leave the field empty and it is recorded as Unknown (uploaded).

Limits
25 MB per image, 8 MB per font file, 250 MB and 200 font files per account. The declared content type is ignored; the leading bytes decide what a file is, and an SVG is sanitised before it is stored.
No detail page
Images is deliberately a flat shelf: a plain image has no maps, weights, stops or code to inspect, so there is no /images/{id} route the way every other shelf has one. The card shows the file's dimensions and format, and the API serves the full record at /api/assets/{id}.
Visibility
Uploads are private, and /api/files/uploads/… serves them only to their owner. They appear on your shelves and can go into collections. An uploaded font exports like any other — a style kit carries its files and @font-face rules. An uploaded image does not: plain images have no export format, so one sits in a collection without adding anything to the kit.

Licensing

Assets carry their own licenses, and the API reports them per asset. Font bundles and icon bundles include the license text in their README.md. Check it before shipping: it governs embedding, modification and redistribution, and it varies from CC0 to non-commercial-only across the sources.