intercom.io.js

Module dependencies.

4  var request = require('request'),
5      qs = require('qs'),
6      _ = require('lodash'),
7      debug = require('debug')('intercom.io'),
8  
9  

Represents errors thrown by intercom, see IntercomError.js

9  
10      IntercomError = require('./IntercomError'),
11      url = require('url'),
12      Q = require('q');
13  
14  
15  

Define some sane default options Right now we only have one endpoint for intercom data

15  
16  var defaultOptions = {
17    endpoint: 'https://api.intercom.io/'
18  };
19  
20  
21  

Intercom constructor.

Params
appId String
  • your app Id OR personalAccessToken
apiKey String
  • your api key
options Object
  • an options object
API
public
27  
28  function Intercom(appId, apiKey, options) {
29  
30  

Overload the contractor Parse out single option objects

30  
31    if (_.isObject(appId) && !_.isString(appId) && ((appId.apiKey && appId.appId) || appId.personalAccessToken)) {
32      apiKey = appId.apiKey || '';
33      options = _.omit(appId, 'apiKey', 'appId');
34      appId = appId.appId || appId.personalAccessToken;
35    }
36  
37  
38  

Preform some sane validation checks and throw errors We need the appId

38  
39    if (!appId) {
40      throw new IntercomError('Invalid App ID: ' + appId);
41    }
42  
43  
44  

The api key is also required

43  
44    if (!apiKey) {
45      throw new IntercomError('Invalid API Key: ' + apiKey);
46    }
47  
48  
49  

Copy over the relavant data

48  
49    this.appId = appId;
50    this.apiKey = apiKey || '';
51  
52  
53  

Extend the defaults

52  
53    this.options = _.defaults(options || {}, Intercom.defaultOptions);
54  
55  
56  

Contruct the endpoint with the correct auth from the appId and apiKey

55  
56    this.endpoint = this.options.endpoint;
57  }
58  
59  
60  

Expose defaultOptions for the intercom library so that this is changable.

61  
62  Intercom.defaultOptions = defaultOptions;
63  
64  
65  

Helper method to create an instance easily

Enables use like this:

var intercom = require('intercom.io').create("your_APP_ID", "your_API_key");

or

var intercom = require('intercom.io').create(options);

Params
appId String
  • your app Id
apiKey String
  • your api key
options Object
  • an options object
API
public
79  
80  Intercom.create = function(appId, apiKey, options) {
81    return new Intercom(appId, apiKey, options);
82  };
83  
84  
85  

The main method that makes all the requests to intercom. This method deals with the intercom api and can be used to make requests to the intercom api.

API
public
90  
91  Intercom.prototype.request = function(method, path, parameters, cb) {
92    debug('Requesting [%s] %s with data %o', method, this.endpoint + path, parameters);
93  
94    var url = _.includes(path, this.endpoint) ? path : this.endpoint + path;
95  
96    var requestOptions = {
97      method: method,
98      url: url
99    };
100  
101    if (method === 'GET') {
102      requestOptions.qs = parameters;
103      requestOptions.headers = {
104        'Accept': 'application/json'
105      };
106    } else {
107  
108  

Intercom.io now requires parameters in JSON requestOptions.form = parameters;

108  
109      requestOptions.body = JSON.stringify(parameters);
110      requestOptions.headers = {
111        'Accept': 'application/json',
112        'Content-Type' : 'application/json'
113      };
114    }
115  
116    requestOptions.auth = {
117        username: this.appId,
118        password: this.apiKey || ''
119      };
120  
121  
122  

create a promise to return

121  
122    var deferred = Q.defer();
123  
124    request(requestOptions, function(err, res, data) {
125      if (err) {
126  
127  

Reject the promise

126  
127        return deferred.reject(err);
128      }
129  
130  
131  

Try to parse the data

130  
131      var parsed;
132      if (data) {
133        debug('Received response %s', data);
134  
135        try {
136          parsed = JSON.parse(data);
137  
138          if (parsed && (parsed.error || parsed.errors)) {
139            err = new IntercomError(data);
140  
141  
142  

Reject the promise

141  
142            return deferred.reject(err);
143          }
144        } catch (exception) {
145  
146  

Reject the promise return deferred.reject(exception);

146  
147        }
148      }
149  
150      var headers = res.headers;
151      data = parsed || data;
152      data.meta = {
153        ratelimit_limit: headers['x-ratelimit-limit'],
154        ratelimit_remaining: headers['x-ratelimit-remaining'],
155        ratelimit_reset: headers['x-ratelimit-reset']
156      };
157  
158  
159  

Resolve the promise

158  
159      return deferred.resolve(data);
160    });
161  
162  
163  

Return the promise and promisify any callback provided

162  
163    return deferred.promise.nodeify(cb);
164  };
165  
166  
167  

GETs all the pages of an Intercom resource in parallel.

Params
path String The resource to retrieve (e.g. companies)
parameters Object Query parameters for the root resource
cb Function Optional request callback
Returns
Promise A promise of an array containing all the elements of the requested resource.
API
public
175  
176  Intercom.prototype.getPages = function(path, parameters, cb) {
177  
178  

TODO Add a progress indicator when each page is retrieved

177  
178    var self = this;
179  
180    var rootPromise = this.request('GET', path, parameters);
181  
182    function requestNextPage(pages, nextUrl, parameters) {
183      return self.request('GET', nextUrl, parameters).then(function(root) {
184        var next = _.get(root, 'pages.next');
185        if(next) {
186          pages.push(root);
187          return requestNextPage(pages, next, parameters);
188        }
189        return pages.concat(root);
190      });
191    }
192  
193    function getAllPages(root) {
194      var next = _.get(root, 'pages.next');
195      if (next) {
196        return requestNextPage([root], next, parameters);
197      }
198      return root;
199    }
200  
201    function gatherPages (acc, result) {
202      return acc.concat(result[path]);
203    }
204  
205    return rootPromise.then(function (root) {
206      return root;
207    }).then(function (root) {
208      return getAllPages(root);
209    }).then(function (results) {
210      return results.reduce(gatherPages, []);
211    }).nodeify(cb);
212  };
213  
214  
215  

Helper method to create dates for intercom easily

Params
date NumberorDate
  • the date (in milliseconds if Number). Leave empty if you want the date set to now
Returns
Number epoch - time in seconds since Epoch (how intercom handles dates)
API
public
220  
221  Intercom.prototype.date = function(date) {
222    if (date === undefined) {
223      date = new Date();
224    }
225  
226    if (date && _.isDate(date) && date.getTime) {
227      return Math.floor(date.getTime() / 1000);
228    }
229  
230    return Math.floor((new Date(date)) / 1000);
231  };
232  
233  
234  

Users

233  
234  Intercom.prototype.getUsers = function(options, cb) {
235    if (_.isFunction(options)) {
236      cb = options;
237      options = {};
238    }
239  
240    return this.request('GET', 'users', options, cb);
241  };
242  
243  Intercom.prototype.getUser = function(userObj, cb) {
244    return this.request('GET', 'users', userObj, cb);
245  };
246  
247  Intercom.prototype.viewUser = function(userObj, cb) {
248    if (userObj && userObj.hasOwnProperty('id')) {
249        return this.request('GET', 'users' + '/' + userObj.id, {}, cb);
250    } else {
251        return this.request('GET', 'users', userObj, cb);
252    }
253  };
254  
255  Intercom.prototype.createUser = function(userObj, cb) {
256    return this.request('POST', 'users', userObj, cb);
257  };
258  
259  Intercom.prototype.updateUser = function(userObj, cb) {
260    return this.request('POST', 'users', userObj, cb);
261  };
262  
263  Intercom.prototype.deleteUser = function(userObj, cb) {
264    if (userObj && userObj.hasOwnProperty('id')) {
265      return this.request('DELETE', 'users' + '/' + userObj.id, {}, cb);
266    }
267    else {
268      return this.request('DELETE', 'users', userObj, cb);
269    }
270  };
271  
272  Intercom.prototype.bulkAddUsers = function(userObj, cb) {
273    return this.request('POST', 'bulk/users', userObj, cb);
274  };
275  
276  
277  
278  

Contacts

277  
278  Intercom.prototype.createContact = function(obj, cb) {
279    return this.request('POST', 'contacts', obj, cb);
280  };
281  Intercom.prototype.updateContact = Intercom.prototype.createContact;
282  
283  Intercom.prototype.deleteContact = function(obj, cb) {
284    return this.request('DELETE', 'contacts', obj, cb);
285  };
286  
287  Intercom.prototype.getContact = function(options, cb) {
288    if (_.isFunction(options)) {
289      cb = options;
290      options = {};
291    }
292  
293    return this.request('GET', 'contacts', options, cb);
294  };
295  Intercom.prototype.getContacts = Intercom.prototype.viewContact = Intercom.prototype.getContact;
296  
297  Intercom.prototype.convertContact = function(obj, cb) {
298    return this.request('POST', 'contacts/convert', obj, cb);
299  };
300  
301  
302  

Companies

301  
302  Intercom.prototype.listCompanies = function(companyObj, cb) {
303    return this.request('GET', 'companies', companyObj, cb);
304  };
305  
306  Intercom.prototype.viewCompany = function(companyObj, cb) {
307    if (companyObj && companyObj.hasOwnProperty('id')) {
308        return this.request('GET', 'companies/' + companyObj.id, {}, cb);
309    } else {
310        return this.request('GET', 'companies', companyObj, cb);
311    }
312  };
313  
314  Intercom.prototype.createCompany = function(companyObj, cb) {
315    return this.request('POST', 'companies', companyObj, cb);
316  };
317  
318  Intercom.prototype.updateCompany = function(companyObj, cb) {
319    return this.request('POST', 'companies', companyObj, cb);
320  };
321  
322  
323  

// Functionality doesn't currently exist Intercom.prototype.deleteCompany = function(companyObj, cb) { // return this.request('DELETE', 'companies', companyObj, cb); };

327  
328  
329  Intercom.prototype.listCompanyUsers = function(companyObj, cb) {
330    if (companyObj && companyObj.hasOwnProperty('id')) {
331        return this.request('GET', 'companies/' + companyObj.id + '/users', {}, cb);
332    } else {
333        return this.request('GET', 'companies', companyObj, cb);
334    }
335  };
336  
337  
338  

Admins

337  
338  Intercom.prototype.listAdmins = function(adminObj, cb) {
339    return this.request('GET', 'admins', adminObj, cb);
340  };
341  
342  
343  

Notes

342  
343  Intercom.prototype.createNote = function(noteObj, cb) {
344    return this.request('POST', 'notes', noteObj, cb);
345  };
346  
347  Intercom.prototype.listNotes = function(noteObj, cb) {
348    return this.request('GET', 'notes', noteObj, cb);
349  };
350  
351  Intercom.prototype.viewNote = function(noteObj, cb) {
352    if (noteObj && noteObj.hasOwnProperty('id')) {
353      return this.request('GET', 'notes/' + noteObj.id, {}, cb);
354    } else {
355      return this.request('GET', 'notes', noteObj, cb);
356    }
357  };
358  
359  
360  

Tags

359  
360  Intercom.prototype.getTag = function(tagObj, cb) {
361    return this.request('GET', 'tags', tagObj, cb);
362  };
363  
364  Intercom.prototype.createTag = function(tagObj, cb) {
365    return this.request('POST', 'tags', tagObj, cb);
366  };
367  
368  Intercom.prototype.deleteTag = function(tagObj, cb) {
369    return this.request('DELETE', 'tags/' + tagObj.id, {}, cb);
370  };
371  
372  Intercom.prototype.updateTag = function(tagObj, cb) {
373  
374  

Note: tagObj should be empty

373  
374    return this.request('POST', 'tags', tagObj, cb);
375  };
376  
377  
378  

Segments

377  
378  Intercom.prototype.listSegments = function(segmentObj, cb) {
379    return this.request('GET', 'segments', segmentObj, cb);
380  };
381  
382  Intercom.prototype.viewSegment = function(segmentObj, cb) {
383    if (segmentObj && segmentObj.hasOwnProperty('id')) {
384      return this.request('GET', 'segments/' + segmentObj.id || segmentObj.segment_id, {}, cb);
385    } else {
386      return this.request('GET', 'segments', segmentObj, cb);
387    }
388  };
389  
390  
391  

Events

390  
391  Intercom.prototype.createEvent = function(eventObj, cb) {
392    return this.request('POST', 'events', eventObj, cb);
393  };
394  
395  
396  

Counts

395  
396  Intercom.prototype.getCounts = function(countObj, cb) {
397    return this.request('GET', 'counts', countObj, cb);
398  };
399  
400  
401  

Conversations

(NOTE: the Conversations API is only available to Apps on the Starter and Premium plans)

401  
402  Intercom.prototype.createUserMessage = function(messageObj, cb) {
403    return this.request('POST', 'messages', messageObj, cb);
404  };
405  
406  Intercom.prototype.listConversations = function (convObj, cb) {
407    return this.request('GET', 'conversations', convObj, cb);
408  };
409  
410  Intercom.prototype.getConversation = function (convObj, cb) {
411    if (convObj && convObj.hasOwnProperty('id')) {
412      return this.request('GET', 'conversations/' + convObj.id, {}, cb);
413    } else {
414      return this.request('GET', 'conversations', convObj, cb);
415    }
416  };
417  
418  
419  

It will automatically reply to the last conversation if convObj.id is left out

418  
419  Intercom.prototype.replyConversation = function (convObj, cb) {
420    if (convObj && convObj.hasOwnProperty('id')) {
421      return this.request('POST', 'conversations/' + convObj.id + '/reply', convObj, cb);
422    } else {
423      return this.request('POST', 'conversations/last/reply', convObj, cb);
424    }
425  };
426  
427  

Closing a conversation is the same as replying to a conversation with a special convObj See https://developers.intercom.io/docs/closing-a-conversation

427  
428  Intercom.prototype.closeConversation = Intercom.prototype.replyConversation;
429  
430  Intercom.prototype.markConversationAsRead = function (convObj, cb) {
431    if (convObj && convObj.hasOwnProperty('id')) {
432      return this.request('PUT', 'conversations/' + convObj.id , convObj, cb);
433    } else {
434      return this.request('PUT', 'conversations/last', convObj, cb);
435    }
436  };
437  
438  
439  

Expose Intercom Library.

440  
441  module.exports = Intercom;
442