late-sdk 0.0.684 → 0.0.685

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -0
  3. data/docs/AccountsApi.md +76 -0
  4. data/docs/CommentAutomationAudience.md +22 -0
  5. data/docs/CommentAutomationFollowGate.md +22 -0
  6. data/docs/CommentAutomationsApi.md +1 -1
  7. data/docs/CreateCommentAutomation200ResponseAutomation.md +4 -0
  8. data/docs/CreateCommentAutomationRequest.md +5 -1
  9. data/docs/GetCommentAutomation200ResponseAutomation.md +4 -0
  10. data/docs/GetCommentAutomation200ResponseLogsInner.md +7 -1
  11. data/docs/GetInstagramFollowStatus200Response.md +34 -0
  12. data/docs/UpdateCommentAutomation200ResponseAutomation.md +4 -0
  13. data/docs/UpdateCommentAutomationRequest.md +4 -0
  14. data/docs/WebhookPayloadCommentCommentAuthor.md +3 -1
  15. data/docs/WebhookPayloadCommentCommentAuthorInstagramProfile.md +24 -0
  16. data/lib/zernio-sdk/api/accounts_api.rb +72 -0
  17. data/lib/zernio-sdk/api/comment_automations_api.rb +3 -3
  18. data/lib/zernio-sdk/models/comment_automation_audience.rb +237 -0
  19. data/lib/zernio-sdk/models/comment_automation_follow_gate.rb +226 -0
  20. data/lib/zernio-sdk/models/create_comment_automation200_response_automation.rb +19 -1
  21. data/lib/zernio-sdk/models/create_comment_automation_request.rb +22 -4
  22. data/lib/zernio-sdk/models/get_comment_automation200_response_automation.rb +19 -1
  23. data/lib/zernio-sdk/models/get_comment_automation200_response_logs_inner.rb +45 -4
  24. data/lib/zernio-sdk/models/get_instagram_follow_status200_response.rb +299 -0
  25. data/lib/zernio-sdk/models/update_comment_automation200_response_automation.rb +19 -1
  26. data/lib/zernio-sdk/models/update_comment_automation_request.rb +19 -1
  27. data/lib/zernio-sdk/models/webhook_payload_comment_comment_author.rb +14 -5
  28. data/lib/zernio-sdk/models/webhook_payload_comment_comment_author_instagram_profile.rb +181 -0
  29. data/lib/zernio-sdk/version.rb +1 -1
  30. data/lib/zernio-sdk.rb +4 -0
  31. data/openapi.yaml +162 -3
  32. data/spec/api/accounts_api_spec.rb +14 -0
  33. data/spec/api/comment_automations_api_spec.rb +1 -1
  34. data/spec/models/comment_automation_audience_spec.rb +56 -0
  35. data/spec/models/comment_automation_follow_gate_spec.rb +48 -0
  36. data/spec/models/create_comment_automation200_response_automation_spec.rb +12 -0
  37. data/spec/models/create_comment_automation_request_spec.rb +12 -0
  38. data/spec/models/get_comment_automation200_response_automation_spec.rb +12 -0
  39. data/spec/models/get_comment_automation200_response_logs_inner_spec.rb +23 -1
  40. data/spec/models/get_instagram_follow_status200_response_spec.rb +88 -0
  41. data/spec/models/update_comment_automation200_response_automation_spec.rb +12 -0
  42. data/spec/models/update_comment_automation_request_spec.rb +12 -0
  43. data/spec/models/webhook_payload_comment_comment_author_instagram_profile_spec.rb +54 -0
  44. data/spec/models/webhook_payload_comment_comment_author_spec.rb +6 -0
  45. data/zernio-sdk-0.0.685.gem +0 -0
  46. metadata +18 -2
  47. data/zernio-sdk-0.0.684.gem +0 -0
@@ -0,0 +1,181 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api
5
+
6
+ The version of the OpenAPI document: 1.0.4
7
+ Contact: support@zernio.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.19.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Zernio
17
+ # Instagram only, best-effort. Present ONLY for commenters who have messaged the account before: Meta gates the follow relationship behind messaging consent, and commenting does not grant it. Absent otherwise - treat a missing object as \"unknown\", never as \"not a follower\". To check on demand, call GET /v1/accounts/{accountId}/follow-status/{userId}.
18
+ class WebhookPayloadCommentCommentAuthorInstagramProfile < ApiModelBase
19
+ # The commenter follows this account.
20
+ attr_accessor :is_follower
21
+
22
+ # This account follows the commenter.
23
+ attr_accessor :is_following
24
+
25
+ attr_accessor :follower_count
26
+
27
+ attr_accessor :is_verified
28
+
29
+ # Attribute mapping from ruby-style variable name to JSON key.
30
+ def self.attribute_map
31
+ {
32
+ :'is_follower' => :'isFollower',
33
+ :'is_following' => :'isFollowing',
34
+ :'follower_count' => :'followerCount',
35
+ :'is_verified' => :'isVerified'
36
+ }
37
+ end
38
+
39
+ # Returns attribute mapping this model knows about
40
+ def self.acceptable_attribute_map
41
+ attribute_map
42
+ end
43
+
44
+ # Returns all the JSON keys this model knows about
45
+ def self.acceptable_attributes
46
+ acceptable_attribute_map.values
47
+ end
48
+
49
+ # Attribute type mapping.
50
+ def self.openapi_types
51
+ {
52
+ :'is_follower' => :'Boolean',
53
+ :'is_following' => :'Boolean',
54
+ :'follower_count' => :'Integer',
55
+ :'is_verified' => :'Boolean'
56
+ }
57
+ end
58
+
59
+ # List of attributes with nullable: true
60
+ def self.openapi_nullable
61
+ Set.new([
62
+ :'is_follower',
63
+ :'is_following',
64
+ :'follower_count',
65
+ :'is_verified'
66
+ ])
67
+ end
68
+
69
+ # Initializes the object
70
+ # @param [Hash] attributes Model attributes in the form of hash
71
+ def initialize(attributes = {})
72
+ if (!attributes.is_a?(Hash))
73
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::WebhookPayloadCommentCommentAuthorInstagramProfile` initialize method"
74
+ end
75
+
76
+ # check to see if the attribute exists and convert string to symbol for hash key
77
+ acceptable_attribute_map = self.class.acceptable_attribute_map
78
+ attributes = attributes.each_with_object({}) { |(k, v), h|
79
+ if (!acceptable_attribute_map.key?(k.to_sym))
80
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::WebhookPayloadCommentCommentAuthorInstagramProfile`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
81
+ end
82
+ h[k.to_sym] = v
83
+ }
84
+
85
+ if attributes.key?(:'is_follower')
86
+ self.is_follower = attributes[:'is_follower']
87
+ end
88
+
89
+ if attributes.key?(:'is_following')
90
+ self.is_following = attributes[:'is_following']
91
+ end
92
+
93
+ if attributes.key?(:'follower_count')
94
+ self.follower_count = attributes[:'follower_count']
95
+ end
96
+
97
+ if attributes.key?(:'is_verified')
98
+ self.is_verified = attributes[:'is_verified']
99
+ end
100
+ end
101
+
102
+ # Show invalid properties with the reasons. Usually used together with valid?
103
+ # @return Array for valid properties with the reasons
104
+ def list_invalid_properties
105
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
106
+ invalid_properties = Array.new
107
+ invalid_properties
108
+ end
109
+
110
+ # Check to see if the all the properties in the model are valid
111
+ # @return true if the model is valid
112
+ def valid?
113
+ warn '[DEPRECATED] the `valid?` method is obsolete'
114
+ true
115
+ end
116
+
117
+ # Checks equality by comparing each attribute.
118
+ # @param [Object] Object to be compared
119
+ def ==(o)
120
+ return true if self.equal?(o)
121
+ self.class == o.class &&
122
+ is_follower == o.is_follower &&
123
+ is_following == o.is_following &&
124
+ follower_count == o.follower_count &&
125
+ is_verified == o.is_verified
126
+ end
127
+
128
+ # @see the `==` method
129
+ # @param [Object] Object to be compared
130
+ def eql?(o)
131
+ self == o
132
+ end
133
+
134
+ # Calculates hash code according to all attributes.
135
+ # @return [Integer] Hash code
136
+ def hash
137
+ [is_follower, is_following, follower_count, is_verified].hash
138
+ end
139
+
140
+ # Builds the object from hash
141
+ # @param [Hash] attributes Model attributes in the form of hash
142
+ # @return [Object] Returns the model itself
143
+ def self.build_from_hash(attributes)
144
+ return nil unless attributes.is_a?(Hash)
145
+ attributes = attributes.transform_keys(&:to_sym)
146
+ transformed_hash = {}
147
+ openapi_types.each_pair do |key, type|
148
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
149
+ transformed_hash["#{key}"] = nil
150
+ elsif type =~ /\AArray<(.*)>/i
151
+ # check to ensure the input is an array given that the attribute
152
+ # is documented as an array but the input is not
153
+ if attributes[attribute_map[key]].is_a?(Array)
154
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
155
+ end
156
+ elsif !attributes[attribute_map[key]].nil?
157
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
158
+ end
159
+ end
160
+ new(transformed_hash)
161
+ end
162
+
163
+ # Returns the object in the form of hash
164
+ # @return [Hash] Returns the object in the form of hash
165
+ def to_hash
166
+ hash = {}
167
+ self.class.attribute_map.each_pair do |attr, param|
168
+ value = self.send(attr)
169
+ if value.nil?
170
+ is_nullable = self.class.openapi_nullable.include?(attr)
171
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
172
+ end
173
+
174
+ hash[param] = _to_hash(value)
175
+ end
176
+ hash
177
+ end
178
+
179
+ end
180
+
181
+ end
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.684'
14
+ VERSION = '0.0.685'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -132,6 +132,8 @@ require 'zernio-sdk/models/check_phone_number_portability200_response_results_in
132
132
  require 'zernio-sdk/models/check_phone_number_portability_request'
133
133
  require 'zernio-sdk/models/check_verification200_response'
134
134
  require 'zernio-sdk/models/check_verification_request'
135
+ require 'zernio-sdk/models/comment_automation_audience'
136
+ require 'zernio-sdk/models/comment_automation_follow_gate'
135
137
  require 'zernio-sdk/models/complete_google_business_verification_request'
136
138
  require 'zernio-sdk/models/complete_telegram_connect200_response'
137
139
  require 'zernio-sdk/models/complete_whats_app_phone_selection200_response'
@@ -590,6 +592,7 @@ require 'zernio-sdk/models/get_inbox_volume200_response_summary'
590
592
  require 'zernio-sdk/models/get_inbox_volume200_response_timeseries_inner'
591
593
  require 'zernio-sdk/models/get_inbox_volume400_response'
592
594
  require 'zernio-sdk/models/get_instagram_account_insights404_response'
595
+ require 'zernio-sdk/models/get_instagram_follow_status200_response'
593
596
  require 'zernio-sdk/models/get_instagram_publishing_limit200_response'
594
597
  require 'zernio-sdk/models/get_instagram_story_insights200_response'
595
598
  require 'zernio-sdk/models/get_instagram_story_insights200_response_data'
@@ -1514,6 +1517,7 @@ require 'zernio-sdk/models/webhook_payload_comment_comment'
1514
1517
  require 'zernio-sdk/models/webhook_payload_comment_comment_ad'
1515
1518
  require 'zernio-sdk/models/webhook_payload_comment_comment_attachment'
1516
1519
  require 'zernio-sdk/models/webhook_payload_comment_comment_author'
1520
+ require 'zernio-sdk/models/webhook_payload_comment_comment_author_instagram_profile'
1517
1521
  require 'zernio-sdk/models/webhook_payload_comment_post'
1518
1522
  require 'zernio-sdk/models/webhook_payload_conversation_started'
1519
1523
  require 'zernio-sdk/models/webhook_payload_conversation_started_conversation'
data/openapi.yaml CHANGED
@@ -1404,6 +1404,49 @@ components:
1404
1404
  type: object
1405
1405
  additionalProperties: true
1406
1406
  description: Additional structured context (e.g. field-level validation errors).
1407
+ CommentAutomationAudience:
1408
+ type: object
1409
+ description: |
1410
+ Who a comment automation answers. Instagram only - Meta exposes the follow
1411
+ relationship on no other platform, and only for people who have MESSAGED the
1412
+ account (a comment grants no consent). `whenUnknown` is therefore the important
1413
+ setting: it decides what happens for a first-time commenter.
1414
+ properties:
1415
+ followerStatus:
1416
+ type: string
1417
+ enum: [any, follower, non_follower]
1418
+ default: any
1419
+ minFollowerCount:
1420
+ type: integer
1421
+ minimum: 0
1422
+ description: 'Skip commenters with fewer followers than this. Omit for no size rule.'
1423
+ whenUnknown:
1424
+ type: string
1425
+ enum: [send, skip, verify]
1426
+ default: send
1427
+ description: |
1428
+ What to do when Instagram will not reveal the follow relationship.
1429
+ * `send` (default) - deliver the DM anyway (fails open).
1430
+ * `skip` - stay silent.
1431
+ * `verify` - send `followGate.message` with a confirm button. Tapping it is a
1432
+ message, which grants consent, so the re-check on the tap resolves and the
1433
+ real DM (or `followGate.notFollowingMessage`) follows automatically.
1434
+ CommentAutomationFollowGate:
1435
+ type: object
1436
+ description: 'Copy for the follow gate. Sensible defaults are used for any field left empty.'
1437
+ properties:
1438
+ message:
1439
+ type: string
1440
+ maxLength: 640
1441
+ description: 'Confirmation DM sent when whenUnknown=verify.'
1442
+ buttonLabel:
1443
+ type: string
1444
+ maxLength: 20
1445
+ description: 'Confirm button label. Defaults to "I''m following".'
1446
+ notFollowingMessage:
1447
+ type: string
1448
+ maxLength: 1000
1449
+ description: 'Sent to a commenter we know does not follow (followerStatus=follower). Omit to stay silent on a keyword comment; a confirm tap always gets an answer.'
1407
1450
  DmButton:
1408
1451
  type: object
1409
1452
  description: |
@@ -2670,6 +2713,25 @@ components:
2670
2713
  type: string
2671
2714
  picture:
2672
2715
  type: [string, "null"]
2716
+ instagramProfile:
2717
+ type: object
2718
+ description: |
2719
+ Instagram only, best-effort. Present ONLY for commenters who have
2720
+ messaged the account before: Meta gates the follow relationship behind
2721
+ messaging consent, and commenting does not grant it. Absent otherwise -
2722
+ treat a missing object as "unknown", never as "not a follower". To check
2723
+ on demand, call GET /v1/accounts/{accountId}/follow-status/{userId}.
2724
+ properties:
2725
+ isFollower:
2726
+ type: [boolean, "null"]
2727
+ description: The commenter follows this account.
2728
+ isFollowing:
2729
+ type: [boolean, "null"]
2730
+ description: This account follows the commenter.
2731
+ followerCount:
2732
+ type: [integer, "null"]
2733
+ isVerified:
2734
+ type: [boolean, "null"]
2673
2735
  createdAt:
2674
2736
  type: string
2675
2737
  format: date-time
@@ -15031,6 +15093,80 @@ paths:
15031
15093
  recommendations: []
15032
15094
  '401': { $ref: '#/components/responses/Unauthorized' }
15033
15095
  '404': { $ref: '#/components/responses/NotFound' }
15096
+ /v1/accounts/{accountId}/follow-status/{userId}:
15097
+ get:
15098
+ operationId: getInstagramFollowStatus
15099
+ tags: [Accounts]
15100
+ x-platforms: ["instagram"]
15101
+ summary: Check whether an Instagram user follows the account
15102
+ description: |
15103
+ Resolves the follow relationship between an Instagram user and the connected
15104
+ account, plus their public profile counters.
15105
+
15106
+ `userId` is the Instagram-scoped id (IGSID) Meta gives you on a webhook:
15107
+ `sender.id` on `message.received`, `comment.author.id` on `comment.received`.
15108
+
15109
+ **Meta only answers for people who have MESSAGED the account.** Commenting grants
15110
+ no consent, so a commenter who has never DMed you is unresolvable - that is a
15111
+ platform rule, not a limitation of this endpoint. When it cannot be resolved the
15112
+ response is still `200` with `isFollower: null` and an `unavailableReason`, because
15113
+ "unknown" is a normal state to branch on:
15114
+
15115
+ * `consent_required` - the user has never messaged this account.
15116
+ * `dm_access_disabled` - the account owner turned off Instagram Direct API access.
15117
+ * `not_messageable` - the id is not a messaging-scoped id.
15118
+ * `error` - a transient Graph API failure.
15119
+
15120
+ To gate a comment automation on this, use the automation's `audience` rules instead
15121
+ of calling this per comment - they run the same lookup only on comments that
15122
+ actually match a keyword, and can ask the commenter to confirm with one tap.
15123
+
15124
+ Answers are cached briefly per (account, user). Pass `refresh=true` right after
15125
+ asking someone to follow, so a follow from a moment ago is visible.
15126
+ security:
15127
+ - bearerAuth: []
15128
+ parameters:
15129
+ - { name: accountId, in: path, required: true, schema: { type: string }, description: Instagram account ID }
15130
+ - { name: userId, in: path, required: true, schema: { type: string }, description: 'Instagram-scoped user id (IGSID) from a webhook payload' }
15131
+ - { name: refresh, in: query, required: false, schema: { type: boolean }, description: Bypass the cache and re-query Meta }
15132
+ responses:
15133
+ '200':
15134
+ description: Follow status (fields are null when Meta would not resolve it)
15135
+ content:
15136
+ application/json:
15137
+ schema:
15138
+ type: object
15139
+ required: [userId, accountId, isFollower]
15140
+ properties:
15141
+ userId: { type: string }
15142
+ accountId: { type: string }
15143
+ isFollower:
15144
+ type: [boolean, "null"]
15145
+ description: 'The user follows this account. Null = unknown, never "no".'
15146
+ isFollowedByAccount:
15147
+ type: [boolean, "null"]
15148
+ description: This account follows the user.
15149
+ followerCount: { type: [integer, "null"] }
15150
+ isVerified: { type: [boolean, "null"] }
15151
+ username: { type: [string, "null"] }
15152
+ name: { type: [string, "null"] }
15153
+ unavailableReason:
15154
+ type: [string, "null"]
15155
+ enum: [consent_required, dm_access_disabled, not_messageable, error, null]
15156
+ description: 'Why the follow relationship could not be resolved. Null when it was.'
15157
+ example:
15158
+ userId: "1312733120229708"
15159
+ accountId: "6977a34e77637c5c857c816c"
15160
+ isFollower: true
15161
+ isFollowedByAccount: false
15162
+ followerCount: 25
15163
+ isVerified: false
15164
+ username: "to.bias8262"
15165
+ name: "Tobi Ma"
15166
+ unavailableReason: null
15167
+ '400': { $ref: '#/components/responses/BadRequest' }
15168
+ '401': { $ref: '#/components/responses/Unauthorized' }
15169
+ '404': { $ref: '#/components/responses/NotFound' }
15034
15170
  /v1/accounts/{accountId}/tiktok/creator-info:
15035
15171
  get:
15036
15172
  x-resource-group: "accounts"
@@ -35760,6 +35896,13 @@ paths:
35760
35896
  account-wide automations, each with its own keyword set, and they all run
35761
35897
  independently. Per-post automations take priority on their post.
35762
35898
 
35899
+ Audience (`audience`, Instagram only): restrict the automation to followers or
35900
+ non-followers, and/or to accounts above a follower count. Instagram only reveals the
35901
+ follow relationship for people who have messaged the account, so `audience.whenUnknown`
35902
+ decides what happens for everyone else - including `verify`, which sends a one-tap
35903
+ confirmation DM (`followGate`) and then delivers the real DM automatically. People we
35904
+ already know follow you skip the tap entirely.
35905
+
35763
35906
  Links in the DM's buttons can be click-tracked (`linkTracking`, on by default) and
35764
35907
  clickers optionally tagged (`clickTag`) for segmentation. Stats returned include
35765
35908
  delivered, read, and link clicks.
@@ -35806,6 +35949,8 @@ paths:
35806
35949
  description: "Optional alternate public replies, rotated at random alongside commentReply (picked independently of the DM). Up to 5."
35807
35950
  linkTracking: { type: boolean, default: true, description: "Wrap link buttons in the DM in a tracked redirect so clicks are counted (Link Clicks / CTR). Pass false to send links exactly as written. Defaults to on." }
35808
35951
  clickTag: { type: string, description: "Optional tag applied to a contact when they click a tracked link (requires linkTracking). Lets you segment clickers for broadcasts/sequences." }
35952
+ audience: { $ref: '#/components/schemas/CommentAutomationAudience' }
35953
+ followGate: { $ref: '#/components/schemas/CommentAutomationFollowGate' }
35809
35954
  responses:
35810
35955
  '200':
35811
35956
  description: Automation created
@@ -35837,6 +35982,8 @@ paths:
35837
35982
  commentReplyVariations: { type: array, items: { type: string }, description: "Alternate public replies rotated at random with commentReply. Omitted when none." }
35838
35983
  linkTracking: { type: boolean }
35839
35984
  clickTag: { type: string }
35985
+ audience: { $ref: '#/components/schemas/CommentAutomationAudience' }
35986
+ followGate: { $ref: '#/components/schemas/CommentAutomationFollowGate' }
35840
35987
  isActive: { type: boolean }
35841
35988
  stats: { type: object, properties: { totalTriggered: { type: integer }, totalSent: { type: integer }, totalFailed: { type: integer } } }
35842
35989
  createdAt: { type: string, format: date-time }
@@ -35889,6 +36036,8 @@ paths:
35889
36036
  commentReplyVariations: { type: array, items: { type: string }, description: "Alternate public replies rotated at random with commentReply. Omitted when none." }
35890
36037
  linkTracking: { type: boolean }
35891
36038
  clickTag: { type: string }
36039
+ audience: { $ref: '#/components/schemas/CommentAutomationAudience' }
36040
+ followGate: { $ref: '#/components/schemas/CommentAutomationFollowGate' }
35892
36041
  isActive: { type: boolean }
35893
36042
  stats: { type: object, properties: { totalTriggered: { type: integer }, totalSent: { type: integer }, totalFailed: { type: integer } } }
35894
36043
  createdAt: { type: string, format: date-time }
@@ -35903,7 +36052,10 @@ paths:
35903
36052
  commenterId: { type: string }
35904
36053
  commenterName: { type: string }
35905
36054
  commentText: { type: string }
35906
- status: { type: string, enum: [sent, failed, skipped], description: DM outcome }
36055
+ status: { type: string, enum: [sent, failed, skipped, gated], description: "DM outcome. 'gated' = the follow-gate confirmation DM went out and we are waiting for the tap; it flips to 'sent' or 'skipped' when they tap." }
36056
+ audienceOutcome: { type: string, enum: [passed, blocked, gate_sent, gate_passed, gate_failed], description: "How the audience rule resolved. Absent on automations without one." }
36057
+ commenterIsFollower: { type: boolean, description: "Follow relationship at decision time. Absent when Instagram would not tell us (the commenter never messaged the account)." }
36058
+ commenterFollowerCount: { type: integer }
35907
36059
  error: { type: string, description: DM error message if status is failed }
35908
36060
  commentReplyStatus: { type: string, enum: [sent, failed, skipped], description: "Outcome of the optional public reply on the triggering comment. 'skipped' if no commentReply was configured or if the DM failed (the public reply is not attempted in that case)." }
35909
36061
  commentReplyError: { type: string, description: Public-reply error message if commentReplyStatus is failed }
@@ -35954,6 +36106,8 @@ paths:
35954
36106
  description: "Alternate public replies for random rotation. Pass [] to clear."
35955
36107
  linkTracking: { type: boolean, description: "Wrap link buttons in a tracked redirect to count clicks. Pass false to send links untouched." }
35956
36108
  clickTag: { type: string, description: "Tag applied to a contact when they click a tracked link (requires linkTracking). Empty string clears it." }
36109
+ audience: { $ref: '#/components/schemas/CommentAutomationAudience' }
36110
+ followGate: { $ref: '#/components/schemas/CommentAutomationFollowGate' }
35957
36111
  isActive: { type: boolean }
35958
36112
  responses:
35959
36113
  '200':
@@ -35981,6 +36135,8 @@ paths:
35981
36135
  commentReply: { type: string }
35982
36136
  dmMessageVariations: { type: array, items: { type: string }, description: "Alternate DM texts rotated at random with dmMessage. Omitted when none." }
35983
36137
  commentReplyVariations: { type: array, items: { type: string }, description: "Alternate public replies rotated at random with commentReply. Omitted when none." }
36138
+ audience: { $ref: '#/components/schemas/CommentAutomationAudience' }
36139
+ followGate: { $ref: '#/components/schemas/CommentAutomationFollowGate' }
35984
36140
  isActive: { type: boolean }
35985
36141
  updatedAt: { type: string, format: date-time }
35986
36142
  '401': { $ref: '#/components/responses/Unauthorized' }
@@ -36011,7 +36167,7 @@ paths:
36011
36167
  - bearerAuth: []
36012
36168
  parameters:
36013
36169
  - { name: automationId, in: path, required: true, schema: { type: string } }
36014
- - { name: status, in: query, schema: { type: string, enum: [sent, failed, skipped] }, description: Filter by result status }
36170
+ - { name: status, in: query, schema: { type: string, enum: [sent, failed, skipped, gated] }, description: Filter by result status }
36015
36171
  - { name: limit, in: query, schema: { type: integer, default: 50, minimum: 1, maximum: 200 } }
36016
36172
  - { name: skip, in: query, schema: { type: integer, default: 0, minimum: 0 } }
36017
36173
  responses:
@@ -36033,7 +36189,10 @@ paths:
36033
36189
  commenterId: { type: string }
36034
36190
  commenterName: { type: string }
36035
36191
  commentText: { type: string }
36036
- status: { type: string, enum: [sent, failed, skipped], description: DM outcome }
36192
+ status: { type: string, enum: [sent, failed, skipped, gated], description: "DM outcome. 'gated' = the follow-gate confirmation DM went out and we are waiting for the tap; it flips to 'sent' or 'skipped' when they tap." }
36193
+ audienceOutcome: { type: string, enum: [passed, blocked, gate_sent, gate_passed, gate_failed], description: "How the audience rule resolved. Absent on automations without one." }
36194
+ commenterIsFollower: { type: boolean, description: "Follow relationship at decision time. Absent when Instagram would not tell us (the commenter never messaged the account)." }
36195
+ commenterFollowerCount: { type: integer }
36037
36196
  error: { type: string, description: DM error message if status is failed }
36038
36197
  commentReplyStatus: { type: string, enum: [sent, failed, skipped], description: "Outcome of the optional public reply on the triggering comment. 'skipped' if no commentReply was configured or if the DM failed (the public reply is not attempted in that case)." }
36039
36198
  commentReplyError: { type: string, description: Public-reply error message if commentReplyStatus is failed }
@@ -86,6 +86,20 @@ describe 'AccountsApi' do
86
86
  end
87
87
  end
88
88
 
89
+ # unit tests for get_instagram_follow_status
90
+ # Check whether an Instagram user follows the account
91
+ # Resolves the follow relationship between an Instagram user and the connected account, plus their public profile counters. &#x60;userId&#x60; is the Instagram-scoped id (IGSID) Meta gives you on a webhook: &#x60;sender.id&#x60; on &#x60;message.received&#x60;, &#x60;comment.author.id&#x60; on &#x60;comment.received&#x60;. **Meta only answers for people who have MESSAGED the account.** Commenting grants no consent, so a commenter who has never DMed you is unresolvable - that is a platform rule, not a limitation of this endpoint. When it cannot be resolved the response is still &#x60;200&#x60; with &#x60;isFollower: null&#x60; and an &#x60;unavailableReason&#x60;, because \&quot;unknown\&quot; is a normal state to branch on: * &#x60;consent_required&#x60; - the user has never messaged this account. * &#x60;dm_access_disabled&#x60; - the account owner turned off Instagram Direct API access. * &#x60;not_messageable&#x60; - the id is not a messaging-scoped id. * &#x60;error&#x60; - a transient Graph API failure. To gate a comment automation on this, use the automation&#39;s &#x60;audience&#x60; rules instead of calling this per comment - they run the same lookup only on comments that actually match a keyword, and can ask the commenter to confirm with one tap. Answers are cached briefly per (account, user). Pass &#x60;refresh&#x3D;true&#x60; right after asking someone to follow, so a follow from a moment ago is visible.
92
+ # @param account_id Instagram account ID
93
+ # @param user_id Instagram-scoped user id (IGSID) from a webhook payload
94
+ # @param [Hash] opts the optional parameters
95
+ # @option opts [Boolean] :refresh Bypass the cache and re-query Meta
96
+ # @return [GetInstagramFollowStatus200Response]
97
+ describe 'get_instagram_follow_status test' do
98
+ it 'should work' do
99
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
100
+ end
101
+ end
102
+
89
103
  # unit tests for get_slack_settings
90
104
  # Get Slack account settings
91
105
  # Returns the connected Slack channel details and the default message identity (name and avatar shown as the author on every post, with Slack&#39;s APP badge). The identity applies to messages only; the app&#39;s own Slack profile is global and cannot be changed per workspace.
@@ -34,7 +34,7 @@ describe 'CommentAutomationsApi' do
34
34
 
35
35
  # unit tests for create_comment_automation
36
36
  # Create comment-to-DM automation
37
- # Create a keyword-triggered DM automation on an Instagram or Facebook account. When someone comments a matching keyword (or, with &#x60;trigger: story_reply&#x60;, replies to your Instagram story with one), they automatically receive a DM. Triggers (&#x60;trigger&#x60;): * &#x60;comment&#x60; (default): fires on keyword comments on a post or reel. * &#x60;story_reply&#x60;: fires when someone replies to your Instagram story with a keyword, and answers them with a DM. Set &#x60;platformPostId&#x60; to a story media id to scope to one story, or omit it to match replies to any story. Targeting (comment trigger): * Per-post: set &#x60;platformPostId&#x60; to scope to one specific post (only one active per-post automation is allowed per post). * Account-wide (\&quot;any post\&quot;): omit &#x60;platformPostId&#x60; (and &#x60;postId&#x60;). The automation evaluates every comment on every post on the account. You can stack unlimited account-wide automations, each with its own keyword set, and they all run independently. Per-post automations take priority on their post. Links in the DM&#39;s buttons can be click-tracked (&#x60;linkTracking&#x60;, on by default) and clickers optionally tagged (&#x60;clickTag&#x60;) for segmentation. Stats returned include delivered, read, and link clicks.
37
+ # Create a keyword-triggered DM automation on an Instagram or Facebook account. When someone comments a matching keyword (or, with &#x60;trigger: story_reply&#x60;, replies to your Instagram story with one), they automatically receive a DM. Triggers (&#x60;trigger&#x60;): * &#x60;comment&#x60; (default): fires on keyword comments on a post or reel. * &#x60;story_reply&#x60;: fires when someone replies to your Instagram story with a keyword, and answers them with a DM. Set &#x60;platformPostId&#x60; to a story media id to scope to one story, or omit it to match replies to any story. Targeting (comment trigger): * Per-post: set &#x60;platformPostId&#x60; to scope to one specific post (only one active per-post automation is allowed per post). * Account-wide (\&quot;any post\&quot;): omit &#x60;platformPostId&#x60; (and &#x60;postId&#x60;). The automation evaluates every comment on every post on the account. You can stack unlimited account-wide automations, each with its own keyword set, and they all run independently. Per-post automations take priority on their post. Audience (&#x60;audience&#x60;, Instagram only): restrict the automation to followers or non-followers, and/or to accounts above a follower count. Instagram only reveals the follow relationship for people who have messaged the account, so &#x60;audience.whenUnknown&#x60; decides what happens for everyone else - including &#x60;verify&#x60;, which sends a one-tap confirmation DM (&#x60;followGate&#x60;) and then delivers the real DM automatically. People we already know follow you skip the tap entirely. Links in the DM&#39;s buttons can be click-tracked (&#x60;linkTracking&#x60;, on by default) and clickers optionally tagged (&#x60;clickTag&#x60;) for segmentation. Stats returned include delivered, read, and link clicks.
38
38
  # @param create_comment_automation_request
39
39
  # @param [Hash] opts the optional parameters
40
40
  # @return [CreateCommentAutomation200Response]
@@ -0,0 +1,56 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api
5
+
6
+ The version of the OpenAPI document: 1.0.4
7
+ Contact: support@zernio.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.19.0
10
+
11
+ =end
12
+
13
+ require 'spec_helper'
14
+ require 'json'
15
+ require 'date'
16
+
17
+ # Unit tests for Zernio::CommentAutomationAudience
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::CommentAutomationAudience do
21
+ #let(:instance) { Zernio::CommentAutomationAudience.new }
22
+
23
+ describe 'test an instance of CommentAutomationAudience' do
24
+ it 'should create an instance of CommentAutomationAudience' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::CommentAutomationAudience)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "follower_status"' do
31
+ it 'should work' do
32
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["any", "follower", "non_follower"])
34
+ # validator.allowable_values.each do |value|
35
+ # expect { instance.follower_status = value }.not_to raise_error
36
+ # end
37
+ end
38
+ end
39
+
40
+ describe 'test attribute "min_follower_count"' do
41
+ it 'should work' do
42
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
43
+ end
44
+ end
45
+
46
+ describe 'test attribute "when_unknown"' do
47
+ it 'should work' do
48
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
49
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["send", "skip", "verify"])
50
+ # validator.allowable_values.each do |value|
51
+ # expect { instance.when_unknown = value }.not_to raise_error
52
+ # end
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,48 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api
5
+
6
+ The version of the OpenAPI document: 1.0.4
7
+ Contact: support@zernio.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.19.0
10
+
11
+ =end
12
+
13
+ require 'spec_helper'
14
+ require 'json'
15
+ require 'date'
16
+
17
+ # Unit tests for Zernio::CommentAutomationFollowGate
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::CommentAutomationFollowGate do
21
+ #let(:instance) { Zernio::CommentAutomationFollowGate.new }
22
+
23
+ describe 'test an instance of CommentAutomationFollowGate' do
24
+ it 'should create an instance of CommentAutomationFollowGate' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::CommentAutomationFollowGate)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "message"' do
31
+ it 'should work' do
32
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
+ end
34
+ end
35
+
36
+ describe 'test attribute "button_label"' do
37
+ it 'should work' do
38
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
+ end
40
+ end
41
+
42
+ describe 'test attribute "not_following_message"' do
43
+ it 'should work' do
44
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
45
+ end
46
+ end
47
+
48
+ end
@@ -131,6 +131,18 @@ describe Zernio::CreateCommentAutomation200ResponseAutomation do
131
131
  end
132
132
  end
133
133
 
134
+ describe 'test attribute "audience"' do
135
+ it 'should work' do
136
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
137
+ end
138
+ end
139
+
140
+ describe 'test attribute "follow_gate"' do
141
+ it 'should work' do
142
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
143
+ end
144
+ end
145
+
134
146
  describe 'test attribute "is_active"' do
135
147
  it 'should work' do
136
148
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
@@ -143,4 +143,16 @@ describe Zernio::CreateCommentAutomationRequest do
143
143
  end
144
144
  end
145
145
 
146
+ describe 'test attribute "audience"' do
147
+ it 'should work' do
148
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
149
+ end
150
+ end
151
+
152
+ describe 'test attribute "follow_gate"' do
153
+ it 'should work' do
154
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
155
+ end
156
+ end
157
+
146
158
  end
@@ -149,6 +149,18 @@ describe Zernio::GetCommentAutomation200ResponseAutomation do
149
149
  end
150
150
  end
151
151
 
152
+ describe 'test attribute "audience"' do
153
+ it 'should work' do
154
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
155
+ end
156
+ end
157
+
158
+ describe 'test attribute "follow_gate"' do
159
+ it 'should work' do
160
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
161
+ end
162
+ end
163
+
152
164
  describe 'test attribute "is_active"' do
153
165
  it 'should work' do
154
166
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/