Well, yes. it's doable but I wouldn't recommend it. But Composer is doing this. You can figure out how to do this by watching your network traffic when hitting the SAVE button on a Thing/ThingTemplate/ThingShape...whatever.
So you could use PutJSON to localhost/Thingworx/ENTITYTYPE/ENTITYNAME....
A better option and the one I would take would be to RemovePropertyDefinition and then AddPropertyDefinition. I think, due to the way that ThWx holds data in memory, that any values on live things will be there as long as you do it quickly. If you take 1 day or a server reboot between the Remove and the Add, then the data will be lost. This appears to be true in my past trials, but I don't know if it will be true forever. Also. it appears that AddPropewrtyDefinition does not take a Units parameter. So that's a dead end. Bummer.
It would be nice if ThWx could provide us a service EdiPropertyDefinition() but so far we don't have it.
I'm not sure what you mean by API, but from Java you can do it like this:
Thing thing = ...;
ThingManager.getInstance().updateEntity(thing, "Changed units to kg", true);
The PutJSON works, its a little quirky, but for anyone else trying this out the easiest method is:
GetJSON //call this first to get the JSON in correct format, I tried some others (ReadEntityAsJSON) that gave me trouble
Edit your JSON values
Update 'lastModifiedDate' (usually resides in your JSON at yourObject.lastModifiedDate)
Just as a reference, the Delete and quick Re-AddPropertyDefinition does appear to preserve live thing values of that property. I'm doing that elsewhere, and if AddPropertyDefinition had a units parameter I would use it there. Certainly easier and less dangerous than the JSON manipulation. I put in a request to have units added to that service though.
As a further update here for anyone trying this, especially when trying to set units or other property metadata, the URL I'm setting in the PutJSON is formatted as such:
However, as expected, if the entity is open for edit in composer, the units will not be set. Annoyingly, the call will return a "200 ok" http response no matter what the actual outcome was. To force the update of the aspects append '&forceUpdate=1' to the end of the URL.
Of course there are reasons you may not want to force update, but in my situation it seems fine for now. Just thought I'd share.