I have an API which issues a series of charsetAttr commands. Params.dice_pool is an array of attribute value pairs, character_id is worked out earlier in the code. The code does for (key of Object.keys(params.dice_pool)) { sendChat('API', "!setattr --charid "+ character_id + " --" + key + "_show|inactive"); } This generates well formed !setattr commands and all the relevant attributes are set to inactive. However there is a sheet worker which is supposed to react to this change. on('change: <a list of all the attributes that the API above can set>',(event)=>{ console.log('fired event'); var mod_name = event.sourceAttribute.split("_") if (event.newValue ==='inactive') { let attr_to_set = {}; attr_to_set[mod_name[0]] = '0'; setAttrs(attr_to_set); } }); This is supposed to un-check a checkbox on the sheet with a related name and do some other things which aren't relevant. I've checked " Trigger sheet workers when setting attributes:" in charsetAttr. The sheet worker operates normally when the attribute is changed by hand. When the API changes the value it doesn't fire at all ("event fired" isn't written to the console). Am I missing some secret sauce to get this to fire? I came up with this pattern because trying to set the checkbox attribute directly to 0 from the API with sendChat('API', "!setattr --charid "+ character_id + " --" + key + "|0"); gave an error