Icon Packs

Icon packs are collections of SVG device icons, typically imported from Visio stencil (.vssx) files. Listing and viewing icons is available to all authenticated users. Import, update, and delete require admin role.

List Icon Packs

GET /api/v1/icon-packs

List all icon packs with icon counts. Auth: any authenticated user.

Response: 200 OK

[
  {
    "id": "uuid",
    "name": "Cisco Network",
    "builtin": false,
    "brand_color": "#049FD9",
    "created_by": "user-uuid",
    "created_at": "2026-03-03T12:00:00Z",
    "icon_count": 42
  }
]

List Icons in Pack

GET /api/v1/icon-packs/{packID}/icons

List all icons in a pack. Returns metadata only (no svg_data) for performance. Auth: any authenticated user.

Response: 200 OK

[
  {
    "id": "uuid",
    "pack_id": "pack-uuid",
    "name": "Router",
    "device_type": "router",
    "width": 200,
    "height": 200
  }
]

Get Icon SVG

GET /api/v1/icon-packs/{packID}/icons/{iconID}/svg

Returns the raw SVG markup for a single icon. Auth: any authenticated user.

Response: 200 OK — Content-Type: image/svg+xml, Cache-Control: public, max-age=86400, immutable

The response body is raw SVG XML, not JSON. Suitable for direct use in <img src> or fetch().


Get Icon PNG

GET /api/v1/icon-packs/{packID}/icons/{iconID}/png

Returns the icon rendered to a PNG (server-side via rsvg-convert), used as the canvas background-image for imported packs — cytoscape clips SVG background-images at non-1 zoom (#2750). Rendered once and cached in-memory; auth: any authenticated user.

Response: 200 OK — Content-Type: image/png, Cache-Control: public, max-age=86400, immutable

Error responses:


Get Builtin Icon PNG

GET /api/v1/icon-packs/builtin/{pack}/icons/{deviceType}/png[?color=%23RRGGBB]

Builtin packs (default, industrial, osprey3d) live in the binary, not the database, so they have no icon id — this is their equivalent of the endpoint above. The path parameter is pack, not packID: params ending in ID are validated as UUIDs, and a builtin pack id is a name. Used as the canvas background-image for packs whose artwork is too complex to hand the browser as a vector: cytoscape re-rasterizes an SVG background-image at every zoom level, which on the Osprey 3D pucks (130-170 paths per icon) drops the canvas to single-digit fps. A 256px PNG is decoded once and reused at every zoom.

color applies the pack's area recoloring server-side (brand-color substitution or face tint, depending on the pack), so the canvas and the Visio export share one implementation. A device type the pack does not ship falls back to its router icon. Rendered once and cached in-memory (bounded); auth: any authenticated user.

Response: 200 OK — Content-Type: image/png, Cache-Control: public, max-age=86400, immutable

Error responses:


Import Icon Pack (Admin)

POST /api/v1/icon-packs/import

Import a Visio stencil (.vssx) as an icon pack. Admin-only.

Body size limit: 20 MB

Request body:

{
  "name": "Cisco Network",
  "data": "<base64-encoded .vssx file>"
}
Field Type Required Description
name string Yes Display name for the icon pack (max 255 chars)
data string Yes Base64-encoded .vssx stencil file

Response: 201 Created

{
  "id": "uuid",
  "name": "Cisco Network",
  "builtin": false,
  "brand_color": "#049FD9",
  "created_by": "user-uuid",
  "created_at": "2026-03-03T12:00:00Z",
  "icon_count": 42,
  "icons": [
    {
      "id": "uuid",
      "pack_id": "pack-uuid",
      "name": "Router",
      "device_type": "router",
      "width": 200,
      "height": 200
    }
  ]
}

Notes:

Error responses:


Update Icon (Admin)

PUT /api/v1/icon-packs/{packID}/icons/{iconID}

Update an icon's device_type mapping. Admin-only.

Request body:

{
  "device_type": "switch"
}

Response: 200 OK — Updated icon (without svg_data)

Error responses:


Duplicate Icon (Admin)

POST /api/v1/icon-packs/{packID}/icons/{iconID}/duplicate

Copy an icon (same SVG and dimensions) into a new, unassigned icon in the same pack, so one artwork can be assigned to multiple roles (e.g. ABR and ASBR). The copy is named "<name> (copy)" (or "<name> (copy 2)", … if that name is taken) and starts with no device_type. Admin-only. No request body.

Response: 201 Created — New icon (without svg_data)

Error responses:


Delete Icon Pack (Admin)

DELETE /api/v1/icon-packs/{packID}

Delete an icon pack and all its icons. Built-in packs cannot be deleted. Admin-only.

Response: 204 No Content

Error responses: