diff --git a/aiogremlin/client.py b/aiogremlin/client.py
index 93a0d5800442ba85e872b448d73f4073aaaf694f..9f8d2e18ba48927e3bd58e5d7e400e1f4943187e 100644
--- a/aiogremlin/client.py
+++ b/aiogremlin/client.py
@@ -7,119 +7,72 @@ import aiohttp
 
 from aiogremlin.response import GremlinClientWebSocketResponse
 from aiogremlin.exceptions import RequestError
-from aiogremlin.log import logger, INFO
 from aiogremlin.connector import GremlinConnector
 from aiogremlin.subprotocol import gremlin_response_parser, GremlinWriter
 
-__all__ = ("submit", "SimpleGremlinClient", "GremlinClient",
-           "GremlinClientSession")
+__all__ = ("submit", "GremlinClient", "GremlinClientSession",
+           "GremlinResponse", "GremlinResponseStream")
 
 
-class BaseGremlinClient:
+class GremlinClient:
+    """Main interface for interacting with the Gremlin Server.
 
-    def __init__(self, *, lang="gremlin-groovy", op="eval", processor="",
-                 loop=None, verbose=False):
+    :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
+        by default
+    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
+        `asyncio.get_event_loop` is used for getting default event loop
+        (optional)
+    :param str lang: Language of scripts submitted to the server.
+        "gremlin-groovy" by default
+    :param str op: Gremlin Server op argument. "eval" by default.
+    :param str processor: Gremlin Server processor argument. "" by default.
+    :param float timeout: timeout for establishing connection (optional).
+        Values ``0`` or ``None`` mean no timeout
+    :param connector: A class that implements the method ``ws_connect``.
+        Usually an instance of ``aiogremlin.connector.GremlinConnector``
+    """
+
+    def __init__(self, *, url='ws://localhost:8182/', loop=None,
+                 lang="gremlin-groovy", op="eval", processor="",
+                 timeout=None, ws_connector=None):
+        """
+        """
         self._lang = lang
         self._op = op
         self._processor = processor
         self._loop = loop or asyncio.get_event_loop()
         self._closed = False
-        if verbose:
-            logger.setLevel(INFO)
+        self._session = None
+        self._url = url
+        self._timeout = timeout
+        if ws_connector is None:
+            ws_connector = GremlinConnector(loop=self._loop)
+        self._connector = ws_connector
 
     @property
     def loop(self):
+        """Readonly property that returns event loop used by client"""
         return self._loop
 
     @property
     def op(self):
+        """Readonly property that returns op argument for Gremlin Server"""
         return self._op
 
     @property
     def processor(self):
+        """Readonly property. The processor argument for Gremlin
+        Server"""
         return self._processor
 
     @property
     def lang(self):
+        """Readonly property. The language used for Gremlin scripts"""
         return self._lang
 
-    def submit(self):
-        raise NotImplementedError
-
-    @asyncio.coroutine
-    def execute(self, gremlin, *, bindings=None, lang=None,
-                op=None, processor=None, binary=True):
-        """
-        """
-        lang = lang or self.lang
-        op = op or self.op
-        processor = processor or self.processor
-        resp = yield from self.submit(gremlin, bindings=bindings, lang=lang,
-                                      op=op, processor=processor,
-                                      binary=binary)
-
-        return (yield from resp.get())
-
-
-class SimpleGremlinClient(BaseGremlinClient):
-
-    def __init__(self, connection, *, lang="gremlin-groovy", op="eval",
-                 processor="", loop=None, verbose=False):
-        """This class is primarily designed to be used in the context
-        `manager"""
-        super().__init__(lang=lang, op=op, processor=processor, loop=loop,
-                         verbose=verbose)
-        self._connection = connection
-
-    @asyncio.coroutine
-    def close(self):
-        if self._closed:
-            return
-        self._closed = True
-        try:
-            yield from self._connection.release()
-        finally:
-            self._connection = None
-
-    @property
-    def closed(self):
-        return (self._closed or self._connection.closed or
-                self._connection is None)
-
-    @asyncio.coroutine
-    def submit(self, gremlin, *, bindings=None, lang="gremlin-groovy",
-               op="eval", processor="", session=None, binary=True):
-        """
-        """
-        writer = GremlinWriter(self._connection)
-
-        connection = writer.write(gremlin, bindings=bindings, lang=lang, op=op,
-                                  processor=processor, session=session,
-                                  binary=binary)
-
-        return GremlinResponse(self._connection,
-                               session=session,
-                               loop=self._loop)
-
-
-class GremlinClient(BaseGremlinClient):
-
-    def __init__(self, *, url='ws://localhost:8182/', loop=None,
-                 protocols=None, lang="gremlin-groovy", op="eval",
-                 processor="", timeout=None, verbose=False, connector=None):
-        """
-        """
-        super().__init__(lang=lang, op=op, processor=processor, loop=loop,
-                         verbose=verbose)
-        self._url = url
-        self._timeout = timeout
-        self._session = None
-        if connector is None:
-            connector = GremlinConnector(loop=self._loop)
-        self._connector = connector
-
     @property
     def url(self):
+        """Getter/setter for database url used by the client"""
         return self._url
 
     @url.setter
@@ -128,10 +81,13 @@ class GremlinClient(BaseGremlinClient):
 
     @property
     def closed(self):
+        """Readonly property. Return True if client has been closed"""
         return self._closed or self._connector is None
 
     @asyncio.coroutine
     def close(self):
+        """Close client. If client has not been detached from underlying
+        ws_connector, this coroutinemethod closes the latter as well."""
         if self._closed:
             return
         self._closed = True
@@ -141,40 +97,72 @@ class GremlinClient(BaseGremlinClient):
             self._connector = None
 
     def detach(self):
+        """Detach client from ws_connector. Client status is now closed"""
         self._connector = None
 
     @asyncio.coroutine
     def submit(self, gremlin, *, bindings=None, lang=None,
-               op=None, processor=None, binary=True):
+               op=None, processor=None, binary=True, session=None,
+               timeout=None):
         """
         """
         lang = lang or self.lang
         op = op or self.op
         processor = processor or self.processor
+        if session is None:
+            session = self._session
+        if timeout is None:
+            timeout = self._timeout
 
         ws = yield from self._connector.ws_connect(
-            self.url, timeout=self._timeout)
+            self.url, timeout=timeout)
 
         writer = GremlinWriter(ws)
 
         ws = writer.write(gremlin, bindings=bindings, lang=lang, op=op,
                           processor=processor, binary=binary,
-                          session=self._session)
+                          session=session)
+
+        return GremlinResponse(ws, session=session, loop=self._loop)
+
+    @asyncio.coroutine
+    def execute(self, gremlin, *, bindings=None, lang=None, session=None,
+                op=None, processor=None, binary=True, timeout=None):
+        """
+        """
+        lang = lang or self.lang
+        op = op or self.op
+        processor = processor or self.processor
+        resp = yield from self.submit(gremlin, bindings=bindings, lang=lang,
+                                      op=op, processor=processor,
+                                      binary=binary, session=session,
+                                      timeout=timeout)
 
-        return GremlinResponse(ws, session=self._session, loop=self._loop)
+        return (yield from resp.get())
 
 
 class GremlinClientSession(GremlinClient):
+    """Interface for interacting with the Gremlin Server using sessions.
+
+    :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
+        by default
+    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
+        `asyncio.get_event_loop` is used for getting default event loop
+        (optional)
+    :param str lang: Language of scripts submitted to the server.
+        "gremlin-groovy" by default
+    :param str op: Gremlin Server op argument. "eval" by default.
+    :param str processor: Gremlin Server processor argument. "" by default.
+    :param float timeout: timeout for establishing connection (optional).
+        Values ``0`` or ``None`` mean no timeout
+    """
 
     def __init__(self, *, url='ws://localhost:8182/', loop=None,
-                 protocols=None, lang="gremlin-groovy", op="eval",
-                 processor="session", session=None, timeout=None,
-                 verbose=False, connector=None):
-        """
-        """
-        super().__init__(url=url, protocols=protocols, lang=lang, op=op,
-                         processor=processor, loop=loop, timeout=timeout,
-                         verbose=verbose, connector=connector)
+                 lang="gremlin-groovy", op="eval", processor="session",
+                 session=None, timeout=None,
+                 ws_connector=None):
+        super().__init__(url=url, lang=lang, op=op, processor=processor,
+                         loop=loop, timeout=timeout, ws_connector=ws_connector)
 
         if session is None:
             session = str(uuid.uuid4())
@@ -196,7 +184,16 @@ class GremlinClientSession(GremlinClient):
 
 
 class GremlinResponse:
-
+    """Main interface for reading Gremlin Server responses. Typically returned
+    by ``GremlinClient.submit``, not created by user.
+
+    :param ``aiogremlin.response.GremlinClientWebSocketResponse`` ws: Websocket
+        connection.
+    :param str session: Session id (optional). Typically a uuid
+    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
+        `asyncio.get_event_loop` is used for getting default event loop
+        (optional)
+    """
     def __init__(self, ws, *, session=None, loop=None):
         self._loop = loop or asyncio.get_event_loop()
         self._session = session
@@ -228,7 +225,16 @@ class GremlinResponse:
 
 
 class GremlinResponseStream:
-
+    """
+    Encapsulate and read Gremlin Server responses. Typically instantiated by
+    GremlinResponse constructor, not by user.
+
+    :param ``aiogremlin.response.GremlinClientWebSocketResponse`` ws: Websocket
+        connection.
+    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
+        `asyncio.get_event_loop` is used for getting default event loop
+        (optional)
+    """
     def __init__(self, ws, loop=None):
         self._ws = ws
         self._loop = loop or asyncio.get_event_loop()
@@ -238,6 +244,7 @@ class GremlinResponseStream:
 
     @asyncio.coroutine
     def read(self):
+        """Read a message from the stream"""
         if self._stream.at_eof():
             yield from self._ws.release()
             message = None
@@ -258,8 +265,24 @@ def submit(gremlin, *,
            lang="gremlin-groovy",
            op="eval",
            processor="",
-           connector=None,
+           timeout=None,
+           session=None,
            loop=None):
+    """Submit a script to the Gremlin Server.
+
+    :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
+        by default
+    :param str lang: Language of scripts submitted to the server.
+        "gremlin-groovy" by default
+    :param str op: Gremlin Server op argument. "eval" by default.
+    :param str processor: Gremlin Server processor argument. "" by default.
+    :param float timeout: timeout for establishing connection (optional).
+        Values ``0`` or ``None`` mean no timeout
+    :param str session: Session id (optional). Typically a uuid
+    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
+        `asyncio.get_event_loop` is used for getting default event loop
+        (optional)
+    """
 
     if loop is None:
         loop = asyncio.get_event_loop()
@@ -271,11 +294,12 @@ def submit(gremlin, *,
         ws_response_class=GremlinClientWebSocketResponse)
 
     gremlin_client = GremlinClient(url=url, loop=loop,
-                                   connector=client_session)
+                                   ws_connector=client_session)
 
     try:
         resp = yield from gremlin_client.submit(
-            gremlin, bindings=bindings, lang=lang, op=op, processor=processor)
+            gremlin, bindings=bindings, lang=lang, op=op, processor=processor,
+            session=session, timeout=timeout)
 
         return resp
 
diff --git a/aiogremlin/connector.py b/aiogremlin/connector.py
index e623e4865f81a675ec895f17f4a10f7ed0418b9e..5c9fa791e5bca98d71851c18b0f5364cf55af70b 100644
--- a/aiogremlin/connector.py
+++ b/aiogremlin/connector.py
@@ -1,62 +1,33 @@
-import asyncio
+"""Websocket connection factory and manager."""
 
-from contextlib import contextmanager
+import asyncio
 
 from aiowebsocketclient import WebSocketConnector
 
 from aiogremlin.response import GremlinClientWebSocketResponse
-from aiogremlin.contextmanager import ConnectionContextManager
-from aiogremlin.log import logger
 
 __all__ = ("GremlinConnector",)
 
 
 class GremlinConnector(WebSocketConnector):
-
+    """Create and manage reusable websocket connections. Out of the box
+    support for multiple enpoints (databases).
+
+    :param float conn_timeout: timeout for establishing connection (optional).
+        Values ``0`` or ``None`` mean no timeout
+    :param bool force_close: close websockets after release
+    :param int limit: limit for total open websocket connections
+    :param aiohttp.client.ClientSession client_session: Underlying HTTP
+        session used to establish websocket connections
+    :param loop: `event loop` If param is ``None``, `asyncio.get_event_loop`
+        is used for getting default event loop (optional)
+    :param ws_response_class: WebSocketResponse class implementation.
+        ``ClientWebSocketResponse`` by default
+    :param bool verbose: Set log level to info. False by default
+    """
     def __init__(self, *, conn_timeout=None, force_close=False, limit=1024,
-                 client_session=None, loop=None):
-        """
-        :param float conn_timeout: timeout for establishing connection
-                                   (optional). Values ``0`` or ``None``
-                                   mean no timeout
-        :param bool force_close: close underlying sockets after
-                                 releasing connection
-        :param int limit: limit for total open websocket connections
-        :param aiohttp.client.ClientSession client_session: Underlying HTTP
-                                                            session used to
-                                                            to establish
-                                                            websocket
-                                                            connections
-        :param loop: `event loop`
-                     used for processing HTTP requests.
-                     If param is ``None``, `asyncio.get_event_loop`
-                     is used for getting default event loop.
-                     (optional)
-        :param ws_response_class: WebSocketResponse class implementation.
-                                  ``ClientWebSocketResponse`` by default
-        """
+                 client_session=None, loop=None, verbose=False):
+
         super().__init__(conn_timeout=conn_timeout, force_close=force_close,
                          limit=limit, client_session=client_session, loop=loop,
                          ws_response_class=GremlinClientWebSocketResponse)
-
-    @contextmanager
-    @asyncio.coroutine
-    def connection(self, url, *,
-                   protocols=(),
-                   timeout=10.0,
-                   autoclose=True,
-                   autoping=True):
-        ws = yield from self.ws_connect(url='ws://localhost:8182/')
-        return ConnectionContextManager(ws)
-
-    # aioredis style
-    def __enter__(self):
-        raise RuntimeError(
-            "'yield from' should be used as a context manager expression")
-
-    def __exit__(self, *args):
-        pass
-
-    def __iter__(self):
-        ws = yield from self.ws_connect(url='ws://localhost:8182/')
-        return ConnectionContextManager(ws)
diff --git a/aiogremlin/contextmanager.py b/aiogremlin/contextmanager.py
deleted file mode 100644
index 6216ba43b0c1c1fc4c0b4e4cf53aadde6cdf9b65..0000000000000000000000000000000000000000
--- a/aiogremlin/contextmanager.py
+++ /dev/null
@@ -1,19 +0,0 @@
-class ConnectionContextManager:
-
-    __slots__ = ("_ws")
-
-    def __init__(self, ws):
-        self._ws = ws
-
-    def __enter__(self):
-        if self._ws.closed:
-            raise RuntimeError("Connection closed unexpectedly.")
-        return self._ws
-
-    def __exit__(self, exception_type, exception_value, traceback):
-        try:
-            self._ws._close_code = 1000
-            self._ws._closing = True
-            self._ws._do_close()
-        finally:
-            self._ws = None
diff --git a/aiogremlin/exceptions.py b/aiogremlin/exceptions.py
index 285e83d3b441f96a631bf7c794d7ba6c7157ca96..c131e1733c09f805199c477341bad439f4932da1 100644
--- a/aiogremlin/exceptions.py
+++ b/aiogremlin/exceptions.py
@@ -1,19 +1,12 @@
-"""
-Gremlin Server exceptions.
-"""
+"""Gremlin Server exceptions."""
 
-__all__ = ("RequestError", "GremlinServerError", "SocketClientError")
-
-
-class SocketClientError(IOError):
-    pass
+__all__ = ("RequestError", "GremlinServerError")
 
 
 class StatusException(IOError):
 
     def __init__(self, value, result):
         """Handle all exceptions returned from the Gremlin Server as per:
-        https://github.com/apache/incubator-tinkerpop/blob/ddd0b36bed9a2b1ce5b335b1753d881f0614a6c4/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java
         """
         self.value = value
         self.response = {
diff --git a/aiogremlin/log.py b/aiogremlin/log.py
deleted file mode 100644
index 4db936717f07bd9ca79df9b8e1054f3906a44d7d..0000000000000000000000000000000000000000
--- a/aiogremlin/log.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import logging
-
-
-INFO = logging.INFO
-
-
-logging.basicConfig(
-    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
-
-
-logger = logging.getLogger("aiogremlin")
diff --git a/aiogremlin/response.py b/aiogremlin/response.py
index b22e0e766d11ad34f9c0198ca3647d7e48761b13..a5170e02fa381d2b83760846176d06e3ad245d40 100644
--- a/aiogremlin/response.py
+++ b/aiogremlin/response.py
@@ -1,5 +1,7 @@
 """
+Class used to pass messages with the Gremlin Server.
 """
+
 import asyncio
 import base64
 import hashlib
@@ -8,8 +10,6 @@ import os
 import aiohttp
 
 from aiowebsocketclient.connector import ClientWebSocketResponse
-from aiogremlin.exceptions import SocketClientError
-from aiogremlin.log import INFO, logger
 
 __all__ = ('GremlinClientWebSocketResponse',)
 
diff --git a/docs/aiogremlin.rst b/docs/aiogremlin.rst
index 9e900446a46e450fade6c07d1b843198e1f87850..1a87eb4318adf5e41ee598f8b9c45b69db3a041b 100644
--- a/docs/aiogremlin.rst
+++ b/docs/aiogremlin.rst
@@ -1,5 +1,15 @@
-API
-===
+.. _aiogremlin-client-reference:
+
+Client Reference
+================
+
+aiogremlin package
+-------------------------
+
+.. automodule:: aiogremlin
+    :members:
+    :undoc-members:
+    :show-inheritance:
 
 aiogremlin.client module
 ------------------------
@@ -16,14 +26,7 @@ aiogremlin.connector module
     :members:
     :undoc-members:
     :show-inheritance:
-
-aiogremlin.contextmanager module
---------------------------------
-
-.. automodule:: aiogremlin.contextmanager
-    :members:
-    :undoc-members:
-    :show-inheritance:
+    :inherited-members:
 
 aiogremlin.exceptions module
 ----------------------------
@@ -33,14 +36,6 @@ aiogremlin.exceptions module
     :undoc-members:
     :show-inheritance:
 
-aiogremlin.log module
----------------------
-
-.. automodule:: aiogremlin.log
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
 aiogremlin.response module
 --------------------------
 
@@ -48,6 +43,7 @@ aiogremlin.response module
     :members:
     :undoc-members:
     :show-inheritance:
+    :inherited-members:
 
 aiogremlin.subprotocol module
 -----------------------------
diff --git a/docs/conf.py b/docs/conf.py
index af3e9c04396d3ea5ed0e7ac867a837b877f7bb80..30a471d45b9915b0512b3e108027e76333077adc 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,6 +13,7 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
+import alabaster
 import sys
 import os
 import shlex
@@ -33,6 +34,8 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
 extensions = [
     'sphinx.ext.autodoc',
     'sphinx.ext.viewcode',
+    'sphinx.ext.intersphinx',
+    'alabaster'
 ]
 
 # Add any paths that contain templates here, relative to this directory.
@@ -117,10 +120,18 @@ html_theme = 'alabaster'
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+html_theme_options = {
+    # 'logo': 'logo.png',
+    'description': 'Async client for the TP3 Gremlin Server',
+    'logo_text_align': 'left',
+    'github_user': 'davebshow',
+    'github_repo': 'aiogremlin',
+    'github_button': True,
+    'github_banner': True
+}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+html_theme_path = [alabaster.get_path()]
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
@@ -157,7 +168,11 @@ html_static_path = ['_static']
 #html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+html_sidebars = {
+    '**': [
+        'about.html', 'navigation.html', 'searchbox.html', 'donate.html',
+    ]
+}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
@@ -286,3 +301,6 @@ texinfo_documents = [
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
 #texinfo_no_detailmenu = False
+intersphinx_mapping = {
+    'python': ('https://docs.python.org/3.4', None),
+    'aiohttp': ('http://aiohttp.readthedocs.org/en/stable/', None)}
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
deleted file mode 100644
index 3ce1d78a117c4c8b1b614c6109375044d1f88568..0000000000000000000000000000000000000000
--- a/docs/getting_started.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Getting Started
-===============
diff --git a/docs/index.rst b/docs/index.rst
index ac9c9f6c1778e650cc459258ce7f4a6d63ac5fb9..d714c5f01c8afad02e0083e448ee34cb86c1264b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,15 +3,83 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to aiogremlin's documentation!
-======================================
+==========
+aiogremlin
+==========
+
+:py:mod:`aiogremlin` is an asynchronous client for the `Tinkerpop 3 Gremlin Server`_
+based on the `asyncio`_ and `aiohttp`_ libraries.
+
+Releases
+========
+The latest release of ``aiogremlin`` is **0.0.10**.
+
+
+Requirements
+============
+
+- Python 3.4
+- Tinkerpop 3 Gremlin Server 3.0.0.M9
+
+
+Dependencies
+============
+- aiohttp 0.16.5
+- aiowebsocketclient 0.0.3
+
+To speed up serialization, you can also install `ujson`_. If not available,
+aiogremlin will use the Python standard library :any:`json<json>` module.
+
+- ujson 1.33
+
+
+Installation
+============
+Install using pip::
+
+    $ pip install aiogremlin
+
+
+Getting Started
+===============
+
+:py:mod:`aiogremlin` has a simple API that is quite easy to use. However, as it relies
+heavily on `asyncio`_ and `aiohttp`_, it is helpful to be familar with the
+basics of these modules. If you're not, maybe check out the :py:mod:`asyncio`
+documentation relating to the :ref:`event loop<asyncio-event-loop>` and the
+concept of the :ref:`coroutine<coroutine>`. Also, I would recommend the
+documentation relating to :py:mod:`aiohttp`'s
+:ref:`websocket client<aiohttp-client-websockets>` and
+:ref:`HTTP client<aiohttp-client-reference>` implementations.
+
+Minimal Example
+---------------
+Submit a script to the Gremlin Server::
+
+    >>> import asyncio
+    >>> import aiogremlin
+    >>> @asyncio.coroutine
+    ... def go():
+    ...     resp = yield from aiogremlin.submit("1 + 1")
+    ...     return (yield from resp.get())
+    >>> loop = asyncio.get_event_loop()
+    >>> results = loop.run_until_complete(go())
+    >>> results
+    [Message(status_code=200, data=[2], message={}, metadata='')]
+
+
+The above example demonstrates how ``aiogremlin`` uses the
+:ref:`event loop<asyncio-event-loop>` to drive communication with the Gremlin
+Server, but the **rest of examples are written as if they were run in a Python
+interpreter**. In reality, **this isn't possible**, so remember, code *must*
+be wrapped in functions and run with the :ref:`event loop<asyncio-event-loop>`.
 
 Contents:
 
 .. toctree::
    :maxdepth: 3
 
-   getting_started
+   usage
    modules
 
 
@@ -21,3 +89,8 @@ Indices and tables
 * :ref:`genindex`
 * :ref:`modindex`
 * :ref:`search`
+
+.. _Tinkerpop 3 Gremlin Server: http://tinkerpop.incubator.apache.org/
+.. _`asyncio`: https://docs.python.org/3/library/asyncio.html
+.. _`aiohttp`: http://aiohttp.readthedocs.org/en/latest/
+.. _`ujson`: https://pypi.python.org/pypi/ujson
diff --git a/docs/modules.rst b/docs/modules.rst
index 0785e374b8938585dbc33b96757d6868799a1e7c..ef0aa53dcfaa1d1db9bd7f1d0fb48b5f272ec968 100644
--- a/docs/modules.rst
+++ b/docs/modules.rst
@@ -1,8 +1,7 @@
-aiogremlin
-==========
+API
+===
 
 .. toctree::
-   :maxdepth: 4
+   :maxdepth: 2
 
-   usage
    aiogremlin
diff --git a/docs/usage.rst b/docs/usage.rst
index b2c0348973387f9fd33643056231fd4be3e6be2e..e4f0c5c9182b135cc2ca41daee3aef83ecf7ecce 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -1,2 +1,197 @@
 Using aiogremlin
 ================
+
+Before you get started, make sure you have the `Gremlin Server`_ up and running.
+All of the following example assume a running Gremlin Server version 3.0.0.M9 at
+'ws://localhost:8182/'.
+
+
+Submitting a script with :py:func:`submit`
+------------------------------------------
+
+
+The simplest way to interact with the Gremlin Server is by using the
+:py:func:`aiogremlin.client.submit` function::
+
+    >>> resp = yield from aiogremlin.submit("x + x", bindings={"x": 2})
+
+This returns an instance of :py:class:`aiogremlin.client.GremlinResponse`. This
+class provides the interface used to read the underlying response stream. The
+easiest way to read the stream is using the
+:py:meth:`aiogremlin.client.GremlinResponse.get`::
+
+    >>> results = yield from resp.get()
+
+However, if you are expecting a huge result set from the server, you may want to
+read the chunked responses one at a time::
+
+    >>> results = []
+    >>> while True:
+    ...     msg = yield from resp.stream.read():
+    ...     if msg is None:
+    ...         break
+    ...     results.append(msg)
+
+
+.. function:: submit(gremlin, *, url='ws://localhost:8182/', bindings=None,
+                     lang="gremlin-groovy", op="eval", processor="",
+                     timeout=None, session=None, loop=None):
+
+    Submit a script to the Gremlin Server.
+
+    :param str gremlin: Gremlin script to submit to server.
+
+    :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
+        by default
+
+    :param dict bindings: A mapping of bindings for Gremlin script.
+
+    :param str lang: Language of scripts submitted to the server.
+        "gremlin-groovy" by default
+
+    :param str op: Gremlin Server op argument. "eval" by default.
+
+    :param str processor: Gremlin Server processor argument. "" by default.
+
+    :param float timeout: timeout for establishing connection (optional).
+        Values ``0`` or ``None`` mean no timeout
+
+    :param str session: Session id (optional). Typically a uuid
+
+    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
+        `asyncio.get_event_loop` is used for getting default event loop
+        (optional)
+
+    :returns: :py:class:`aiogremlin.client.GremlinResponse` object
+
+
+Reusing sockets with :py:class:`GremlinClient`
+----------------------------------------------
+
+To avoid the overhead of repeatedly establishing websocket connections,
+``aiogremlin`` provides the class :py:class:`aiogremlin.client.GremlinClient`.
+This class uses pooling to reuse websocket connections, and facilitates
+concurrent message passing by yielding new websocket connections as needed::
+
+    >>> client = aiogremlin.GremlinClient()
+    >>> resp = client.submit("x + x", bindings={"x": 2})
+
+For convenience, :py:class:`GremlinClient` provides the method
+:py:meth:`aiogremlin.client.GremlinClient.execute`. This is equivalent of calling,
+:py:meth:`GremlinClient.submit` and then :py:meth:`GremlinResponse.get`.
+Therefore::
+
+    >>> results = client.execute("x + x", bindings={"x": 2})
+
+Is equivalent to::
+
+    >>> resp = yield from aiogremlin.submit("x + x", bindings={"x": 2})
+    >>> results = yield from resp.get()
+
+:py:class:`GremlinClient` encapsulates :py:class:`aiogremlin.connector.GremlinConnector`.
+This class produces the websocket connections used by the client, and handles all
+of the connection pooling. It can also handle pools for multiple servers. To do
+so, you can share a :py:class:`GremlinConnector` amongst various client that
+point to different endpoints::
+
+    >>> connector = aiogremlin.GremlinConnector()
+    >>> client1 = aiogremlin.GremlinClient(url=url='ws://localhost:8182/'
+    ...                                    ws_connector=connector)
+    >>> client2 = aiogremlin.GremlinClient(url=url='ws://localhost:8080/'
+    ...                                    ws_connector=connector)
+
+
+.. class:: GremlinClient(self, *, url='ws://localhost:8182/', loop=None,
+                         lang="gremlin-groovy", op="eval", processor="",
+                         timeout=None, ws_connector=None)
+
+    Main interface for interacting with the Gremlin Server.
+
+    :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
+        by default
+
+    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
+        `asyncio.get_event_loop` is used for getting default event loop
+        (optional)
+
+    :param str lang: Language of scripts submitted to the server.
+        "gremlin-groovy" by default
+
+    :param str op: Gremlin Server op argument. "eval" by default
+
+    :param str processor: Gremlin Server processor argument. "" by default
+
+    :param float timeout: timeout for establishing connection (optional).
+        Values ``0`` or ``None`` mean no timeout
+
+    :param ws_connector: A class that implements the method :py:meth:`ws_connect`.
+        Usually an instance of :py:class:`aiogremlin.connector.GremlinConnector`
+
+.. method:: close()
+
+   :ref:`coroutine<coroutine>` method.
+
+   Close client. If client has not been detached from underlying
+   ws_connector, this coroutinemethod closes the latter as well.
+
+.. method:: detach()
+
+   Detach client from ws_connector. Client status is switched to closed.
+
+.. method:: submit(gremlin, *, bindings=None, lang=None, op=None,
+                   processor=None, binary=True, session=None, timeout=None)
+
+   :param str gremlin: Gremlin script to submit to server.
+
+   :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
+                   by default
+
+   :param dict bindings: A mapping of bindings for Gremlin script.
+
+   :param str lang: Language of scripts submitted to the server.
+                    "gremlin-groovy" by default
+
+   :param str op: Gremlin Server op argument. "eval" by default.
+
+   :param str processor: Gremlin Server processor argument. "" by default.
+
+   :param float timeout: timeout for establishing connection (optional).
+                         Values ``0`` or ``None`` mean no timeout
+
+   :param str session: Session id (optional). Typically a uuid
+
+   :returns: :py:class:`aiogremlin.client.GremlinResponse` object
+
+.. method:: execute(gremlin, *, bindings=None, lang=None, op=None,
+                   processor=None, binary=True, session=None, timeout=None)
+
+   :param str gremlin: Gremlin script to submit to server.
+
+   :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
+                   by default
+
+   :param dict bindings: A mapping of bindings for Gremlin script.
+
+   :param str lang: Language of scripts submitted to the server.
+                    "gremlin-groovy" by default
+
+   :param str op: Gremlin Server op argument. "eval" by default.
+
+   :param str processor: Gremlin Server processor argument. "" by default.
+
+   :param float timeout: timeout for establishing connection (optional).
+                         Values ``0`` or ``None`` mean no timeout
+
+   :param str session: Session id (optional). Typically a uuid
+
+   :returns: :py:class:`list` of messages
+
+
+Using Gremlin Server sessions with :py:class:`GremlinClientSession`.
+
+
+
+
+
+
+.. _Gremlin Server: http://tinkerpop.incubator.apache.org/
diff --git a/tests/tests.py b/tests/tests.py
index f924506646cb6d22cafee66230f9074e4fe94d75..df6d8f8c63e8214f13140634d4a8b08821b4142e 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -5,8 +5,8 @@ import asyncio
 import unittest
 import uuid
 
-from aiogremlin import (submit, SimpleGremlinClient, GremlinConnector,
-                        GremlinClient, GremlinClientSession)
+from aiogremlin import (submit, GremlinConnector, GremlinClient,
+                        GremlinClientSession)
 
 
 class SubmitTest(unittest.TestCase):
@@ -31,43 +31,6 @@ class SubmitTest(unittest.TestCase):
         self.assertEqual(results[0].data[0], 8)
 
 
-class SimpleGremlinClientTest(unittest.TestCase):
-
-    def setUp(self):
-        self.loop = asyncio.new_event_loop()
-        asyncio.set_event_loop(None)
-        self.connector = GremlinConnector(force_close=True, loop=self.loop)
-
-    def tearDown(self):
-        self.loop.close()
-
-    def test_submit(self):
-
-        @asyncio.coroutine
-        def go():
-            ws = yield from self.connector.ws_connect('ws://localhost:8182/')
-            client = SimpleGremlinClient(ws, loop=self.loop)
-            resp = yield from client.submit("4 + 4", bindings={"x": 4})
-            results = yield from resp.get()
-            return results
-
-        results = self.loop.run_until_complete(go())
-        self.assertEqual(results[0].data[0], 8)
-
-    def test_close(self):
-
-        @asyncio.coroutine
-        def go():
-            ws = yield from self.connector.ws_connect('ws://localhost:8182/')
-            client = SimpleGremlinClient(ws, loop=self.loop)
-            yield from client.close()
-            self.assertTrue(client.closed)
-            self.assertTrue(ws.closed)
-            self.assertIsNone(client._connection)
-
-        results = self.loop.run_until_complete(go())
-
-
 class GremlinClientTest(unittest.TestCase):
 
     def setUp(self):
@@ -229,20 +192,20 @@ class ContextMngrTest(unittest.TestCase):
         self.loop.run_until_complete(self.connector.close())
         self.loop.close()
 
-    def test_connection_manager(self):
-        results = []
-
-        @asyncio.coroutine
-        def go():
-            with (yield from self.connector) as conn:
-                client = SimpleGremlinClient(conn, loop=self.loop)
-                resp = yield from client.submit("1 + 1")
-                while True:
-                    mssg = yield from resp.stream.read()
-                    if mssg is None:
-                        break
-                    results.append(mssg)
-        self.loop.run_until_complete(go())
+    # def test_connection_manager(self):
+    #     results = []
+    #
+    #     @asyncio.coroutine
+    #     def go():
+    #         with (yield from self.connector) as conn:
+    #             client = SimpleGremlinClient(conn, loop=self.loop)
+    #             resp = yield from client.submit("1 + 1")
+    #             while True:
+    #                 mssg = yield from resp.stream.read()
+    #                 if mssg is None:
+    #                     break
+    #                 results.append(mssg)
+    #     self.loop.run_until_complete(go())
 
 
 if __name__ == "__main__":