Major refactor to make public API cleaner.

The gist of this is that the API user no longer needs to manage Session objects, as it's now handled internally. As a consequence, requests are now constructed at the point of sending, and re-constructed if the session they were using is rejected.
The number of exceptions throws by public API is much smaller: callers now only need to handle IO failures and bad user credentials. There is a 3rd type of exception, but this should only occur when the API gets broken due to incompatible upstream changes.