       send: [pattern, send].join('.')
       receive: [pattern, receive].join('.')
 
-    sendRequest = @sendRequest
     @_patterns = patterns
     @_statuses = statuses
+
+  setOptions: (options) =>
+    previousOptions = @getOptions?() or {}
+    options = _.merge({}, API_DEFAULTS, previousOptions, options)
+
+    @getOptions = -> options
+
+  # send can now be used separately without initializing routes
+  send: (requestConfig, routeOptions, args...) ->
+    return if @records.isPending(requestConfig)
+
+    requestInfo = _.pick(routeOptions, 'subject', 'topic', 'action')
+    requestInfo = guessInfoFromConfig(requestConfig) if _.isEmpty(requestInfo)
+
+    requestConfig.events =
+      success: interpolate(@_patterns.receive, _.merge({status: @_statuses.success}, requestInfo))
+      failure: interpolate(@_patterns.receive, _.merge({status: @_statuses.failure}, requestInfo))
+
+    requestDelay = routeOptions.delay or @getOptions().request.delay
+
+    _.delay =>
+      {handlers} = @getOptions()
+      {onSuccess, onFail} = routeOptions
+
+      onSuccess ?= DEFAULT_SUCCESS
+      onFail ?= DEFAULT_FAIL
+
+      @_xhr.request(requestConfig)
+        # if onFail doesn't Promise.reject anything, then the default fail will not fire.
+        .then(_.partial(onSuccess, _, args...), _.partial(onFail, _, args...))
+        .then(_.partial(handlers.onSuccess, _, args...), _.partial(handlers.onFail, _, args...))
+
+    , requestDelay
+
+
+class APIHandler extends APIHandlerBase
+  constructor: (options, routes, channel) ->
+    super(options, channel)
+
+    @initializeRoutes(routes)
+    @setUpReceivers(@getOptions().events)
+    @initializeEvents(@getOptions().events, routes.length, channel)
+
+  initializeRoutes: (routes) =>
+    @routes = new Routes(routes)
+
+  setUpReceivers: (events) =>
+    sendRequest = @sendRequest
+    patterns = @_patterns
 
     handleSend = (args...) ->
       requestInfo = extractValues(@event, patterns.send)


    @send(requestConfig, routeOptions, args...)

  # send can now be used separately without initializing routes
  send: (requestConfig, routeOptions, args...) ->
    return if @records.isPending(requestConfig)

    requestInfo = _.pick(routeOptions, 'subject', 'topic', 'action')
    requestInfo = guessInfoFromConfig(requestConfig) if _.isEmpty(requestInfo)

    requestConfig.events =
      success: interpolate(@_patterns.receive, _.merge({status: @_statuses.success}, requestInfo))
      failure: interpolate(@_patterns.receive, _.merge({status: @_statuses.failure}, requestInfo))

    requestDelay = routeOptions.delay or @getOptions().request.delay

    _.delay =>
      {handlers} = @getOptions()
      {onSuccess, onFail} = routeOptions

      onSuccess ?= DEFAULT_SUCCESS
      onFail ?= DEFAULT_FAIL

      @_xhr.request(requestConfig)
        # if onFail doesn't Promise.reject anything, then the default fail will not fire.
        .then(_.partial(onSuccess, _, args...), _.partial(onFail, _, args...))
        .then(_.partial(handlers.onSuccess, _, args...), _.partial(handlers.onFail, _, args...))

    , requestDelay

# include and export cascading error handler for convenience/custom error handling.

module.exports = {APIHandler}


  initializeRecords: =>
    @records = new XHRRecords()

  initializeXHR: (xhrOptions, interceptors, isLocal) =>
    xhr = axios.create(xhrOptions)
