posthubify 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +76 -0
- data/lib/posthubify/client.rb +138 -0
- data/lib/posthubify/errors.rb +21 -0
- data/lib/posthubify/http.rb +102 -0
- data/lib/posthubify/resources/accounts.rb +185 -0
- data/lib/posthubify/resources/ads.rb +226 -0
- data/lib/posthubify/resources/analytics.rb +170 -0
- data/lib/posthubify/resources/messaging.rb +882 -0
- data/lib/posthubify/resources/platform.rb +227 -0
- data/lib/posthubify/resources/posts.rb +102 -0
- data/lib/posthubify/resources/telecom.rb +86 -0
- data/lib/posthubify/version.rb +5 -0
- data/lib/posthubify.rb +16 -0
- metadata +57 -0
|
@@ -0,0 +1,882 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Posthubify
|
|
4
|
+
# Inbox — conversations + messages (Node sdk .inbox).
|
|
5
|
+
class InboxResource
|
|
6
|
+
def initialize(http)
|
|
7
|
+
@http = http
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Conversation list (paginated envelope; req → returns data+pagination together).
|
|
11
|
+
def conversations(platform: nil, account_id: nil, limit: nil, cursor: nil, sort_order: nil)
|
|
12
|
+
@http.req('GET', '/inbox/conversations', query: {
|
|
13
|
+
'platform' => platform, 'accountId' => account_id, 'limit' => limit,
|
|
14
|
+
'cursor' => cursor, 'sortOrder' => sort_order
|
|
15
|
+
})
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Messages in a conversation.
|
|
19
|
+
def messages(conversation_id)
|
|
20
|
+
@http.data('GET', "/inbox/conversations/#{conversation_id}/messages")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Send a message to a conversation.
|
|
24
|
+
def send_message(conversation_id, text)
|
|
25
|
+
@http.data('POST', "/inbox/conversations/#{conversation_id}/messages", body: { 'text' => text })
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Start a new conversation (recipientId = PSID/IGSID/convoId/handle).
|
|
29
|
+
def start_conversation(input)
|
|
30
|
+
@http.data('POST', '/inbox/conversations', body: input)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Comment management — list/reply/hide/like/delete (Node sdk .comments).
|
|
35
|
+
class CommentsResource
|
|
36
|
+
def initialize(http)
|
|
37
|
+
@http = http
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Comment list (paginated envelope).
|
|
41
|
+
def list(platform: nil, account_id: nil, limit: nil, cursor: nil)
|
|
42
|
+
@http.req('GET', '/inbox/comments', query: {
|
|
43
|
+
'platform' => platform, 'accountId' => account_id, 'limit' => limit, 'cursor' => cursor
|
|
44
|
+
})
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# A post's comments.
|
|
48
|
+
def for_post(post_id, account_id)
|
|
49
|
+
@http.data('GET', "/inbox/posts/#{post_id}/comments", query: { 'accountId' => account_id })
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Reply to a comment (text or media; the user provides camelCase keys).
|
|
53
|
+
def reply(comment_id, input)
|
|
54
|
+
@http.data('POST', "/inbox/comments/#{comment_id}/reply", body: input)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Private reply to a commenter (IG/FB) — opens a DM without requiring an open window.
|
|
58
|
+
def private_reply(comment_id, input)
|
|
59
|
+
@http.data('POST', "/inbox/comments/#{comment_id}/private-reply", body: input)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Write a top-level comment on a post.
|
|
63
|
+
def create_on_post(post_id, input)
|
|
64
|
+
@http.data('POST', "/inbox/posts/#{post_id}/comments", body: input)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Hide/show a comment.
|
|
68
|
+
def hide(comment_id, input)
|
|
69
|
+
@http.data('POST', "/inbox/comments/#{comment_id}/hide", body: input)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Like a comment.
|
|
73
|
+
def like(comment_id, input)
|
|
74
|
+
@http.data('POST', "/inbox/comments/#{comment_id}/like", body: input)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Delete a comment.
|
|
78
|
+
def delete(comment_id, account_id)
|
|
79
|
+
@http.data('DELETE', "/inbox/comments/#{comment_id}", query: { 'accountId' => account_id })
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Review management — list/reply/delete-reply (Node sdk .reviews).
|
|
84
|
+
class ReviewsResource
|
|
85
|
+
def initialize(http)
|
|
86
|
+
@http = http
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Review list (paginated envelope + summary).
|
|
90
|
+
def list(platform: nil, account_id: nil, min_rating: nil, max_rating: nil, limit: nil, cursor: nil)
|
|
91
|
+
@http.req('GET', '/reviews', query: {
|
|
92
|
+
'platform' => platform, 'accountId' => account_id, 'minRating' => min_rating,
|
|
93
|
+
'maxRating' => max_rating, 'limit' => limit, 'cursor' => cursor
|
|
94
|
+
})
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Delete a review reply.
|
|
98
|
+
def delete_reply(reply_id, account_id)
|
|
99
|
+
@http.data('DELETE', "/reviews/replies/#{reply_id}", query: { 'accountId' => account_id })
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Write a reply to a review.
|
|
103
|
+
def reply(context_id, input)
|
|
104
|
+
@http.data('POST', "/reviews/#{context_id}/reply", body: input)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Contact management — CRUD + channels + bulk import (Node sdk .contacts).
|
|
109
|
+
class ContactsResource
|
|
110
|
+
def initialize(http)
|
|
111
|
+
@http = http
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Contact list (paginated envelope).
|
|
115
|
+
def list(search: nil, tag: nil, limit: nil, cursor: nil)
|
|
116
|
+
@http.req('GET', '/contacts', query: {
|
|
117
|
+
'search' => search, 'tag' => tag, 'limit' => limit, 'cursor' => cursor
|
|
118
|
+
})
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# A single contact.
|
|
122
|
+
def get(id)
|
|
123
|
+
@http.data('GET', "/contacts/#{id}")
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Channel-first idempotent upsert: an existing contact is returned inside the envelope with 'existing' => true →
|
|
127
|
+
# unwrap the data envelope and merge the existing flag (mirrors Node async create).
|
|
128
|
+
def create(input)
|
|
129
|
+
r = @http.req('POST', '/contacts', body: input)
|
|
130
|
+
contact = r.is_a?(Hash) && r.key?('data') ? r['data'] : r
|
|
131
|
+
if r.is_a?(Hash) && r['existing'] && contact.is_a?(Hash)
|
|
132
|
+
contact.merge('existing' => true)
|
|
133
|
+
else
|
|
134
|
+
contact
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Update a contact (partial).
|
|
139
|
+
def update(id, input)
|
|
140
|
+
@http.data('PATCH', "/contacts/#{id}", body: input)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Delete a contact.
|
|
144
|
+
def delete(id)
|
|
145
|
+
@http.data('DELETE', "/contacts/#{id}")
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# A contact's channels.
|
|
149
|
+
def channels(id)
|
|
150
|
+
@http.data('GET', "/contacts/#{id}/channels")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Add a channel to a contact.
|
|
154
|
+
def add_channel(id, input)
|
|
155
|
+
@http.data('POST', "/contacts/#{id}/channels", body: input)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Bulk import (1-1000); channel-first upsert avoids piling up duplicates.
|
|
159
|
+
def bulk(contacts)
|
|
160
|
+
@http.data('POST', '/contacts/bulk', body: { 'contacts' => contacts })
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Automation management — CRUD + activate/pause/duplicate + runs + dry-test (Node sdk .automations).
|
|
165
|
+
class AutomationsResource
|
|
166
|
+
def initialize(http)
|
|
167
|
+
@http = http
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Automation list.
|
|
171
|
+
def list
|
|
172
|
+
@http.data('GET', '/automations')
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# A single automation.
|
|
176
|
+
def get(id)
|
|
177
|
+
@http.data('GET', "/automations/#{id}")
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Create an automation (trigger + action).
|
|
181
|
+
def create(input)
|
|
182
|
+
@http.data('POST', '/automations', body: input)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Update an automation (partial).
|
|
186
|
+
def update(id, input)
|
|
187
|
+
@http.data('PATCH', "/automations/#{id}", body: input)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Delete an automation.
|
|
191
|
+
def delete(id)
|
|
192
|
+
@http.data('DELETE', "/automations/#{id}")
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Activate an automation.
|
|
196
|
+
def activate(id)
|
|
197
|
+
@http.data('POST', "/automations/#{id}/activate")
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Pause an automation.
|
|
201
|
+
def pause(id)
|
|
202
|
+
@http.data('POST', "/automations/#{id}/pause")
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# The copy starts PAUSED (protection against accidental double-triggering).
|
|
206
|
+
def duplicate(id)
|
|
207
|
+
@http.data('POST', "/automations/#{id}/duplicate")
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Automation run records.
|
|
211
|
+
def runs(id, limit: nil)
|
|
212
|
+
@http.data('GET', "/automations/#{id}/runs", query: { 'limit' => limit })
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Dry-run: does a synthetic event match the trigger (nothing is sent).
|
|
216
|
+
def test(id, input = {})
|
|
217
|
+
@http.data('POST', "/automations/#{id}/test", body: input)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# PHASE D4 — IG/FB comment→DM automations (per-post/story, buttons, click-tracking).
|
|
222
|
+
class CommentAutomationsResource
|
|
223
|
+
def initialize(http)
|
|
224
|
+
@http = http
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# List comment-automations (filter: account_id/platform/enabled).
|
|
228
|
+
def list(account_id: nil, platform: nil, enabled: nil)
|
|
229
|
+
@http.data('GET', '/comment-automations',
|
|
230
|
+
query: { 'accountId' => account_id, 'platform' => platform, 'enabled' => enabled })
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# A single comment-automation (including funnel stats).
|
|
234
|
+
def get(id)
|
|
235
|
+
@http.data('GET', "/comment-automations/#{id}")
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Create a comment→DM automation. input: {name, platform, accountId, triggerType?, targeting?, ...}.
|
|
239
|
+
def create(input)
|
|
240
|
+
@http.data('POST', '/comment-automations', body: input)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Update a comment-automation (partial; platform/account cannot change).
|
|
244
|
+
def update(id, input)
|
|
245
|
+
@http.data('PATCH', "/comment-automations/#{id}", body: input)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Delete a comment-automation.
|
|
249
|
+
def delete(id)
|
|
250
|
+
@http.data('DELETE', "/comment-automations/#{id}")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Per-comment trigger audit ledger (paginated).
|
|
254
|
+
def logs(id, limit: nil, cursor: nil)
|
|
255
|
+
@http.req('GET', "/comment-automations/#{id}/logs", query: { 'limit' => limit, 'cursor' => cursor })
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# PHASE D5 — graph-based conversation automation (node/edge, versioning, run timeline).
|
|
260
|
+
class WorkflowsResource
|
|
261
|
+
def initialize(http)
|
|
262
|
+
@http = http
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def list(account_id: nil, status: nil)
|
|
266
|
+
@http.data('GET', '/workflows', query: { 'accountId' => account_id, 'status' => status })
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def get(id)
|
|
270
|
+
@http.data('GET', "/workflows/#{id}")
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# Draft workflow from a node/edge graph. input: {name, accountId, nodes?, edges?, triggerConfig?}.
|
|
274
|
+
def create(input)
|
|
275
|
+
@http.data('POST', '/workflows', body: input)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# F3 — generate a graph with AI from a natural-language command. create:true → a draft is saved (returns the workflow).
|
|
279
|
+
def generate(command, account_id, create: false)
|
|
280
|
+
@http.data('POST', '/workflows/generate', body: { 'command' => command, 'accountId' => account_id, 'create' => create })
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def update(id, input)
|
|
284
|
+
@http.data('PATCH', "/workflows/#{id}", body: input)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def delete(id)
|
|
288
|
+
@http.data('DELETE', "/workflows/#{id}")
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def activate(id)
|
|
292
|
+
@http.data('POST', "/workflows/#{id}/activate")
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def pause(id)
|
|
296
|
+
@http.data('POST', "/workflows/#{id}/pause")
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def duplicate(id)
|
|
300
|
+
@http.data('POST', "/workflows/#{id}/duplicate")
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def executions(id, limit: nil, cursor: nil)
|
|
304
|
+
@http.req('GET', "/workflows/#{id}/executions", query: { 'limit' => limit, 'cursor' => cursor })
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Manual test-run (side-effect-free dry-run). input: {message?, variables?}. → {execution, events}.
|
|
308
|
+
def run_test(id, input = {})
|
|
309
|
+
@http.data('POST', "/workflows/#{id}/executions", body: input)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def events(id, execution_id)
|
|
313
|
+
@http.data('GET', "/workflows/#{id}/executions/#{execution_id}/events")
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def versions(id)
|
|
317
|
+
@http.data('GET', "/workflows/#{id}/versions")
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def version(id, version)
|
|
321
|
+
@http.data('GET', "/workflows/#{id}/versions/#{version}")
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# Restore the live graph to a snapshot (reversible).
|
|
325
|
+
def restore_version(id, version)
|
|
326
|
+
@http.data('POST', "/workflows/#{id}/versions/#{version}/restore")
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Store a BYOK provider key for the ai node (write-only, encrypted).
|
|
330
|
+
# provider ∈ anthropic|openai|google|mistral|groq.
|
|
331
|
+
def set_secret(id, provider, api_key)
|
|
332
|
+
@http.data('PUT', "/workflows/#{id}/secrets/#{provider}", body: { 'apiKey' => api_key })
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# Broadcast — CRUD + send/schedule/cancel + recipients (Node sdk .broadcasts).
|
|
337
|
+
class BroadcastsResource
|
|
338
|
+
def initialize(http)
|
|
339
|
+
@http = http
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Broadcast list.
|
|
343
|
+
def list
|
|
344
|
+
@http.data('GET', '/broadcasts')
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# A single broadcast.
|
|
348
|
+
def get(id)
|
|
349
|
+
@http.data('GET', "/broadcasts/#{id}")
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Create a broadcast (safe retry with idempotency_key).
|
|
353
|
+
def create(input, idempotency_key: nil)
|
|
354
|
+
@http.data('POST', '/broadcasts', body: input, idempotency_key: idempotency_key)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Editable only in the draft/scheduled/failed stage.
|
|
358
|
+
def update(id, input)
|
|
359
|
+
@http.data('PATCH', "/broadcasts/#{id}", body: input)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Delete a broadcast.
|
|
363
|
+
def delete(id)
|
|
364
|
+
@http.data('DELETE', "/broadcasts/#{id}")
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# Asynchronous (202): sending happens in the background; poll progress with get(id).
|
|
368
|
+
def send(id)
|
|
369
|
+
@http.data('POST', "/broadcasts/#{id}/send")
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# draft → scheduled; when the time comes the server scheduler starts the send.
|
|
373
|
+
def schedule(id, scheduled_at)
|
|
374
|
+
@http.data('POST', "/broadcasts/#{id}/schedule", body: { 'scheduledAt' => scheduled_at })
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# scheduled → draft (content is preserved).
|
|
378
|
+
def cancel(id)
|
|
379
|
+
@http.data('POST', "/broadcasts/#{id}/cancel")
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# Recipients: contact name + per-target status (paginated envelope).
|
|
383
|
+
def recipients(id, limit: nil, cursor: nil)
|
|
384
|
+
@http.req('GET', "/broadcasts/#{id}/recipients", query: { 'limit' => limit, 'cursor' => cursor })
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# Add recipients (duplicates are skipped) — only draft/scheduled.
|
|
388
|
+
def add_recipients(id, contact_ids)
|
|
389
|
+
@http.data('POST', "/broadcasts/#{id}/recipients", body: { 'contactIds' => contact_ids })
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# Message sequence — CRUD + activate/pause + enroll/unenroll (Node sdk .sequences).
|
|
394
|
+
class SequencesResource
|
|
395
|
+
def initialize(http)
|
|
396
|
+
@http = http
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# Sequence list (paginated envelope).
|
|
400
|
+
def list(status: nil, limit: nil, cursor: nil)
|
|
401
|
+
@http.req('GET', '/sequences', query: { 'status' => status, 'limit' => limit, 'cursor' => cursor })
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# A single sequence.
|
|
405
|
+
def get(id)
|
|
406
|
+
@http.data('GET', "/sequences/#{id}")
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
# Create a sequence (steps + status/platform/account_id/exit_on_reply/exit_on_unsubscribe).
|
|
410
|
+
def create(input)
|
|
411
|
+
@http.data('POST', '/sequences', body: input)
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# Update a sequence (partial).
|
|
415
|
+
def update(id, input)
|
|
416
|
+
@http.data('PATCH', "/sequences/#{id}", body: input)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Delete a sequence.
|
|
420
|
+
def delete(id)
|
|
421
|
+
@http.data('DELETE', "/sequences/#{id}")
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
# Activate a sequence.
|
|
425
|
+
def activate(id)
|
|
426
|
+
@http.data('POST', "/sequences/#{id}/activate")
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Pause a sequence.
|
|
430
|
+
def pause(id)
|
|
431
|
+
@http.data('POST', "/sequences/#{id}/pause")
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
# Enroll contacts into a sequence.
|
|
435
|
+
def enroll(id, contact_ids)
|
|
436
|
+
@http.data('POST', "/sequences/#{id}/enroll", body: { 'contactIds' => contact_ids })
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
# Sequence enrollments.
|
|
440
|
+
def enrollments(id)
|
|
441
|
+
@http.data('GET', "/sequences/#{id}/enrollments")
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# Remove a contact from a sequence.
|
|
445
|
+
def unenroll(id, contact_id)
|
|
446
|
+
@http.data('POST', "/sequences/#{id}/unenroll", body: { 'contactId' => contact_id })
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
# Custom fields (D3) — definition CRUD + per-contact value (Node sdk .customFields).
|
|
450
|
+
class CustomFieldsResource
|
|
451
|
+
def initialize(http)
|
|
452
|
+
@http = http
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def list
|
|
456
|
+
@http.data('GET', '/custom-fields')
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def create(input)
|
|
460
|
+
@http.data('POST', '/custom-fields', body: input)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
def update(key, input)
|
|
464
|
+
@http.data('PATCH', "/custom-fields/#{key}", body: input)
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
def delete(key)
|
|
468
|
+
@http.data('DELETE', "/custom-fields/#{key}")
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
def values_for(contact_id)
|
|
472
|
+
@http.data('GET', "/contacts/#{contact_id}/fields")
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def set_value(contact_id, key, value)
|
|
476
|
+
@http.data('PUT', "/contacts/#{contact_id}/fields/#{key}", body: { 'value' => value })
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
def clear_value(contact_id, key)
|
|
480
|
+
@http.data('DELETE', "/contacts/#{contact_id}/fields/#{key}")
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
# WhatsApp Business — message templates (D1). account_id = the connected WhatsApp account.
|
|
485
|
+
# Only status=APPROVED templates can be sent; creation goes to Meta for approval (PENDING).
|
|
486
|
+
class WhatsAppResource
|
|
487
|
+
def initialize(http)
|
|
488
|
+
@http = http
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def list_templates(account_id, status: nil, limit: nil)
|
|
492
|
+
@http.data('GET', "/whatsapp/#{account_id}/templates",
|
|
493
|
+
query: { 'status' => status, 'limit' => limit })
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
def get_template(account_id, name)
|
|
497
|
+
@http.data('GET', "/whatsapp/#{account_id}/templates/#{name}")
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
def create_template(account_id, input)
|
|
501
|
+
@http.data('POST', "/whatsapp/#{account_id}/templates", body: input)
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
def edit_template(account_id, template_id, input)
|
|
505
|
+
@http.data('PATCH', "/whatsapp/#{account_id}/templates/#{template_id}", body: input)
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def delete_template(account_id, name, hsm_id: nil)
|
|
509
|
+
@http.data('DELETE', "/whatsapp/#{account_id}/templates/#{name}", query: { 'hsmId' => hsm_id })
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def send_template(account_id, input)
|
|
513
|
+
@http.data('POST', "/whatsapp/#{account_id}/template-messages", body: input)
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def get_profile(account_id)
|
|
517
|
+
@http.data('GET', "/whatsapp/#{account_id}/profile")
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
def update_profile(account_id, input)
|
|
521
|
+
@http.data('PATCH', "/whatsapp/#{account_id}/profile", body: input)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
def request_code(account_id, input)
|
|
525
|
+
@http.data('POST', "/whatsapp/#{account_id}/request-code", body: input)
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def verify_code(account_id, code)
|
|
529
|
+
@http.data('POST', "/whatsapp/#{account_id}/verify-code", body: { 'code' => code })
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def register(account_id, pin)
|
|
533
|
+
@http.data('POST', "/whatsapp/#{account_id}/register", body: { 'pin' => pin })
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
def set_two_step_pin(account_id, pin)
|
|
537
|
+
@http.data('POST', "/whatsapp/#{account_id}/two-step", body: { 'pin' => pin })
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def list_blocked(account_id, limit: nil)
|
|
541
|
+
@http.data('GET', "/whatsapp/#{account_id}/blocked", query: { 'limit' => limit })
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
def block(account_id, users)
|
|
545
|
+
@http.data('POST', "/whatsapp/#{account_id}/block", body: { 'users' => users })
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
def unblock(account_id, users)
|
|
549
|
+
@http.data('POST', "/whatsapp/#{account_id}/unblock", body: { 'users' => users })
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
# --- Flows (D1e) ---
|
|
553
|
+
def list_flows(account_id)
|
|
554
|
+
@http.data('GET', "/whatsapp/#{account_id}/flows")
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
def get_flow(account_id, flow_id)
|
|
558
|
+
@http.data('GET', "/whatsapp/#{account_id}/flows/#{flow_id}")
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
def create_flow(account_id, input)
|
|
562
|
+
@http.data('POST', "/whatsapp/#{account_id}/flows", body: input)
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def update_flow(account_id, flow_id, input)
|
|
566
|
+
@http.data('PATCH', "/whatsapp/#{account_id}/flows/#{flow_id}", body: input)
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def delete_flow(account_id, flow_id)
|
|
570
|
+
@http.data('DELETE', "/whatsapp/#{account_id}/flows/#{flow_id}")
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def upload_flow_json(account_id, flow_id, flow_json)
|
|
574
|
+
@http.data('PUT', "/whatsapp/#{account_id}/flows/#{flow_id}/json", body: { 'flowJson' => flow_json })
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
def publish_flow(account_id, flow_id)
|
|
578
|
+
@http.data('POST', "/whatsapp/#{account_id}/flows/#{flow_id}/publish")
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
def deprecate_flow(account_id, flow_id)
|
|
582
|
+
@http.data('POST', "/whatsapp/#{account_id}/flows/#{flow_id}/deprecate")
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
def get_flow_preview(account_id, flow_id, invalidate: nil)
|
|
586
|
+
@http.data('GET', "/whatsapp/#{account_id}/flows/#{flow_id}/preview",
|
|
587
|
+
query: { 'invalidate' => invalidate })
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
# --- Sandbox (D1f) — shared test number sessions ---
|
|
591
|
+
def sandbox_list_sessions
|
|
592
|
+
@http.data('GET', '/whatsapp/sandbox/sessions')
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def sandbox_create_session(phone)
|
|
596
|
+
@http.data('POST', '/whatsapp/sandbox/sessions', body: { 'phone' => phone })
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
def sandbox_revoke_session(session_id)
|
|
600
|
+
@http.data('DELETE', "/whatsapp/sandbox/sessions/#{session_id}")
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
# --- Calling (D1g) — voice calls ---
|
|
604
|
+
def calling_get_config(account_id)
|
|
605
|
+
@http.data('GET', '/whatsapp/calling', query: { 'accountId' => account_id })
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
def calling_enable(account_id, input)
|
|
609
|
+
@http.data('POST', "/whatsapp/phone-numbers/#{account_id}/calling", body: input)
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
def calling_update(account_id, input)
|
|
613
|
+
@http.data('PATCH', "/whatsapp/phone-numbers/#{account_id}/calling", body: input)
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
def calling_disable(account_id)
|
|
617
|
+
@http.data('DELETE', "/whatsapp/phone-numbers/#{account_id}/calling")
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
def call_permissions(account_id, to)
|
|
621
|
+
@http.data('GET', '/whatsapp/call-permissions', query: { 'accountId' => account_id, 'to' => to })
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def place_call(account_id, input)
|
|
625
|
+
@http.data('POST', '/whatsapp/calls', body: { 'accountId' => account_id }.merge(input))
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
def list_calls(account_id, limit: nil)
|
|
629
|
+
@http.data('GET', '/whatsapp/calls', query: { 'accountId' => account_id, 'limit' => limit })
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
def get_call(account_id, call_id)
|
|
633
|
+
@http.data('GET', "/whatsapp/calls/#{call_id}", query: { 'accountId' => account_id })
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
def estimate_call(to, recording: nil)
|
|
637
|
+
@http.data('GET', '/whatsapp/calls/estimate', query: { 'to' => to, 'recording' => recording })
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
# Google Business Profile (D2) — location + review. account_id = the connected GBP account.
|
|
642
|
+
class GmbResource
|
|
643
|
+
def initialize(http)
|
|
644
|
+
@http = http
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
def list_locations(account_id, page_token: nil)
|
|
648
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-locations", query: { 'pageToken' => page_token })
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
def switch_location(account_id, location_name)
|
|
652
|
+
@http.data('PUT', "/accounts/#{account_id}/gmb-locations", body: { 'locationName' => location_name })
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
def list_reviews(account_id, location_id: nil, page_token: nil)
|
|
656
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-reviews",
|
|
657
|
+
query: { 'locationId' => location_id, 'pageToken' => page_token })
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
def batch_reviews(account_id, location_names)
|
|
661
|
+
@http.data('POST', "/accounts/#{account_id}/gmb-reviews/batch",
|
|
662
|
+
body: { 'locationNames' => location_names })
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
def reply_review(account_id, review_id, comment, location_id: nil)
|
|
666
|
+
@http.data('POST', "/accounts/#{account_id}/gmb-reviews/#{review_id}/reply",
|
|
667
|
+
body: { 'comment' => comment }, query: { 'locationId' => location_id })
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
def delete_review_reply(account_id, review_id, location_id: nil)
|
|
671
|
+
@http.data('DELETE', "/accounts/#{account_id}/gmb-reviews/#{review_id}/reply",
|
|
672
|
+
query: { 'locationId' => location_id })
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
# ── Listing content (D2 cp3) ──
|
|
676
|
+
def get_location_details(account_id, location_id: nil, read_mask: nil)
|
|
677
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-location-details",
|
|
678
|
+
query: { 'locationId' => location_id, 'readMask' => read_mask })
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
def update_location_details(account_id, update_mask, patch, location_id: nil)
|
|
682
|
+
@http.data('PUT', "/accounts/#{account_id}/gmb-location-details",
|
|
683
|
+
body: { 'updateMask' => update_mask, 'patch' => patch },
|
|
684
|
+
query: { 'locationId' => location_id })
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
def get_attributes(account_id, location_id: nil)
|
|
688
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-attributes", query: { 'locationId' => location_id })
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
def update_attributes(account_id, attributes, attribute_mask, location_id: nil)
|
|
692
|
+
@http.data('PUT', "/accounts/#{account_id}/gmb-attributes",
|
|
693
|
+
body: { 'attributes' => attributes, 'attributeMask' => attribute_mask },
|
|
694
|
+
query: { 'locationId' => location_id })
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
def list_attribute_metadata(account_id, language_code:, location_id: nil, category_name: nil,
|
|
698
|
+
region_code: nil, page_size: nil, page_token: nil)
|
|
699
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-attribute-metadata",
|
|
700
|
+
query: { 'languageCode' => language_code, 'locationId' => location_id,
|
|
701
|
+
'categoryName' => category_name, 'regionCode' => region_code,
|
|
702
|
+
'pageSize' => page_size, 'pageToken' => page_token })
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
def get_services(account_id, location_id: nil)
|
|
706
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-services", query: { 'locationId' => location_id })
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
def update_services(account_id, service_items, location_id: nil)
|
|
710
|
+
@http.data('PUT', "/accounts/#{account_id}/gmb-services",
|
|
711
|
+
body: { 'serviceItems' => service_items }, query: { 'locationId' => location_id })
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
def get_food_menus(account_id, location_id: nil)
|
|
715
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-food-menus", query: { 'locationId' => location_id })
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
def update_food_menus(account_id, menus, update_mask: nil, location_id: nil)
|
|
719
|
+
@http.data('PUT', "/accounts/#{account_id}/gmb-food-menus",
|
|
720
|
+
body: { 'menus' => menus, 'updateMask' => update_mask },
|
|
721
|
+
query: { 'locationId' => location_id })
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
# ── Media (D2 cp3) ──
|
|
725
|
+
def list_media(account_id, location_id: nil, page_size: nil, page_token: nil)
|
|
726
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-media",
|
|
727
|
+
query: { 'locationId' => location_id, 'pageSize' => page_size, 'pageToken' => page_token })
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
def create_media(account_id, source_url, category, location_id: nil)
|
|
731
|
+
@http.data('POST', "/accounts/#{account_id}/gmb-media",
|
|
732
|
+
body: { 'sourceUrl' => source_url, 'category' => category },
|
|
733
|
+
query: { 'locationId' => location_id })
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
def delete_media(account_id, media_id, location_id: nil)
|
|
737
|
+
@http.data('DELETE', "/accounts/#{account_id}/gmb-media",
|
|
738
|
+
query: { 'mediaId' => media_id, 'locationId' => location_id })
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
# ── Place actions (D2 cp3) ──
|
|
742
|
+
def list_place_actions(account_id, location_id: nil, page_size: nil, page_token: nil)
|
|
743
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-place-actions",
|
|
744
|
+
query: { 'locationId' => location_id, 'pageSize' => page_size, 'pageToken' => page_token })
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
def create_place_action(account_id, uri, place_action_type, location_id: nil)
|
|
748
|
+
@http.data('POST', "/accounts/#{account_id}/gmb-place-actions",
|
|
749
|
+
body: { 'uri' => uri, 'placeActionType' => place_action_type },
|
|
750
|
+
query: { 'locationId' => location_id })
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
def update_place_action(account_id, name, uri: nil, place_action_type: nil, location_id: nil)
|
|
754
|
+
@http.data('PATCH', "/accounts/#{account_id}/gmb-place-actions",
|
|
755
|
+
body: { 'name' => name, 'uri' => uri, 'placeActionType' => place_action_type },
|
|
756
|
+
query: { 'locationId' => location_id })
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
def delete_place_action(account_id, name, location_id: nil)
|
|
760
|
+
@http.data('DELETE', "/accounts/#{account_id}/gmb-place-actions",
|
|
761
|
+
query: { 'name' => name, 'locationId' => location_id })
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
# ── Verification (D2 cp3) ──
|
|
765
|
+
def get_verifications(account_id, location_id: nil)
|
|
766
|
+
@http.data('GET', "/accounts/#{account_id}/gmb-verifications", query: { 'locationId' => location_id })
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
def start_verification(account_id, body, location_id: nil)
|
|
770
|
+
@http.data('POST', "/accounts/#{account_id}/gmb-verifications",
|
|
771
|
+
body: body, query: { 'locationId' => location_id })
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
def fetch_verification_options(account_id, language_code, context: nil, location_id: nil)
|
|
775
|
+
@http.data('POST', "/accounts/#{account_id}/gmb-verifications/options",
|
|
776
|
+
body: { 'languageCode' => language_code, 'context' => context },
|
|
777
|
+
query: { 'locationId' => location_id })
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
def complete_verification(account_id, verification_id, pin, location_id: nil)
|
|
781
|
+
@http.data('POST', "/accounts/#{account_id}/gmb-verifications/#{verification_id}/complete",
|
|
782
|
+
body: { 'pin' => pin }, query: { 'locationId' => location_id })
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
# Discord community-ops (D6) — role/member/event/pin/DM/settings. account_id scopes to the connected account.
|
|
787
|
+
class DiscordResource
|
|
788
|
+
def initialize(http)
|
|
789
|
+
@http = http
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
def list_roles(account_id, guild_id)
|
|
793
|
+
@http.data('GET', "/discord/guilds/#{guild_id}/roles", query: { 'accountId' => account_id })
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
def list_members(account_id, guild_id, limit: nil, after: nil)
|
|
797
|
+
@http.data('GET', "/discord/guilds/#{guild_id}/members",
|
|
798
|
+
query: { 'accountId' => account_id, 'limit' => limit, 'after' => after })
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
def assign_role(account_id, guild_id, user_id, role_id)
|
|
802
|
+
@http.data('PUT', "/discord/guilds/#{guild_id}/members/#{user_id}/roles/#{role_id}",
|
|
803
|
+
query: { 'accountId' => account_id })
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
def remove_role(account_id, guild_id, user_id, role_id)
|
|
807
|
+
@http.data('DELETE', "/discord/guilds/#{guild_id}/members/#{user_id}/roles/#{role_id}",
|
|
808
|
+
query: { 'accountId' => account_id })
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
def list_events(account_id, guild_id, with_user_count: nil)
|
|
812
|
+
@http.data('GET', "/discord/guilds/#{guild_id}/events",
|
|
813
|
+
query: { 'accountId' => account_id, 'withUserCount' => with_user_count })
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
def create_event(account_id, guild_id, body)
|
|
817
|
+
@http.data('POST', "/discord/guilds/#{guild_id}/events", query: { 'accountId' => account_id }, body: body)
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
def get_event(account_id, guild_id, event_id, with_user_count: nil)
|
|
821
|
+
@http.data('GET', "/discord/guilds/#{guild_id}/events/#{event_id}",
|
|
822
|
+
query: { 'accountId' => account_id, 'withUserCount' => with_user_count })
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
def update_event(account_id, guild_id, event_id, body)
|
|
826
|
+
@http.data('PATCH', "/discord/guilds/#{guild_id}/events/#{event_id}",
|
|
827
|
+
query: { 'accountId' => account_id }, body: body)
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
def delete_event(account_id, guild_id, event_id)
|
|
831
|
+
@http.data('DELETE', "/discord/guilds/#{guild_id}/events/#{event_id}", query: { 'accountId' => account_id })
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
def list_pins(account_id, channel_id)
|
|
835
|
+
@http.data('GET', "/discord/channels/#{channel_id}/pins", query: { 'accountId' => account_id })
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
def pin(account_id, channel_id, message_id)
|
|
839
|
+
@http.data('PUT', "/discord/channels/#{channel_id}/pins/#{message_id}", query: { 'accountId' => account_id })
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
def unpin(account_id, channel_id, message_id)
|
|
843
|
+
@http.data('DELETE', "/discord/channels/#{channel_id}/pins/#{message_id}", query: { 'accountId' => account_id })
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
def send_dm(body)
|
|
847
|
+
@http.data('POST', '/discord/dms', body: body)
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
def list_channels(account_id)
|
|
851
|
+
@http.data('GET', "/accounts/#{account_id}/discord-channels")
|
|
852
|
+
end
|
|
853
|
+
|
|
854
|
+
def get_settings(account_id)
|
|
855
|
+
@http.data('GET', "/accounts/#{account_id}/discord-settings")
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
def update_settings(account_id, patch)
|
|
859
|
+
@http.data('PATCH', "/accounts/#{account_id}/discord-settings", body: patch)
|
|
860
|
+
end
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
# Content discovery (D7) — read-only Reddit feed/search + LinkedIn mention via the connected account.
|
|
864
|
+
class DiscoveryResource
|
|
865
|
+
def initialize(http)
|
|
866
|
+
@http = http
|
|
867
|
+
end
|
|
868
|
+
|
|
869
|
+
def reddit_feed(account_id, subreddit, query = {})
|
|
870
|
+
@http.data('GET', '/reddit/feed', query: { 'accountId' => account_id, 'subreddit' => subreddit }.merge(query))
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
def reddit_search(account_id, q, query = {})
|
|
874
|
+
@http.data('GET', '/reddit/search', query: { 'accountId' => account_id, 'q' => q }.merge(query))
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
def linkedin_mentions(account_id, q)
|
|
878
|
+
@http.data('GET', "/accounts/#{account_id}/linkedin-mentions", query: { 'q' => q })
|
|
879
|
+
end
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
end
|