intercom 3.5.10 → 4.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +35 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
  4. data/Gemfile +1 -4
  5. data/README.md +418 -216
  6. data/RELEASING.md +9 -0
  7. data/Rakefile +1 -1
  8. data/changes.txt +141 -0
  9. data/intercom.gemspec +1 -2
  10. data/lib/intercom.rb +34 -19
  11. data/lib/intercom/api_operations/archive.rb +16 -0
  12. data/lib/intercom/api_operations/delete.rb +4 -1
  13. data/lib/intercom/api_operations/find.rb +5 -2
  14. data/lib/intercom/api_operations/find_all.rb +4 -3
  15. data/lib/intercom/api_operations/list.rb +4 -1
  16. data/lib/intercom/api_operations/load.rb +4 -2
  17. data/lib/intercom/api_operations/nested_resource.rb +70 -0
  18. data/lib/intercom/api_operations/request_hard_delete.rb +12 -0
  19. data/lib/intercom/api_operations/save.rb +6 -4
  20. data/lib/intercom/api_operations/scroll.rb +4 -5
  21. data/lib/intercom/api_operations/search.rb +18 -0
  22. data/lib/intercom/article.rb +7 -0
  23. data/lib/intercom/base_collection_proxy.rb +72 -0
  24. data/lib/intercom/client.rb +66 -18
  25. data/lib/intercom/client_collection_proxy.rb +17 -39
  26. data/lib/intercom/collection.rb +7 -0
  27. data/lib/intercom/company.rb +8 -0
  28. data/lib/intercom/contact.rb +22 -3
  29. data/lib/intercom/conversation.rb +5 -0
  30. data/lib/intercom/data_attribute.rb +7 -0
  31. data/lib/intercom/deprecated_leads_collection_proxy.rb +22 -0
  32. data/lib/intercom/deprecated_resources.rb +13 -0
  33. data/lib/intercom/errors.rb +44 -4
  34. data/lib/intercom/extended_api_operations/segments.rb +3 -1
  35. data/lib/intercom/extended_api_operations/tags.rb +3 -1
  36. data/lib/intercom/lead.rb +21 -0
  37. data/lib/intercom/lib/typed_json_deserializer.rb +42 -37
  38. data/lib/intercom/note.rb +4 -0
  39. data/lib/intercom/request.rb +162 -95
  40. data/lib/intercom/scroll_collection_proxy.rb +38 -42
  41. data/lib/intercom/search_collection_proxy.rb +47 -0
  42. data/lib/intercom/section.rb +23 -0
  43. data/lib/intercom/segment.rb +4 -0
  44. data/lib/intercom/service/article.rb +20 -0
  45. data/lib/intercom/service/base_service.rb +13 -0
  46. data/lib/intercom/service/collection.rb +24 -0
  47. data/lib/intercom/service/company.rb +4 -2
  48. data/lib/intercom/service/contact.rb +29 -6
  49. data/lib/intercom/service/conversation.rb +23 -2
  50. data/lib/intercom/service/data_attribute.rb +20 -0
  51. data/lib/intercom/service/event.rb +12 -0
  52. data/lib/intercom/service/lead.rb +41 -0
  53. data/lib/intercom/service/note.rb +4 -8
  54. data/lib/intercom/service/section.rb +7 -0
  55. data/lib/intercom/service/tag.rb +8 -8
  56. data/lib/intercom/service/team.rb +17 -0
  57. data/lib/intercom/service/user.rb +4 -2
  58. data/lib/intercom/service/visitor.rb +15 -6
  59. data/lib/intercom/tag.rb +4 -0
  60. data/lib/intercom/team.rb +7 -0
  61. data/lib/intercom/traits/api_resource.rb +48 -27
  62. data/lib/intercom/traits/dirty_tracking.rb +8 -1
  63. data/lib/intercom/user.rb +12 -3
  64. data/lib/intercom/utils.rb +13 -2
  65. data/lib/intercom/version.rb +1 -1
  66. data/lib/intercom/visitor.rb +0 -2
  67. data/spec/spec_helper.rb +881 -436
  68. data/spec/unit/intercom/admin_spec.rb +2 -2
  69. data/spec/unit/intercom/article_spec.rb +40 -0
  70. data/spec/unit/intercom/base_collection_proxy_spec.rb +30 -0
  71. data/spec/unit/intercom/client_collection_proxy_spec.rb +41 -41
  72. data/spec/unit/intercom/client_spec.rb +76 -9
  73. data/spec/unit/intercom/collection_spec.rb +32 -0
  74. data/spec/unit/intercom/company_spec.rb +29 -21
  75. data/spec/unit/intercom/contact_spec.rb +365 -29
  76. data/spec/unit/intercom/conversation_spec.rb +70 -7
  77. data/spec/unit/intercom/count_spec.rb +4 -4
  78. data/spec/unit/intercom/data_attribute_spec.rb +40 -0
  79. data/spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb +17 -0
  80. data/spec/unit/intercom/event_spec.rb +25 -8
  81. data/spec/unit/intercom/job_spec.rb +24 -24
  82. data/spec/unit/intercom/lead_spec.rb +57 -0
  83. data/spec/unit/intercom/lib/flat_store_spec.rb +22 -20
  84. data/spec/unit/intercom/message_spec.rb +1 -1
  85. data/spec/unit/intercom/note_spec.rb +4 -10
  86. data/spec/unit/intercom/request_spec.rb +150 -9
  87. data/spec/unit/intercom/scroll_collection_proxy_spec.rb +40 -39
  88. data/spec/unit/intercom/search_collection_proxy_spec.rb +60 -0
  89. data/spec/unit/intercom/section_spec.rb +32 -0
  90. data/spec/unit/intercom/segment_spec.rb +2 -2
  91. data/spec/unit/intercom/subscription_spec.rb +5 -6
  92. data/spec/unit/intercom/tag_spec.rb +22 -14
  93. data/spec/unit/intercom/team_spec.rb +21 -0
  94. data/spec/unit/intercom/traits/api_resource_spec.rb +129 -47
  95. data/spec/unit/intercom/user_spec.rb +227 -217
  96. data/spec/unit/intercom/visitor_spec.rb +49 -0
  97. data/spec/unit/intercom_spec.rb +5 -3
  98. metadata +63 -26
  99. data/.travis.yml +0 -6
  100. data/lib/intercom/extended_api_operations/users.rb +0 -16
  101. data/spec/unit/intercom/visitors_spec.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0f98bf7f9725ad035949ca88859ba807a6323a83
4
- data.tar.gz: 97e46a4507500d311495e11114fb80d0715cb0a0
2
+ SHA256:
3
+ metadata.gz: ebb883bd25fc8d132306baac3a22c43650701dbe42d42b95ada3819bc52cc2d6
4
+ data.tar.gz: 8d1158c4d79cf19916c6cc1d413c329588d1ff36b5741517e029415e0f992360
5
5
  SHA512:
6
- metadata.gz: 8c83c5d9c5ad9d4844b5b8f7c3602e6bf76cbbb9e9836b264acbdcfdb5e3567310c1441e23c7cd0b2dac30f0200bbea46175fe9eea5c130aa49d16e9ca5cd2d4
7
- data.tar.gz: b480c171fd98135e719c37be86b0d13f7288f65130583d863afad3dd32acdc42de3e66be8941620047ba57db9fc54548b10307cbed55bd5278563825e6728de0
6
+ metadata.gz: 0a0ea848ac117043da9707f2f9689504abda06f34e218a077c0591216aa654c3e9ca73f9874f2255e7300cd3329c95ba6440232c30d58364877e7d358bf950d0
7
+ data.tar.gz: 95b5ffdd05e7332fcbd53061c08c380d8632bd9f11d09e3673da65ca25b4624377b409116292b41f626a0fc6b4ad3d1c5183e5315533d3b4f94fe285c74041a6
@@ -0,0 +1,35 @@
1
+ version: 2
2
+ jobs:
3
+ "Test against Ruby 2.4":
4
+ docker:
5
+ - image: circleci/ruby:2.4.9
6
+ working_directory: ~/intercom-ruby
7
+ steps:
8
+ - checkout
9
+ - run: bundle install
10
+ - run: bundle exec rake
11
+ "Test against Ruby 2.5":
12
+ docker:
13
+ - image: circleci/ruby:2.5.7
14
+ working_directory: ~/intercom-ruby
15
+ steps:
16
+ - checkout
17
+ - run: bundle install
18
+ - run: bundle exec rake
19
+ "Test against Ruby 2.6":
20
+ docker:
21
+ - image: circleci/ruby:2.6.5
22
+ working_directory: ~/intercom-ruby
23
+ steps:
24
+ - checkout
25
+ - run: bundle install
26
+ - run: bundle exec rake
27
+
28
+ workflows:
29
+ version: 2
30
+ build_and_test:
31
+ jobs:
32
+ - "Test against Ruby 2.4"
33
+ - "Test against Ruby 2.5"
34
+ - "Test against Ruby 2.6"
35
+
@@ -0,0 +1,5 @@
1
+ #### Why?
2
+ Why are you making this change?
3
+
4
+ #### How?
5
+ Technical details on your change
data/Gemfile CHANGED
@@ -1,13 +1,10 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem 'webmock'
3
4
  gemspec
4
5
 
5
6
  group :development, :test do
6
7
  platforms :jruby do
7
- gem 'json-jruby'
8
8
  gem 'jruby-openssl'
9
9
  end
10
- platforms :ruby_18 do
11
- gem 'json_pure'
12
- end
13
10
  end
data/README.md CHANGED
@@ -6,35 +6,39 @@ Ruby bindings for the Intercom API (https://developers.intercom.io/reference).
6
6
 
7
7
  [Gem Documentation](http://rubydoc.info/github/intercom/intercom-ruby/master/frames)
8
8
 
9
- For generating Intercom javascript script tags for Rails, please see https://github.com/intercom/intercom-rails.
9
+ For generating Intercom JavaScript script tags for Rails, please see https://github.com/intercom/intercom-rails.
10
10
 
11
11
  ## Upgrading information
12
12
 
13
- Version 3 of intercom-ruby is not backwards compatible with previous versions.
14
-
15
- Version 3 moves away from a global setup approach to the use of an Intercom Client.
13
+ Version 4 of intercom-ruby is not backwards compatible with previous versions. Please see our [migration guide](https://github.com/intercom/intercom-ruby/wiki/Migration-guide-for-v4) for full details of breaking changes.
16
14
 
17
15
  This version of the gem is compatible with `Ruby 2.1` and above.
18
16
 
19
17
  ## Installation
20
18
 
19
+
21
20
  gem install intercom
22
21
 
23
22
  Using bundler:
24
23
 
25
- gem 'intercom', '~> 3.5.9'
24
+ gem 'intercom', '~> 4.1'
26
25
 
27
26
  ## Basic Usage
28
27
 
29
28
  ### Configure your client
30
29
 
31
- > If you already have a personal access token you can find it [here](https://app.intercom.io/a/apps/_/settings/personal-access-token). If you want to create or learn more about personal access tokens then you can find more info [here](https://developers.intercom.io/docs/personal-access-tokens).
30
+ > If you already have a personal access token you can find it [here](https://app.intercom.io/a/apps/_/developer-hub/). If you want to create or learn more about personal access tokens then you can find more info [here](https://developers.intercom.io/docs/personal-access-tokens).
32
31
 
33
32
  ```ruby
34
33
  # With an OAuth or Personal Access token:
35
34
  intercom = Intercom::Client.new(token: 'my_token')
36
35
  ```
37
36
 
37
+ ```ruby
38
+ # With a versioned app:
39
+ intercom = Intercom::Client.new(token: 'my_token', api_version: '2.1')
40
+ ```
41
+
38
42
  If you are building a third party application you can get your access_tokens by [setting-up-oauth](https://developers.intercom.io/page/setting-up-oauth) for Intercom.
39
43
  You can also use the [omniauth-intercom lib](https://github.com/intercom/omniauth-intercom) which is a middleware helping you to handle the authentication process with Intercom.
40
44
 
@@ -42,146 +46,258 @@ You can also use the [omniauth-intercom lib](https://github.com/intercom/omniaut
42
46
 
43
47
  Resources this API supports:
44
48
 
45
- https://api.intercom.io/users
46
49
  https://api.intercom.io/contacts
50
+ https://api.intercom.io/visitors
47
51
  https://api.intercom.io/companies
48
- https://api.intercom.io/counts
52
+ https://api.intercom.io/data_attributes
53
+ https://api.intercom.io/events
49
54
  https://api.intercom.io/tags
50
55
  https://api.intercom.io/notes
51
56
  https://api.intercom.io/segments
52
- https://api.intercom.io/events
53
57
  https://api.intercom.io/conversations
54
58
  https://api.intercom.io/messages
59
+ https://api.intercom.io/admins
60
+ https://api.intercom.io/teams
61
+ https://api.intercom.io/counts
55
62
  https://api.intercom.io/subscriptions
56
63
  https://api.intercom.io/jobs
57
- https://api.intercom.io/bulk
64
+ https://api.intercom.io/articles
65
+ https://api.intercom.io/help_center/collections
66
+ https://api.intercom.io/help_center/sections
67
+
58
68
 
59
69
  ### Examples
60
70
 
61
- #### Users
71
+ #### Contacts
72
+ Note that this is a new resource compatible only with the new [Contacts API](https://developers.intercom.com/intercom-api-reference/reference#contacts-model) released in API v2.0.
62
73
 
63
74
  ```ruby
64
- # Find user by email
65
- user = intercom.users.find(email: "bob@example.com")
66
- # Find user by user_id
67
- user = intercom.users.find(user_id: "1")
68
- # Find user by id
69
- user = intercom.users.find(id: "1")
70
- # Create a user
71
- user = intercom.users.create(email: "bob@example.com", name: "Bob Smith", signed_up_at: Time.now.to_i)
72
- # Delete a user
73
- user = intercom.users.find(id: "1")
74
- deleted_user = intercom.users.delete(user)
75
- # Update custom_attributes for a user
76
- user.custom_attributes["average_monthly_spend"] = 1234.56
77
- intercom.users.save(user)
78
- # Perform incrementing
79
- user.increment('karma')
80
- intercom.users.save(user)
81
- # Perform decrementing
82
- user.decrement('karma', 5)
83
- intercom.users.save(user)
84
- # Iterate over all users
85
- intercom.users.all.each {|user| puts %Q(#{user.email} - #{user.custom_attributes["average_monthly_spend"]}) }
86
- intercom.users.all.map {|user| user.email }
87
- # List your users create in the last two days
88
- intercom.users.find_all(type: 'users', page: 1, per_page: 10, created_since: 2, order: :asc).to_a.each_with_index {|usr, i| puts "#{i+1}: #{usr.name}"};
89
- # Paginate through your list of users choosing how many to return per page (default and max is 50 per page)
90
- intercom.users.find_all(type: 'users', page: 1, per_page: 10, order: :asc).to_a.each_with_index {|usr, i| puts "#{i+1}: #{usr.name}"}
91
- # If you have over 10,000 users then you will need to use the scroll function to list your users
92
- # otherwise you will encounter a page limit with list all your users
93
- # You can use the scroll method to list all your users
94
- intercom.users.scroll.each { |user| puts user.name}
95
- # Alternatively you can use the scroll.next method to get 100 users with each request
96
- result = intercom.users.scroll.next
97
- # The result object then contains a records attributes that is an array of your user objects and it also contains a scroll_param which
98
- # you can then use to request the next 100 users. Note that the scroll parameter will time out after one minute and you will need to
99
- # make a new request
100
- result.scroll_param
101
- => "0730e341-63ef-44da-ab9c-9113f886326d"
102
- result = intercom.users.scroll.next("0730e341-63ef-44da-ab9c-9113f886326d");
103
-
104
- #Bulk operations.
105
- # Submit bulk job to create users. If any of the items in create_items match an existing user that user will be updated
106
- intercom.users.submit_bulk_job(create_items: [{user_id: "25", email: "alice@example.com"}, {user_id: "25", email: "bob@example.com"}])
107
- # Submit bulk job to create users with companies. Companies must be sent as an array of objects nested within each applicable user object
108
- intercom.users.submit_bulk_job(create_items: [{user_id: "25", email: "alice@example.com", companies: [{company_id: 9, name: "Test Company"}]}])
109
- # Submit bulk job, to delete users
110
- intercom.users.submit_bulk_job(delete_items: [{user_id: "25", email: "alice@example.com"}, {user_id: "25", email: "bob@example.com"}])
111
- # Submit bulk job, to add items to existing job
112
- intercom.users.submit_bulk_job(create_items: [{user_id: "25", email: "alice@example.com"}], delete_items: [{user_id: "25", email: "bob@example.com"}], job_id:'job_abcd1234')
75
+ # Create a contact with "lead" role
76
+ contact = intercom.contacts.create(email: "some_contact2@example.com", role: "lead")
77
+
78
+ # Get a single contact using their intercom_id
79
+ intercom.contacts.find(id: contact.id)
80
+
81
+ # Update a contact
82
+ contact.name = "New name"
83
+ intercom.contacts.save(contact)
84
+
85
+ # Update a contact's role from "lead" to "user"
86
+ contact.role = "user"
87
+ intercom.contacts.save(contact)
88
+
89
+ # Archive a contact
90
+ intercom.contacts.archive(contact)
91
+
92
+ # Unarchive a contact
93
+ intercom.contacts.unarchive(contact)
94
+
95
+ # Delete a contact permanently
96
+ intercom.contacts.delete(contact)
97
+
98
+ # List all contacts
99
+ contacts = intercom.contacts.all
100
+ contacts.each { |contact| p contact.name }
101
+
102
+ # Search for contacts by email
103
+ contacts = intercom.contacts.search(
104
+ "query": {
105
+ "field": 'email',
106
+ "operator": '=',
107
+ "value": 'some_contact@example.com'
108
+ }
109
+ )
110
+ contacts.each {|c| p c.email}
111
+ # For full detail on possible queries, please refer to the API documentation:
112
+ # https://developers.intercom.com/intercom-api-reference/reference
113
+
114
+ # Merge a lead into an existing user
115
+ lead = intercom.contacts.create(email: "some_contact2@example.com", role: "lead")
116
+ intercom.contacts.merge(lead, intercom.contacts.find(id: "5db2e80ab1b92243d2188cfe"))
117
+
118
+ # Add a tag to a contact
119
+ tag = intercom.tags.find(id: "123")
120
+ contact.add_tag(id: tag.id)
121
+
122
+ # Remove a tag
123
+ contact.remove_tag(id: tag.id)
124
+
125
+ # List tags for a contact
126
+ contact.tags.each {|t| p t.name}
127
+
128
+ # Create a note on a contact
129
+ contact.create_note(body: "<p>Text for the note</p>")
130
+
131
+ # List notes for a contact
132
+ contact.notes.each {|n| p n.body}
133
+
134
+ # List segments for a contact
135
+ contact.segments.each {|segment| p segment.name}
136
+
137
+ # Add a contact to a company
138
+ company = intercom.companies.find(id: "123")
139
+ contact.add_company(id: company.id)
140
+
141
+ # Remove a contact from a company
142
+ contact.remove_company(id: company.id)
143
+
144
+ # List companies for a contact
145
+ contact.companies.each {|c| p c.name}
113
146
  ```
114
147
 
115
- #### Admins
148
+ #### Visitors
116
149
  ```ruby
117
- # Find access token owner (only with Personal Access Token and OAuth)
118
- intercom.admins.me
119
- # Find an admin by id
120
- intercom.admins.find(id: admin_id)
121
- # Iterate over all admins
122
- intercom.admins.all.each {|admin| puts admin.email }
150
+ # Get and update a visitor
151
+ visitor = intercom.visitors.find(id: "5dd570e7b1b922452676af23")
152
+ visitor.name = "New name"
153
+ intercom.visitors.save(visitor)
154
+
155
+ # Convert a visitor into a lead
156
+ intercom.visitors.convert(visitor)
157
+
158
+ # Convert a visitor into a user
159
+ user = intercom.contacts.find(id: "5db2e7f5b1b92243d2188cb3")
160
+ intercom.visitors.convert(visitor, user)
123
161
  ```
124
162
 
125
163
  #### Companies
126
164
  ```ruby
127
- # Add a user to one or more companies
128
- user = intercom.users.find(email: "bob@example.com")
129
- user.companies = [{company_id: 6, name: "Intercom"}, {company_id: 9, name: "Test Company"}]
130
- intercom.users.save(user)
131
- # You can also pass custom attributes within a company as you do this
132
- user.companies = [{id: 6, name: "Intercom", custom_attributes: {referral_source: "Google"} } ]
133
- intercom.users.save(user)
134
165
  # Find a company by company_id
135
166
  company = intercom.companies.find(company_id: "44")
167
+
136
168
  # Find a company by name
137
169
  company = intercom.companies.find(name: "Some company")
170
+
138
171
  # Find a company by id
139
172
  company = intercom.companies.find(id: "41e66f0313708347cb0000d0")
173
+
140
174
  # Update a company
141
175
  company.name = 'Updated company name'
142
176
  intercom.companies.save(company)
177
+
178
+ # Delete a company
179
+ intercom.companies.delete(company)
180
+
143
181
  # Iterate over all companies
144
182
  intercom.companies.all.each {|company| puts %Q(#{company.name} - #{company.custom_attributes["referral_source"]}) }
145
183
  intercom.companies.all.map {|company| company.name }
146
- # Get a list of users in a company
147
- intercom.companies.users(company.id)
184
+
185
+ # Get a large list of companies using scroll
186
+ intercom.companies.scroll.each { |comp| puts comp.name}
187
+ # Please see users scroll for more details of how to use scroll
188
+ ```
189
+
190
+ #### Data Attributes
191
+ Data Attributes are a type of metadata used to describe your customer and company models. These include standard and custom attributes.
192
+ ```ruby
193
+ # Create a new custom data attribute
194
+ intercom.data_attributes.create({ name: "test_attribute", model: "contact", data_type: "string" })
195
+
196
+ # List all data attributes
197
+ attributes = intercom.data_attributes.all
198
+ attributes.each { |attribute| p attribute.name }
199
+
200
+ # Update an attribute
201
+ attribute = intercom.data_attributes.all.first
202
+ attribute.label = "New label"
203
+ intercom.data_attributes.save(attribute)
204
+
205
+ # Archive an attribute
206
+ attribute.archived = true
207
+ intercom.data_attributes.save(attribute)
208
+
209
+ # Find all customer attributes including archived
210
+ customer_attributes_incl_archived = intercom.data_attributes.find_all({"model": "contact", "include_archived": true})
211
+ customer_attributes_incl_archived.each { |attr| p attribute.name }
148
212
  ```
149
213
 
214
+ #### Events
215
+ ```ruby
216
+ intercom.events.create(
217
+ event_name: "invited-friend",
218
+ created_at: Time.now.to_i,
219
+ email: user.email,
220
+ metadata: {
221
+ "invitee_email" => "pi@example.org",
222
+ invite_code: "ADDAFRIEND",
223
+ "found_date" => 12909364407
224
+ }
225
+ )
226
+
227
+ # Alternatively, use "user_id" in case your app allows multiple accounts having the same email
228
+ intercom.events.create(
229
+ event_name: "invited-friend",
230
+ created_at: Time.now.to_i,
231
+ user_id: user.uuid,
232
+ )
233
+
234
+ # Retrieve event list for user with id:'123abc'
235
+ intercom.events.find_all("type" => "user", "intercom_user_id" => "123abc")
236
+ ```
237
+
238
+ Metadata Objects support a few simple types that Intercom can present on your behalf
239
+
240
+ ```ruby
241
+ intercom.events.create(
242
+ event_name: "placed-order",
243
+ email: current_user.email,
244
+ created_at: 1403001013,
245
+ metadata: {
246
+ order_date: Time.now.to_i,
247
+ stripe_invoice: 'inv_3434343434',
248
+ order_number: {
249
+ value: '3434-3434',
250
+ url: 'https://example.org/orders/3434-3434'
251
+ },
252
+ price: {
253
+ currency: 'usd',
254
+ amount: 2999
255
+ }
256
+ }
257
+ )
258
+ ```
259
+
260
+ The metadata key values in the example are treated as follows-
261
+ - order_date: a Date (key ends with '_date')
262
+ - stripe_invoice: The identifier of the Stripe invoice (has a 'stripe_invoice' key)
263
+ - order_number: a Rich Link (value contains 'url' and 'value' keys)
264
+ - price: An Amount in US Dollars (value contains 'amount' and 'currency' keys)
265
+
266
+ *NB:* This version of the gem reserves the field name `type` in Event data.
267
+
150
268
  #### Tags
151
269
  ```ruby
152
- # Tag users
153
- tag = intercom.tags.tag(name: 'blue', users: [{email: "test1@example.com"}])
154
- # Untag users
155
- intercom.tags.untag(name: 'blue', users: [{user_id: "42ea2f1b93891f6a99000427"}])
156
270
  # Iterate over all tags
157
271
  intercom.tags.all.each {|tag| "#{tag.id} - #{tag.name}" }
158
272
  intercom.tags.all.map {|tag| tag.name }
273
+
159
274
  # Tag companies
160
- tag = intercom.tags.tag(name: 'blue', companies: [{id: "42ea2f1b93891f6a99000427"}])
275
+ tag = intercom.tags.tag(name: 'blue', companies: [{company_id: "42ea2f1b93891f6a99000427"}])
276
+
277
+ # Untag Companies
278
+ tag = intercom.tags.untag(name: 'blue', companies: [{ company_id: "42ea2f1b93891f6a99000427" }])
279
+ ```
280
+
281
+ #### Notes
282
+ ```ruby
283
+ # Find a note by id
284
+ note = intercom.notes.find(id: "123")
161
285
  ```
162
286
 
163
287
  #### Segments
164
288
  ```ruby
165
289
  # Find a segment
166
290
  segment = intercom.segments.find(id: segment_id)
291
+
167
292
  # Iterate over all segments
168
293
  intercom.segments.all.each {|segment| puts "id: #{segment.id} name: #{segment.name}"}
169
294
  ```
170
295
 
171
- #### Notes
172
- ```ruby
173
- # Find a note by id
174
- note = intercom.notes.find(id: note)
175
- # Create a note for a user
176
- note = intercom.notes.create(body: "<p>Text for the note</p>", email: 'joe@example.com')
177
- # Iterate over all notes for a user via their email address
178
- intercom.notes.find_all(email: 'joe@example.com').each {|note| puts note.body}
179
- # Iterate over all notes for a user via their user_id
180
- intercom.notes.find_all(user_id: '123').each {|note| puts note.body}
181
- ```
182
-
183
296
  #### Conversations
184
297
  ```ruby
298
+ # Iterate over all conversations for your app
299
+ intercom.conversations.all.each { |convo| ... }
300
+
185
301
  # FINDING CONVERSATIONS FOR AN ADMIN
186
302
  # Iterate over all conversations (open and closed) assigned to an admin
187
303
  intercom.conversations.find_all(type: 'admin', id: '7').each {|convo| ... }
@@ -189,7 +305,7 @@ intercom.conversations.find_all(type: 'admin', id: '7').each {|convo| ... }
189
305
  intercom.conversations.find_all(type: 'admin', id: 7, open: true).each {|convo| ... }
190
306
  # Iterate over closed conversations assigned to an admin
191
307
  intercom.conversations.find_all(type: 'admin', id: 7, open: false).each {|convo| ... }
192
- # Iterate over closed conversations for assigned an admin, before a certain moment in time
308
+ # Iterate over closed conversations which are assigned to an admin, and where updated_at is before a certain moment in time
193
309
  intercom.conversations.find_all(type: 'admin', id: 7, open: false, before: 1374844930).each {|convo| ... }
194
310
 
195
311
  # FINDING CONVERSATIONS FOR A USER
@@ -199,18 +315,32 @@ intercom.conversations.find_all(email: 'joe@example.com', type: 'user').each {|c
199
315
  intercom.conversations.find_all(email: 'joe@example.com', type: 'user', unread: false).each {|convo| ... }
200
316
  # Iterate over all unread conversations with a user based on the users email
201
317
  intercom.conversations.find_all(email: 'joe@example.com', type: 'user', unread: true).each {|convo| ... }
318
+ # Iterate over all conversations for a user with their Intercom user ID
319
+ intercom.conversations.find_all(intercom_user_id: '536e564f316c83104c000020', type: 'user').each {|convo| ... }
320
+ # Iterate over all conversations for a lead
321
+ # NOTE: to iterate over a lead's conversations you MUST use their Intercom User ID and type User
322
+ intercom.conversations.find_all(intercom_user_id: lead.id, type: 'user').each {|convo| ... }
202
323
 
203
324
  # FINDING A SINGLE CONVERSATION
204
325
  conversation = intercom.conversations.find(id: '1')
205
326
 
206
327
  # INTERACTING WITH THE PARTS OF A CONVERSATION
207
328
  # Getting the subject of a part (only applies to email-based conversations)
208
- conversation.rendered_message.subject
329
+ conversation.source.subject
330
+
209
331
  # Get the part_type of the first part
210
- conversation.conversation_parts[0].part_type
332
+ conversation.conversation_parts.first.part_type
333
+
211
334
  # Get the body of the second part
212
335
  conversation.conversation_parts[1].body
213
336
 
337
+ # Get statistics related to the conversation
338
+ conversation.statistics.time_to_admin_reply
339
+ conversation.statistics.last_assignment_at
340
+
341
+ # Get information on the sla applied to a conversation
342
+ conversation.sla_applied.sla_name
343
+
214
344
  # REPLYING TO CONVERSATIONS
215
345
  # User (identified by email) replies with a comment
216
346
  intercom.conversations.reply(id: conversation.id, type: 'user', email: 'joe@example.com', message_type: 'comment', body: 'foo')
@@ -219,6 +349,9 @@ intercom.conversations.reply(id: conversation.id, type: 'admin', admin_id: '123'
219
349
  # User (identified by email) replies with a comment and attachment
220
350
  intercom.conversations.reply(id: conversation.id, type: 'user', email: 'joe@example.com', message_type: 'comment', body: 'foo', attachment_urls: ['http://www.example.com/attachment.jpg'])
221
351
 
352
+ #reply to a user's last conversation
353
+ intercom.conversations.reply_to_last(type: 'user', body: 'Thanks again', message_type: 'comment', user_id: '12345', admin_id: '123')
354
+
222
355
  # Open
223
356
  intercom.conversations.open(id: conversation.id, admin_id: '123')
224
357
 
@@ -226,26 +359,75 @@ intercom.conversations.open(id: conversation.id, admin_id: '123')
226
359
  intercom.conversations.close(id: conversation.id, admin_id: '123')
227
360
 
228
361
  # Assign
362
+ # Note: Conversations can be assigned to teams. However, the entity that performs the operation of assigning the conversation has to be an existing teammate.
363
+ # You can use `intercom.admins.all.each {|a| puts a.inspect if a.type == 'admin' }` to list all of your teammates.
229
364
  intercom.conversations.assign(id: conversation.id, admin_id: '123', assignee_id: '124')
230
365
 
366
+ # Snooze
367
+ intercom.conversations.snooze(id: conversation.id, admin_id: '123', snoozed_until: 9999999999)
368
+
231
369
  # Reply and Open
232
370
  intercom.conversations.reply(id: conversation.id, type: 'admin', admin_id: '123', message_type: 'open', body: 'bar')
233
371
 
234
372
  # Reply and Close
235
373
  intercom.conversations.reply(id: conversation.id, type: 'admin', admin_id: '123', message_type: 'close', body: 'bar')
236
374
 
375
+ # Admin reply to last conversation
376
+ intercom.conversations.reply_to_last(intercom_user_id: '5678', type: 'admin', admin_id: '123', message_type: 'comment', body: 'bar')
377
+
378
+ # User reply to last conversation
379
+ intercom.conversations.reply_to_last(intercom_user_id: '5678', type: 'user', message_type: 'comment', body: 'bar')
380
+
237
381
  # ASSIGNING CONVERSATIONS TO ADMINS
238
382
  intercom.conversations.reply(id: conversation.id, type: 'admin', assignee_id: assignee_admin.id, admin_id: admin.id, message_type: 'assignment')
239
383
 
240
384
  # MARKING A CONVERSATION AS READ
241
385
  intercom.conversations.mark_read(conversation.id)
386
+
387
+ # RUN ASSIGNMENT RULES
388
+ intercom.conversations.run_assignment_rules(conversation.id)
389
+
390
+ # Search for conversations
391
+ # For full detail on possible queries, please refer to the API documentation:
392
+ # https://developers.intercom.com/intercom-api-reference/reference
393
+
394
+ # Search for open conversations sorted by the created_at date
395
+ conversations = intercom.conversations.search(
396
+ query: {
397
+ field: "open",
398
+ operator: "=",
399
+ value: true
400
+ },
401
+ sort_field: "created_at",
402
+ sort_order: "descending"
403
+ )
404
+ conversations.each {|c| p c.id}
405
+
406
+ # Tagging for conversations
407
+ tag = intercom.tags.find(id: "2")
408
+ conversation = intercom.conversations.find(id: "1")
409
+
410
+ # An Admin ID is required to add or remove tag on a conversation
411
+ admin = intercom.admins.find(id: "1")
412
+
413
+ # Add a tag to a conversation
414
+ conversation.add_tag(id: tag.id, admin_id: admin.id)
415
+
416
+ # Remove a tag from a conversation
417
+ conversation.remove_tag(id: tag.id, admin_id: admin.id)
418
+
419
+ # Add a contact to a conversation
420
+ conversation.add_contact(admin_id: admin.id, customer: { intercom_user_id: contact.id })
421
+
422
+ # Remove a contact from a conversation
423
+ conversation.remove_contact(id: contact.id, admin_id: admin.id)
242
424
  ```
243
425
 
244
426
  #### Full loading of an embedded entity
245
427
  ```ruby
246
- # Given a conversation with a partial user, load the full user. This can be
428
+ # Given a conversation with a partial contact, load the full contact. This can be
247
429
  # done for any entity
248
- intercom.users.load(conversation.user)
430
+ intercom.contacts.load(conversation.contacts.first)
249
431
  ```
250
432
 
251
433
  #### Sending messages
@@ -314,156 +496,148 @@ intercom.messages.create({
314
496
  })
315
497
  ```
316
498
 
317
- #### Events
499
+ #### Admins
318
500
  ```ruby
319
- intercom.events.create(
320
- event_name: "invited-friend",
321
- created_at: Time.now.to_i,
322
- email: user.email,
323
- metadata: {
324
- "invitee_email" => "pi@example.org",
325
- invite_code: "ADDAFRIEND",
326
- "found_date" => 12909364407
327
- }
328
- )
329
-
330
- # Retrieve event list for user with id:'123abc'
331
- intercom.events.find_all("type" => "user", "intercom_user_id" => "123abc")
501
+ # Find access token owner (only with Personal Access Token and OAuth)
502
+ intercom.admins.me
503
+ # Find an admin by id
504
+ intercom.admins.find(id: admin_id)
505
+ # Iterate over all admins
506
+ intercom.admins.all.each {|admin| puts admin.email }
507
+ ```
332
508
 
509
+ #### Teams
510
+ ```ruby
511
+ # Find a team by id
512
+ intercom.teams.find(id: team_id)
513
+ # Iterate over all teams
514
+ intercom.teams.all.each {|team| puts team.name }
333
515
  ```
334
516
 
335
- Metadata Objects support a few simple types that Intercom can present on your behalf
517
+ #### Counts
336
518
 
337
519
  ```ruby
338
- intercom.events.create(
339
- event_name: "placed-order",
340
- email: current_user.email,
341
- created_at: 1403001013,
342
- metadata: {
343
- order_date: Time.now.to_i,
344
- stripe_invoice: 'inv_3434343434',
345
- order_number: {
346
- value: '3434-3434',
347
- url: 'https://example.org/orders/3434-3434'
348
- },
349
- price: {
350
- currency: 'usd',
351
- amount: 2999
352
- }
353
- }
354
- )
520
+ # App-wide counts
521
+ intercom.counts.for_app
522
+
523
+ # Users in segment counts
524
+ intercom.counts.for_type(type: 'user', count: 'segment')
355
525
  ```
356
526
 
357
- The metadata key values in the example are treated as follows-
358
- - order_date: a Date (key ends with '_date')
359
- - stripe_invoice: The identifier of the Stripe invoice (has a 'stripe_invoice' key)
360
- - order_number: a Rich Link (value contains 'url' and 'value' keys)
361
- - price: An Amount in US Dollars (value contains 'amount' and 'currency' keys)
527
+ #### Subscriptions
362
528
 
363
- *NB:* This version of the gem reserves the field name `type` in Event data.
529
+ Subscribe to events in Intercom to receive webhooks.
364
530
 
365
- Bulk operations.
366
531
  ```ruby
367
- # Submit bulk job, to create events
368
- intercom.events.submit_bulk_job(create_items: [
369
- {
370
- event_name: "ordered-item",
371
- created_at: 1438944980,
372
- user_id: "314159",
373
- metadata: {
374
- order_date: 1438944980,
375
- stripe_invoice: "inv_3434343434"
376
- }
377
- },
378
- {
379
- event_name: "invited-friend",
380
- created_at: 1438944979,
381
- user_id: "314159",
382
- metadata: {
383
- invitee_email: "pi@example.org",
384
- invite_code: "ADDAFRIEND"
385
- }
386
- }
387
- ])
388
-
389
-
390
- # Submit bulk job, to add items to existing job
391
- intercom.events.submit_bulk_job(create_items: [
392
- {
393
- event_name: "ordered-item",
394
- created_at: 1438944980,
395
- user_id: "314159",
396
- metadata: {
397
- order_date: 1438944980,
398
- stripe_invoice: "inv_3434343434"
399
- }
400
- },
401
- {
402
- event_name: "invited-friend",
403
- created_at: 1438944979,
404
- user_id: "314159",
405
- metadata: {
406
- invitee_email: "pi@example.org",
407
- invite_code: "ADDAFRIEND"
408
- }
409
- }
410
- ], job_id:'job_abcd1234')
411
- ```
532
+ # create a subscription
533
+ intercom.subscriptions.create(url: "http://example.com", topics: ["user.created"])
534
+
535
+ # fetch a subscription
536
+ intercom.subscriptions.find(id: "nsub_123456789")
412
537
 
413
- ### Contacts
538
+ # delete a subscription
539
+ subscription = intercom.subscriptions.find(id: "nsub_123456789")
540
+ intercom.subscriptions.delete(subscription)
414
541
 
415
- `Contacts` represent logged out users of your application.
542
+ # list subscriptions
543
+ intercom.subscriptions.all
544
+ ```
416
545
 
546
+ #### Articles
417
547
  ```ruby
418
- # Create a contact
419
- contact = intercom.contacts.create(email: "some_contact@example.com")
548
+ # Create an article
549
+ article = intercom.articles.create(title: "New Article", author_id: "123456")
420
550
 
421
- # Update a contact
422
- contact.custom_attributes['foo'] = 'bar'
423
- intercom.contacts.save(contact)
551
+ # Create an article with translations
552
+ article = intercom.articles.create(title: "New Article",
553
+ author_id: "123456",
554
+ translated_content: {fr: {title: "Nouvel Article"}, es: {title: "Nuevo artículo"}})
424
555
 
425
- # Find contacts by email
426
- contacts = intercom.contacts.find_all(email: "some_contact@example.com")
556
+ # Fetch an article
557
+ intercom.articles.find(id: "123456")
427
558
 
428
- # Convert a contact into a user
429
- intercom.contacts.convert(contact, user)
559
+ # List all articles
560
+ articles = intercom.articles.all
561
+ articles.each { |article| p article.title }
430
562
 
431
- # Delete a contact
432
- intercom.contacts.delete(contact)
433
- ```
563
+ # Update an article
564
+ article.title = "Article Updated!"
565
+ intercom.articles.save(article)
434
566
 
435
- ### Counts
567
+ # Update an article's existing translation
568
+ article.translated_content.en.title = "English Updated!"
569
+ intercom.articles.save(article)
436
570
 
437
- ```ruby
438
- # App-wide counts
439
- intercom.counts.for_app
571
+ # Update an article by adding a new translation
572
+ article.translated_content.es = {title: "Artículo en español"}
573
+ intercom.articles.save(article)
440
574
 
441
- # Users in segment counts
442
- intercom.counts.for_type(type: 'user', count: 'segment')
575
+ # Delete an article
576
+ intercom.articles.delete(article)
443
577
  ```
444
578
 
445
- ### Subscriptions
579
+ #### Collections
580
+ ```ruby
581
+ # Create a collection
582
+ collection = intercom.collections.create(name: "New Collection")
446
583
 
447
- Subscribe to events in Intercom to receive webhooks.
584
+ # Create a collection with translations
585
+ collection = intercom.collections.create(name: "New Collection",
586
+ translated_content: {fr: {name: "Nouvelle collection"}, es: {name: "Nueva colección"}})
448
587
 
449
- ```ruby
450
- # create a subscription
451
- intercom.subscriptions.create(url: "http://example.com", topics: ["user.created"])
588
+ # Fetch a collection
589
+ intercom.collections.find(id: "123456")
452
590
 
453
- # fetch a subscription
454
- intercom.subscriptions.find(id: "nsub_123456789")
591
+ # List all collections
592
+ collections = intercom.collections.all
593
+ collections.each { |collection| p collection.name }
455
594
 
456
- # list subscriptions
457
- intercom.subscriptions.all
595
+ # Update a collection
596
+ collection.name = "Collection updated!"
597
+ intercom.collections.save(collection)
598
+
599
+ # Update a collection's existing translation
600
+ collection.translated_content.en.name = "English Updated!"
601
+ intercom.collections.save(collection)
602
+
603
+ # Update a collection by adding a new translation
604
+ collection.translated_content.es = {name: "Colección en español", description: "Descripción en español"}
605
+ intercom.collections.save(collection)
606
+
607
+ # Delete an collection
608
+ intercom.collections.delete(collection)
458
609
  ```
459
- ### Bulk jobs
460
610
 
611
+ #### Sections
461
612
  ```ruby
462
- # fetch a job
463
- intercom.jobs.find(id: 'job_abcd1234')
613
+ # Create a section
614
+ section = intercom.sections.create(name: "New Section", parent_id: "123456")
615
+
616
+ # Create a section with translations
617
+ section = intercom.sections.create(name: "New Section",
618
+ translated_content: {fr: {name: "Nouvelle section"}, es: {name: "Nueva sección"}})
619
+
620
+ # Fetch a section
621
+ intercom.sections.find(id: "123456")
464
622
 
465
- # fetch a job's error feed
466
- intercom.jobs.errors(id: 'job_abcd1234')
623
+ # List all sections
624
+ sections = intercom.sections.all
625
+ sections.each { |section| p section.name }
626
+
627
+ # Update a section
628
+ section.name = "Section updated!"
629
+ intercom.sections.save(section)
630
+
631
+ # Update a section's existing translation
632
+ section.translated_content.en.name = "English Updated!"
633
+ intercom.collections.save(section)
634
+
635
+ # Update a section by adding a new translation
636
+ section.translated_content.es = {name: "Sección en español"}
637
+ intercom.collections.save(section)
638
+
639
+ # Delete an section
640
+ intercom.sections.delete(section)
467
641
  ```
468
642
 
469
643
  ### Errors
@@ -480,6 +654,7 @@ Intercom::ServerError
480
654
  Intercom::ServiceUnavailableError
481
655
  Intercom::ServiceConnectionError
482
656
  Intercom::ResourceNotFound
657
+ Intercom::BlockedUserError
483
658
  Intercom::BadRequestError
484
659
  Intercom::RateLimitExceeded
485
660
  Intercom::AttributeNotSetError # Raised when you try to call a getter that does not exist on an object
@@ -496,6 +671,12 @@ intercom.rate_limit_details
496
671
  #=> {:limit=>180, :remaining=>179, :reset_at=>2014-10-07 14:58:00 +0100}
497
672
  ```
498
673
 
674
+ You can handle the rate limits yourself but a simple option is to use the handle_rate_limit flag.
675
+ This will automatically catch the 429 rate limit exceeded error and wait until the reset time to retry. After three retries a rate limit exception will be raised. Encountering this error frequently may require a revisiting of your usage of the API.
676
+
677
+ ```
678
+ intercom = Intercom::Client.new(token: ENV['AT'], handle_rate_limit: true)
679
+ ```
499
680
 
500
681
  ### Pull Requests
501
682
 
@@ -512,3 +693,24 @@ intercom.rate_limit_details
512
693
  - **Send coherent history**. Make sure each individual commit in your pull
513
694
  request is meaningful. If you had to make multiple intermediate commits while
514
695
  developing, please squash them before sending them to us.
696
+
697
+ ### Development
698
+
699
+ #### Running tests
700
+
701
+ ```bash
702
+ # all tests
703
+ bundle exec spec
704
+
705
+ # unit tests
706
+ bundle exec spec:unit
707
+
708
+ # integration tests
709
+ bundle exec spec:integration
710
+
711
+ # single test file
712
+ bundle exec m spec/unit/intercom/job_spec.rb
713
+
714
+ # single test
715
+ bundle exec m spec/unit/intercom/job_spec.rb:49
716
+ ```