Nah. You can't use Start/EndUndo without defining what to undo through an AddUndo. While there are a few commands that have the whole Undo sequence built in, you will normally want to define your AddUndos yourself so you are in control of the process.
Imagine it like that: Start/EndUndo define just a "container" which is added to the undo list. When the user presses "Undo", this container will try to restore the previous state by applying all its content (multiple changes) in reverse sequence. If you don't put anything into this container by calling AddUndo, well, the Undo process does not have any information on what to change back. After all, the Undo need to know what the previous state even was.
For example, if you want to delete an object, you will AddUndo(UNDOTYPE_DELETE, obj) before the deletion happens - because after the deletion, the object is gone. The AddUndo will keep a copy of the deleted object so it can later restore it. Without an AddUndo, there is no such copy and the Undo doesn't know what you deleted and what to restore.
Now, why is there such a container structure? After all, Maxon could just build an undo into every command?
Yes they could, but this would create an enormous overhead that may not be needed in all cases (for temporary objects, e.g.). Not defining an undo step explicitly through Start/EndUndo would also mean that the user would have to press Undo for every such substep, instead of pressing it once to revert the results of the whole script. If the script does three hundred object changes, the user would need to press Undo 300 times. Not very practical.
Could Maxon at least put an AddUndo into every command then, and leave only the Start/EndUndo markers in place? Yes they could, but still, you wouldn't want to burden the system with tons of Undo objects that may never be needed. So, you have to decide yourself what objects to make "undoable" and where to use just straightforward code.
In fact, undoing is one of the, eh, more interesting topics in software. If you use an undo schema as in C4D, you still have to look out for exceptions and unwanted returns, so you don't accidentally skip an EndUndo. You also may need to trigger an undo in error cases to revert to the original structure before exiting (controlled fail). And naturally you have to think about what AddUndos to actually place.
Darn, I could have sworn there was a whole chapter on Undoing in the API manual but now I can't find it. >:-(