docs: function addApi(emitter, opts) {
  	if (!opts) opts = {}
  	var result
  
  	if (isEndApi) result = arguments.callee.name + ' invoked after endApi'
  	else if (!(emitter instanceof events.EventEmitter)) result = 'Bad emitter'
  	else if (typeof emitter.id != 'string' || !emitter.id) result = 'Emitter id property (api name) not string or blank'
  	else {
  		if (apiMap[emitter.id]) result = 'Duplicate api: ' + emitter.id
  		else {
  			result = apiMap[emitter.id] = {api: emitter.id, emitter: emitter}
  			if (opts.ready === true ||
  				opts.ready === null ||
  				typeof opts.ready === 'number') { // singleton ready
  				emitter.once('ready', onReady)
  				var timeout
  				if (typeof opts.ready === 'number' && opts.ready > 0) timeout = opts.ready
  				var timer = rqs.addRq(result.api, timeout)
  			} else result.isReady = true
  
  			result.instanceReady = opts.ready === undefined ||
  				opts.ready === true
  
  			if (opts && findFn('saveApi') && findFn('endApi') && findFn('apiState')) ;
  		}
  	}
  
  	return result
  
  	function findFn(fName) {
  		if (opts[fName])
  			if (typeof opts[fName] == 'function')
  				result[fName] = opts[fName]
  			else result = fName + ' must be function'
  		return typeof result != 'string'
  	}
  
  	function onReady(err) {
  		timer.clear()
  		var args = Array.prototype.slice.call(arguments)
  		var api = getApi(this, args)
  		var err
  
  		if (api) {
  			if (!api.isReady) {
  				api.isReady = err || true
  				if (!(err instanceof Error)) { // we have an new api becoming ready
  					if (apiReadyWait.length) checkApisReady()
  				} else err = new Error('onReady with error for api: ' + api.api)
  			} else  err = new Error('Multiple onReady for api: ' + api.api)
  		}
  		if (err) apierror.emitError(err, {args: args, emitter: this})
  	}
  }