| Entity | Key | Purpose |
|---|---|---|
spool |
card_uids |
Comma-separated uppercase hex NFC UIDs associated with the spool |
filament |
variant |
Filament subtype / variant (e.g. “Silk”, “Matte”) |
Both fields use Spoolman’s double-serialised string convention: the inner value is
JSON-encoded before storage, so a single UID "AABBCCDD" is stored as "\"AABBCCDD\"".
spoollink decodes these on read and re-encodes on write.
card_uids Custom FieldNFC tag UIDs are stored in a Spoolman custom field named card_uids on the spool entity.
{
"key": "card_uids",
"name": "Card UIDs",
"entity_type": "spool",
"field_type": "text",
"order": 1,
"default_value": "\"\""
}
The extra.card_uids value is a JSON-encoded string — the string value itself is
wrapped in JSON quotes by the client before sending, so it arrives as a JSON string
containing another JSON string:
extra.card_uids = "\"AABBCCDD,11223344\""
When decoded, the inner string is a comma-separated list of uppercase hex UIDs:
AABBCCDD,11223344
Before writing, the comma-separated UID string must be JSON-encoded:
jsonEncode("AABBCCDD,11223344") → "\"AABBCCDD,11223344\""
On read, strip the outer JSON quotes if present; handle both encoded and raw forms:
raw = "\"AABBCCDD,11223344\""
decoded = AABBCCDD,11223344
uids = ["AABBCCDD", "11223344"]
card_uids{
"extra": {
"card_uids": "\"AABBCCDD,11223344\""
}
}
NFC tag UIDs are formatted as uppercase hex with no separators:
AABBCCDD (4-byte UID)
04A1B2C3D4E5F6 (7-byte UID)
When an NFC tag is scanned or assigned to a spool:
GET api/v1/spool/{id}.extra.card_uids if not already present.PATCH api/v1/spool/{id}.limit=1000&allow_archived=true) and filtering client-side on card_uids.card_uids and write back via PATCH.variant Custom Field (Filament)The filament variant (e.g. “Silk”, “Matte”) is stored in a Spoolman custom field named
variant on the filament entity.
{
"key": "variant",
"name": "Variant",
"entity_type": "filament",
"field_type": "text",
"order": 1,
"default_value": "\"\""
}
The value follows the same JSON-encoded string convention as card_uids:
extra.variant = "\"Silk\""
{
"name": "Galaxy Black Silk",
"material": "PLA",
"extra": {
"variant": "\"Silk\""
}
}
spoollink Component Flowspoollink is a Moonraker component (moonraker/components/spoollink.py), loaded when a
[spoollink] section is present in the Moonraker config. It runs in Moonraker’s event loop
and uses the built-in http_client, klippy_apis, and spoolman components directly, so
it does not maintain its own WebSocket connection.
spoollink calls server.register_remote_method("spoollink_resolve_spool", ...);
Moonraker re-registers it with Klipper on every Klippy ready, so the binding survives
Klipper restarts.component_init), spoollink calls GET api/v1/field/spool and
GET api/v1/field/filament to verify the card_uids and variant custom fields exist,
creating them via POST api/v1/field/{entity}/{key} if missing.spoollink_resolve_spool with channel, spool_id, and/or card_uid.spoollink resolves the spool from Spoolman:
GET api/v1/spool/{id}GET api/v1/spool?limit=1000, then filter client-side
on extra.card_uids (comma-separated, JSON-encoded uppercase hex UIDs).spool_id and card_uid are given and the card is not yet in the spool’s
card_uids, spoollink appends it via PATCH api/v1/spool/{id} with
{"extra": {"card_uids": "\"UID1,UID2\""}} (JSON-encoded string, as required by
Spoolman’s custom field API). Any other spool that already carries the same UID has it
removed via a subsequent PATCH — a UID can only belong to one spool at a time.spoollink pushes the resolved filament info into Klipper by calling the
spoollink/set endpoint (registered by the Klipper [spoollink] router), which merges
it onto filament_protocol.FILAMENT_INFO_STRUCT and applies it to print_task_config.force_generic_vendor is enabled, non-Snapmaker filament metadata
sent to Klipper uses Generic as the vendor and clears the variant. The resolved
Spoolman object, spool ID, card UID, cache data, active spool tracking, and usage
reporting remain unchanged.print_task_config and notifies subscribers.
AFC_lane.get_status() surfaces spool_id to Fluidd/Mainsail.