The callback is the last argument. No matter how many arguments are passed, even if it's a variable argument API, it has to be the last one.
The callback will be called exactly once. Even if there are multiple error conditions. Wrap it using the 'once' library if you don't want to worry about it.
The first argument to the callback is null if everything succeeded, or an error if it failed. The API will NOT throw an error asynchronously (because the calling code can't catch it, and that's mean).
The second argument should be the main results, additional arguments may be passed with supplementary stuff. The 80% use case shouldn't have to know there are more arguments, when possible.
The callback will always be called asynchronously. Lest you release Zalgo .
Some of these requirements may seem silly in one case or another, but before this became a community convention it was anarchy. In the old west of the web, chaos reigned, each api would take a different number of functions passed in different ways, sometimes as objects with "error" and "success" functions as properties, sometimes as the first function. Some API's would throw uncatchable errors.
The value of the Node Style Callback isn't really that it's a nice way to create an asynchronous API (though it is pretty nice). It's that by buying in and building APIs like this, when other people use our module it just works like they expect. And we get the same out of their modules. No digging in the documentation to find out how to pass an error handler so we can figure out why this damn library is hanging forever and never calling me back.