late-sdk 0.0.710 → 0.0.712

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/docs/AdDailyMetrics.md +10 -10
  4. data/docs/AdMetrics.md +10 -10
  5. data/docs/GetCampaignAnalytics200ResponseAnalyticsDailyInner.md +10 -10
  6. data/docs/GetInstagramAudio200Response.md +18 -0
  7. data/docs/InstagramApi.md +148 -0
  8. data/docs/InstagramAudioAsset.md +38 -0
  9. data/docs/InstagramPlatformData.md +3 -1
  10. data/docs/InstagramPlatformDataAudioConfiguration.md +22 -0
  11. data/docs/SearchInstagramAudio200Response.md +18 -0
  12. data/lib/zernio-sdk/api/instagram_api.rb +160 -0
  13. data/lib/zernio-sdk/models/ad_daily_metrics.rb +10 -10
  14. data/lib/zernio-sdk/models/ad_metrics.rb +10 -10
  15. data/lib/zernio-sdk/models/get_campaign_analytics200_response_analytics_daily_inner.rb +10 -10
  16. data/lib/zernio-sdk/models/get_instagram_audio200_response.rb +147 -0
  17. data/lib/zernio-sdk/models/instagram_audio_asset.rb +293 -0
  18. data/lib/zernio-sdk/models/instagram_platform_data.rb +11 -2
  19. data/lib/zernio-sdk/models/instagram_platform_data_audio_configuration.rb +242 -0
  20. data/lib/zernio-sdk/models/search_instagram_audio200_response.rb +149 -0
  21. data/lib/zernio-sdk/version.rb +1 -1
  22. data/lib/zernio-sdk.rb +4 -0
  23. data/openapi.yaml +141 -11
  24. data/spec/api/instagram_api_spec.rb +27 -0
  25. data/spec/models/get_instagram_audio200_response_spec.rb +36 -0
  26. data/spec/models/instagram_audio_asset_spec.rb +100 -0
  27. data/spec/models/instagram_platform_data_audio_configuration_spec.rb +48 -0
  28. data/spec/models/instagram_platform_data_spec.rb +6 -0
  29. data/spec/models/search_instagram_audio200_response_spec.rb +36 -0
  30. data/zernio-sdk-0.0.712.gem +0 -0
  31. metadata +19 -3
  32. data/zernio-sdk-0.0.710.gem +0 -0
@@ -0,0 +1,242 @@
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
+ # Attach a licensed music track or original sound from the Instagram audio catalog to a Reel. Reels only (single video post, not a story or image). Requires an Instagram account connected via Facebook Login; classic Instagram Login accounts get a 400 (instagram_audio_requires_facebook_login). Get audio IDs from GET /v1/accounts/{accountId}/instagram/audio. If the track becomes unavailable by publish time (removed, region-blocked, licensing change), the post fails with a user-error; it is not published without the audio.
18
+ class InstagramPlatformDataAudioConfiguration < ApiModelBase
19
+ # Audio asset ID from the audio search endpoint.
20
+ attr_accessor :audio_id
21
+
22
+ # Volume of the attached audio track, 0-100. Defaults to 100.
23
+ attr_accessor :audio_volume
24
+
25
+ # Volume of the video's own sound, 0-100. Defaults to 100. Set 0 to mute the original video audio.
26
+ attr_accessor :video_volume
27
+
28
+ # Attribute mapping from ruby-style variable name to JSON key.
29
+ def self.attribute_map
30
+ {
31
+ :'audio_id' => :'audioId',
32
+ :'audio_volume' => :'audioVolume',
33
+ :'video_volume' => :'videoVolume'
34
+ }
35
+ end
36
+
37
+ # Returns attribute mapping this model knows about
38
+ def self.acceptable_attribute_map
39
+ attribute_map
40
+ end
41
+
42
+ # Returns all the JSON keys this model knows about
43
+ def self.acceptable_attributes
44
+ acceptable_attribute_map.values
45
+ end
46
+
47
+ # Attribute type mapping.
48
+ def self.openapi_types
49
+ {
50
+ :'audio_id' => :'String',
51
+ :'audio_volume' => :'Integer',
52
+ :'video_volume' => :'Integer'
53
+ }
54
+ end
55
+
56
+ # List of attributes with nullable: true
57
+ def self.openapi_nullable
58
+ Set.new([
59
+ ])
60
+ end
61
+
62
+ # Initializes the object
63
+ # @param [Hash] attributes Model attributes in the form of hash
64
+ def initialize(attributes = {})
65
+ if (!attributes.is_a?(Hash))
66
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::InstagramPlatformDataAudioConfiguration` initialize method"
67
+ end
68
+
69
+ # check to see if the attribute exists and convert string to symbol for hash key
70
+ acceptable_attribute_map = self.class.acceptable_attribute_map
71
+ attributes = attributes.each_with_object({}) { |(k, v), h|
72
+ if (!acceptable_attribute_map.key?(k.to_sym))
73
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::InstagramPlatformDataAudioConfiguration`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
74
+ end
75
+ h[k.to_sym] = v
76
+ }
77
+
78
+ if attributes.key?(:'audio_id')
79
+ self.audio_id = attributes[:'audio_id']
80
+ else
81
+ self.audio_id = nil
82
+ end
83
+
84
+ if attributes.key?(:'audio_volume')
85
+ self.audio_volume = attributes[:'audio_volume']
86
+ end
87
+
88
+ if attributes.key?(:'video_volume')
89
+ self.video_volume = attributes[:'video_volume']
90
+ end
91
+ end
92
+
93
+ # Show invalid properties with the reasons. Usually used together with valid?
94
+ # @return Array for valid properties with the reasons
95
+ def list_invalid_properties
96
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
97
+ invalid_properties = Array.new
98
+ if @audio_id.nil?
99
+ invalid_properties.push('invalid value for "audio_id", audio_id cannot be nil.')
100
+ end
101
+
102
+ if !@audio_volume.nil? && @audio_volume > 100
103
+ invalid_properties.push('invalid value for "audio_volume", must be smaller than or equal to 100.')
104
+ end
105
+
106
+ if !@audio_volume.nil? && @audio_volume < 0
107
+ invalid_properties.push('invalid value for "audio_volume", must be greater than or equal to 0.')
108
+ end
109
+
110
+ if !@video_volume.nil? && @video_volume > 100
111
+ invalid_properties.push('invalid value for "video_volume", must be smaller than or equal to 100.')
112
+ end
113
+
114
+ if !@video_volume.nil? && @video_volume < 0
115
+ invalid_properties.push('invalid value for "video_volume", must be greater than or equal to 0.')
116
+ end
117
+
118
+ invalid_properties
119
+ end
120
+
121
+ # Check to see if the all the properties in the model are valid
122
+ # @return true if the model is valid
123
+ def valid?
124
+ warn '[DEPRECATED] the `valid?` method is obsolete'
125
+ return false if @audio_id.nil?
126
+ return false if !@audio_volume.nil? && @audio_volume > 100
127
+ return false if !@audio_volume.nil? && @audio_volume < 0
128
+ return false if !@video_volume.nil? && @video_volume > 100
129
+ return false if !@video_volume.nil? && @video_volume < 0
130
+ true
131
+ end
132
+
133
+ # Custom attribute writer method with validation
134
+ # @param [Object] audio_id Value to be assigned
135
+ def audio_id=(audio_id)
136
+ if audio_id.nil?
137
+ fail ArgumentError, 'audio_id cannot be nil'
138
+ end
139
+
140
+ @audio_id = audio_id
141
+ end
142
+
143
+ # Custom attribute writer method with validation
144
+ # @param [Object] audio_volume Value to be assigned
145
+ def audio_volume=(audio_volume)
146
+ if audio_volume.nil?
147
+ fail ArgumentError, 'audio_volume cannot be nil'
148
+ end
149
+
150
+ if audio_volume > 100
151
+ fail ArgumentError, 'invalid value for "audio_volume", must be smaller than or equal to 100.'
152
+ end
153
+
154
+ if audio_volume < 0
155
+ fail ArgumentError, 'invalid value for "audio_volume", must be greater than or equal to 0.'
156
+ end
157
+
158
+ @audio_volume = audio_volume
159
+ end
160
+
161
+ # Custom attribute writer method with validation
162
+ # @param [Object] video_volume Value to be assigned
163
+ def video_volume=(video_volume)
164
+ if video_volume.nil?
165
+ fail ArgumentError, 'video_volume cannot be nil'
166
+ end
167
+
168
+ if video_volume > 100
169
+ fail ArgumentError, 'invalid value for "video_volume", must be smaller than or equal to 100.'
170
+ end
171
+
172
+ if video_volume < 0
173
+ fail ArgumentError, 'invalid value for "video_volume", must be greater than or equal to 0.'
174
+ end
175
+
176
+ @video_volume = video_volume
177
+ end
178
+
179
+ # Checks equality by comparing each attribute.
180
+ # @param [Object] Object to be compared
181
+ def ==(o)
182
+ return true if self.equal?(o)
183
+ self.class == o.class &&
184
+ audio_id == o.audio_id &&
185
+ audio_volume == o.audio_volume &&
186
+ video_volume == o.video_volume
187
+ end
188
+
189
+ # @see the `==` method
190
+ # @param [Object] Object to be compared
191
+ def eql?(o)
192
+ self == o
193
+ end
194
+
195
+ # Calculates hash code according to all attributes.
196
+ # @return [Integer] Hash code
197
+ def hash
198
+ [audio_id, audio_volume, video_volume].hash
199
+ end
200
+
201
+ # Builds the object from hash
202
+ # @param [Hash] attributes Model attributes in the form of hash
203
+ # @return [Object] Returns the model itself
204
+ def self.build_from_hash(attributes)
205
+ return nil unless attributes.is_a?(Hash)
206
+ attributes = attributes.transform_keys(&:to_sym)
207
+ transformed_hash = {}
208
+ openapi_types.each_pair do |key, type|
209
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
210
+ transformed_hash["#{key}"] = nil
211
+ elsif type =~ /\AArray<(.*)>/i
212
+ # check to ensure the input is an array given that the attribute
213
+ # is documented as an array but the input is not
214
+ if attributes[attribute_map[key]].is_a?(Array)
215
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
216
+ end
217
+ elsif !attributes[attribute_map[key]].nil?
218
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
219
+ end
220
+ end
221
+ new(transformed_hash)
222
+ end
223
+
224
+ # Returns the object in the form of hash
225
+ # @return [Hash] Returns the object in the form of hash
226
+ def to_hash
227
+ hash = {}
228
+ self.class.attribute_map.each_pair do |attr, param|
229
+ value = self.send(attr)
230
+ if value.nil?
231
+ is_nullable = self.class.openapi_nullable.include?(attr)
232
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
233
+ end
234
+
235
+ hash[param] = _to_hash(value)
236
+ end
237
+ hash
238
+ end
239
+
240
+ end
241
+
242
+ end
@@ -0,0 +1,149 @@
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
+ class SearchInstagramAudio200Response < ApiModelBase
18
+ attr_accessor :audio
19
+
20
+ # Attribute mapping from ruby-style variable name to JSON key.
21
+ def self.attribute_map
22
+ {
23
+ :'audio' => :'audio'
24
+ }
25
+ end
26
+
27
+ # Returns attribute mapping this model knows about
28
+ def self.acceptable_attribute_map
29
+ attribute_map
30
+ end
31
+
32
+ # Returns all the JSON keys this model knows about
33
+ def self.acceptable_attributes
34
+ acceptable_attribute_map.values
35
+ end
36
+
37
+ # Attribute type mapping.
38
+ def self.openapi_types
39
+ {
40
+ :'audio' => :'Array<InstagramAudioAsset>'
41
+ }
42
+ end
43
+
44
+ # List of attributes with nullable: true
45
+ def self.openapi_nullable
46
+ Set.new([
47
+ ])
48
+ end
49
+
50
+ # Initializes the object
51
+ # @param [Hash] attributes Model attributes in the form of hash
52
+ def initialize(attributes = {})
53
+ if (!attributes.is_a?(Hash))
54
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::SearchInstagramAudio200Response` initialize method"
55
+ end
56
+
57
+ # check to see if the attribute exists and convert string to symbol for hash key
58
+ acceptable_attribute_map = self.class.acceptable_attribute_map
59
+ attributes = attributes.each_with_object({}) { |(k, v), h|
60
+ if (!acceptable_attribute_map.key?(k.to_sym))
61
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::SearchInstagramAudio200Response`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
62
+ end
63
+ h[k.to_sym] = v
64
+ }
65
+
66
+ if attributes.key?(:'audio')
67
+ if (value = attributes[:'audio']).is_a?(Array)
68
+ self.audio = value
69
+ end
70
+ end
71
+ end
72
+
73
+ # Show invalid properties with the reasons. Usually used together with valid?
74
+ # @return Array for valid properties with the reasons
75
+ def list_invalid_properties
76
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
77
+ invalid_properties = Array.new
78
+ invalid_properties
79
+ end
80
+
81
+ # Check to see if the all the properties in the model are valid
82
+ # @return true if the model is valid
83
+ def valid?
84
+ warn '[DEPRECATED] the `valid?` method is obsolete'
85
+ true
86
+ end
87
+
88
+ # Checks equality by comparing each attribute.
89
+ # @param [Object] Object to be compared
90
+ def ==(o)
91
+ return true if self.equal?(o)
92
+ self.class == o.class &&
93
+ audio == o.audio
94
+ end
95
+
96
+ # @see the `==` method
97
+ # @param [Object] Object to be compared
98
+ def eql?(o)
99
+ self == o
100
+ end
101
+
102
+ # Calculates hash code according to all attributes.
103
+ # @return [Integer] Hash code
104
+ def hash
105
+ [audio].hash
106
+ end
107
+
108
+ # Builds the object from hash
109
+ # @param [Hash] attributes Model attributes in the form of hash
110
+ # @return [Object] Returns the model itself
111
+ def self.build_from_hash(attributes)
112
+ return nil unless attributes.is_a?(Hash)
113
+ attributes = attributes.transform_keys(&:to_sym)
114
+ transformed_hash = {}
115
+ openapi_types.each_pair do |key, type|
116
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
117
+ transformed_hash["#{key}"] = nil
118
+ elsif type =~ /\AArray<(.*)>/i
119
+ # check to ensure the input is an array given that the attribute
120
+ # is documented as an array but the input is not
121
+ if attributes[attribute_map[key]].is_a?(Array)
122
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
123
+ end
124
+ elsif !attributes[attribute_map[key]].nil?
125
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
126
+ end
127
+ end
128
+ new(transformed_hash)
129
+ end
130
+
131
+ # Returns the object in the form of hash
132
+ # @return [Hash] Returns the object in the form of hash
133
+ def to_hash
134
+ hash = {}
135
+ self.class.attribute_map.each_pair do |attr, param|
136
+ value = self.send(attr)
137
+ if value.nil?
138
+ is_nullable = self.class.openapi_nullable.include?(attr)
139
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
140
+ end
141
+
142
+ hash[param] = _to_hash(value)
143
+ end
144
+ hash
145
+ end
146
+
147
+ end
148
+
149
+ end
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.710'
14
+ VERSION = '0.0.712'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -605,6 +605,7 @@ require 'zernio-sdk/models/get_inbox_volume200_response_summary'
605
605
  require 'zernio-sdk/models/get_inbox_volume200_response_timeseries_inner'
606
606
  require 'zernio-sdk/models/get_inbox_volume400_response'
607
607
  require 'zernio-sdk/models/get_instagram_account_insights404_response'
608
+ require 'zernio-sdk/models/get_instagram_audio200_response'
608
609
  require 'zernio-sdk/models/get_instagram_follow_status200_response'
609
610
  require 'zernio-sdk/models/get_instagram_publishing_limit200_response'
610
611
  require 'zernio-sdk/models/get_instagram_story_insights200_response'
@@ -795,9 +796,11 @@ require 'zernio-sdk/models/instagram_account_insights_response_metrics_value'
795
796
  require 'zernio-sdk/models/instagram_account_insights_response_metrics_value_breakdowns_inner'
796
797
  require 'zernio-sdk/models/instagram_account_insights_response_metrics_value_values_inner'
797
798
  require 'zernio-sdk/models/instagram_account_insights_response_unavailable_metrics_inner'
799
+ require 'zernio-sdk/models/instagram_audio_asset'
798
800
  require 'zernio-sdk/models/instagram_demographics_response'
799
801
  require 'zernio-sdk/models/instagram_demographics_response_demographics_value_inner'
800
802
  require 'zernio-sdk/models/instagram_platform_data'
803
+ require 'zernio-sdk/models/instagram_platform_data_audio_configuration'
801
804
  require 'zernio-sdk/models/instagram_platform_data_trial_params'
802
805
  require 'zernio-sdk/models/instagram_platform_data_user_tags_inner'
803
806
  require 'zernio-sdk/models/like_inbox_comment200_response'
@@ -1152,6 +1155,7 @@ require 'zernio-sdk/models/search_inbox_conversations200_response_data_inner_mat
1152
1155
  require 'zernio-sdk/models/search_inbox_conversations200_response_meta'
1153
1156
  require 'zernio-sdk/models/search_inbox_conversations200_response_meta_accounts_skipped_inner'
1154
1157
  require 'zernio-sdk/models/search_inbox_conversations200_response_meta_failed_accounts_inner'
1158
+ require 'zernio-sdk/models/search_instagram_audio200_response'
1155
1159
  require 'zernio-sdk/models/search_reddit200_response'
1156
1160
  require 'zernio-sdk/models/search_tweets200_response'
1157
1161
  require 'zernio-sdk/models/search_tweets200_response_meta'
data/openapi.yaml CHANGED
@@ -4873,8 +4873,29 @@ components:
4873
4873
  example: 0
4874
4874
  audioName:
4875
4875
  type: string
4876
- description: Custom name for original audio in Reels. Replaces the default "Original Audio" label. Can only be set once.
4876
+ description: 'Custom name for original audio in Reels. Replaces the default "Original Audio" label. Can only be set once. Unrelated to audioConfiguration, which attaches a catalog track.'
4877
4877
  example: "My Podcast Intro"
4878
+ audioConfiguration:
4879
+ type: object
4880
+ description: 'Attach a licensed music track or original sound from the Instagram audio catalog to a Reel. Reels only (single video post, not a story or image). Requires an Instagram account connected via Facebook Login; classic Instagram Login accounts get a 400 (instagram_audio_requires_facebook_login). Get audio IDs from GET /v1/accounts/{accountId}/instagram/audio. If the track becomes unavailable by publish time (removed, region-blocked, licensing change), the post fails with a user-error; it is not published without the audio.'
4881
+ required: [audioId]
4882
+ properties:
4883
+ audioId:
4884
+ type: string
4885
+ description: 'Audio asset ID from the audio search endpoint.'
4886
+ example: "482851939985510"
4887
+ audioVolume:
4888
+ type: integer
4889
+ minimum: 0
4890
+ maximum: 100
4891
+ description: 'Volume of the attached audio track, 0-100. Defaults to 100.'
4892
+ example: 80
4893
+ videoVolume:
4894
+ type: integer
4895
+ minimum: 0
4896
+ maximum: 100
4897
+ description: 'Volume of the video''s own sound, 0-100. Defaults to 100. Set 0 to mute the original video audio.'
4898
+ example: 100
4878
4899
  thumbOffset:
4879
4900
  type: integer
4880
4901
  minimum: 0
@@ -4894,6 +4915,25 @@ components:
4894
4915
  description: When true, the post is labeled by Instagram as containing AI-generated media. Per Meta, this self-disclosure label is for AI-generated media, not AI-written captions. Applies to feed posts, Reels, Stories, and carousels.
4895
4916
  description: Feed aspect ratio 0.8-1.91, carousels up to 10 items, stories require media (no captions). User tag coordinates 0.0-1.0 from top-left. Images over 8 MB and videos over platform limits are auto-compressed.
4896
4917
 
4918
+ InstagramAudioAsset:
4919
+ type: object
4920
+ description: 'One asset from the Instagram audio catalog. Licensed music carries artist/artwork fields; original sounds carry creator fields instead, so most fields are nullable.'
4921
+ properties:
4922
+ audioId:
4923
+ type: string
4924
+ description: 'Audio asset ID. Pass it as platformSpecificData.audioConfiguration.audioId when creating a Reel.'
4925
+ example: "482851939985510"
4926
+ title: { type: [string, "null"], description: 'Track or sound title.' }
4927
+ audioType: { type: [string, "null"], enum: [music, original_sound, null], description: 'Catalog type of the asset.' }
4928
+ durationInMs: { type: [integer, "null"], description: 'Asset duration in milliseconds.' }
4929
+ displayArtist: { type: [string, "null"], description: 'Artist name (licensed music only).' }
4930
+ coverArtworkThumbnailUrl: { type: [string, "null"], description: 'Cover artwork thumbnail (licensed music only).' }
4931
+ downloadUrl: { type: [string, "null"], description: 'Temporary preview URL. Meta expires it after roughly 1.5 days; re-fetch the asset to refresh it.' }
4932
+ igUsername: { type: [string, "null"], description: 'Creator username (original sounds only).' }
4933
+ profilePictureUrl: { type: [string, "null"], description: 'Creator profile picture (original sounds only).' }
4934
+ isAdsEligible: { type: [boolean, "null"], description: 'Whether the asset is eligible for ads use.' }
4935
+ onPlatformAudioPreviewLink: { type: [string, "null"], description: 'Instagram web link to preview the audio.' }
4936
+
4897
4937
  LinkedInPlatformData:
4898
4938
  type: object
4899
4939
  properties:
@@ -6870,20 +6910,20 @@ components:
6870
6910
  description: "Return on ad spend — derived as `purchaseValue / spend`. 0 when `spend` is 0. Equivalent to Meta's `purchase_roas` under default attribution. At ad-set and campaign levels this is recomputed from summed purchaseValue + spend (NOT averaged across children) so it's mathematically correct at every rollup level."
6871
6911
  videoPlayActions:
6872
6912
  type: integer
6873
- description: "Meta video ads only (0 for non-video ads and other platforms), like all video* fields below. Number of times the video started playing (Meta `video_play_actions`), summed over the date range and across children at ad-set/campaign level."
6874
- video30SecWatchedActions: { type: integer, description: "Views of at least 30 seconds (or to the end, for shorter videos). Meta `video_30_sec_watched_actions`." }
6875
- videoThruplayWatchedActions: { type: integer, description: "ThruPlays (watched to completion, or at least 15 seconds). Meta `video_thruplay_watched_actions`." }
6876
- videoP25WatchedActions: { type: integer, description: "Views reaching 25% of the video's length. With the other percentile fields, powers hook/hold/drop-off analysis (e.g. hook rate = videoP25WatchedActions / videoPlayActions). Meta `video_p25_watched_actions`." }
6877
- videoP50WatchedActions: { type: integer, description: "Views reaching 50% of the video's length. Meta `video_p50_watched_actions`." }
6878
- videoP75WatchedActions: { type: integer, description: "Views reaching 75% of the video's length. Meta `video_p75_watched_actions`." }
6879
- videoP95WatchedActions: { type: integer, description: "Views reaching 95% of the video's length. Meta `video_p95_watched_actions`." }
6880
- videoP100WatchedActions: { type: integer, description: "Views reaching 100% of the video's length. Meta `video_p100_watched_actions`." }
6913
+ description: "Number of times the video started playing, summed over the date range and across children at ad-set/campaign level. 0 for non-video ads. Sources: Meta `video_play_actions`, TikTok `video_play_actions`."
6914
+ video30SecWatchedActions: { type: integer, description: "Views of at least 30 seconds (or to the end, for shorter videos). Sources: Meta `video_30_sec_watched_actions` (Meta only)." }
6915
+ videoThruplayWatchedActions: { type: integer, description: "ThruPlays (watched to completion, or at least 15 seconds). Sources: Meta `video_thruplay_watched_actions` (Meta only)." }
6916
+ videoP25WatchedActions: { type: integer, description: "Views reaching 25% of the video's length. With the other percentile fields, powers hook/hold/drop-off analysis (e.g. hook rate = videoP25WatchedActions / videoPlayActions). Sources: Meta `video_p25_watched_actions`, TikTok `video_views_p25`." }
6917
+ videoP50WatchedActions: { type: integer, description: "Views reaching 50% of the video's length. Sources: Meta `video_p50_watched_actions`, TikTok `video_views_p50`." }
6918
+ videoP75WatchedActions: { type: integer, description: "Views reaching 75% of the video's length. Sources: Meta `video_p75_watched_actions`, TikTok `video_views_p75`." }
6919
+ videoP95WatchedActions: { type: integer, description: "Views reaching 95% of the video's length. Sources: Meta `video_p95_watched_actions` (Meta only)." }
6920
+ videoP100WatchedActions: { type: integer, description: "Views reaching 100% of the video's length. Sources: Meta `video_p100_watched_actions`, TikTok `video_views_p100`." }
6881
6921
  videoAvgTimeWatchedActions:
6882
6922
  type: number
6883
- description: "Average seconds watched per play (Meta `video_avg_time_watched_actions`). Aggregated over date ranges and across children as a play-weighted average (total watch time / total plays), never a plain average of averages."
6923
+ description: "Average seconds watched per play. Aggregated over date ranges and across children as a play-weighted average (total watch time / total plays), never a plain average of averages. Sources: Meta `video_avg_time_watched_actions`, TikTok `average_video_play`."
6884
6924
  costPerThruplay:
6885
6925
  type: number
6886
- description: "Derived `spend / videoThruplayWatchedActions`, in ad-account native currency. Rounded to 4 decimals rather than the usual 2 because a ThruPlay routinely costs well under a cent. 0 when the ad has no ThruPlays."
6926
+ description: "Derived `spend / videoThruplayWatchedActions`, in ad-account native currency. Rounded to 4 decimals rather than the usual 2 because a ThruPlay routinely costs well under a cent. 0 when the ad has no ThruPlays (ThruPlay is Meta-only)."
6887
6927
  funnel:
6888
6928
  $ref: '#/components/schemas/AdFunnelCounts'
6889
6929
  engagementBreakdown:
@@ -20591,6 +20631,96 @@ paths:
20591
20631
  '404': { description: Account not found }
20592
20632
  '502': { description: Instagram rejected the request }
20593
20633
 
20634
+ /v1/accounts/{accountId}/instagram/audio:
20635
+ get:
20636
+ x-resource-group: "accounts"
20637
+ operationId: searchInstagramAudio
20638
+ tags: [Instagram]
20639
+ summary: Search Instagram audio
20640
+ description: |
20641
+ Search Instagram's audio catalog (licensed music or original sounds),
20642
+ or list what is currently trending by omitting `q`. Returns up to ~30
20643
+ assets; Meta exposes no pagination on this edge.
20644
+
20645
+ Pass the returned `audioId` as
20646
+ `platformSpecificData.audioConfiguration.audioId` when creating a Reel
20647
+ to publish it with that track.
20648
+
20649
+ Requires an Instagram account connected via **Facebook Login**. Meta
20650
+ hosts this catalog on graph.facebook.com only, so accounts connected
20651
+ with classic Instagram Login receive a 400
20652
+ (`instagram_audio_requires_facebook_login`) and must be reconnected
20653
+ choosing the Facebook option.
20654
+ parameters:
20655
+ - name: accountId
20656
+ in: path
20657
+ required: true
20658
+ description: The ID of the Instagram account
20659
+ schema: { type: string }
20660
+ - name: audioType
20661
+ in: query
20662
+ required: true
20663
+ description: 'Catalog to search: licensed music or original sounds from Reels.'
20664
+ schema: { type: string, enum: [music, original_sound] }
20665
+ - name: q
20666
+ in: query
20667
+ required: false
20668
+ description: 'Search keywords. Omit to get the current trending list.'
20669
+ schema: { type: string, minLength: 1, maxLength: 200 }
20670
+ responses:
20671
+ '200':
20672
+ description: Matching audio assets (may be empty)
20673
+ content:
20674
+ application/json:
20675
+ schema:
20676
+ type: object
20677
+ properties:
20678
+ audio:
20679
+ type: array
20680
+ items: { $ref: '#/components/schemas/InstagramAudioAsset' }
20681
+ '400': { $ref: '#/components/responses/BadRequest' }
20682
+ '401': { $ref: '#/components/responses/Unauthorized' }
20683
+ '404': { description: Account not found }
20684
+ '502': { description: Instagram rejected the request }
20685
+
20686
+ /v1/accounts/{accountId}/instagram/audio/{audioId}:
20687
+ get:
20688
+ x-resource-group: "accounts"
20689
+ operationId: getInstagramAudio
20690
+ tags: [Instagram]
20691
+ summary: Get Instagram audio metadata
20692
+ description: |
20693
+ Fetch one audio asset's metadata by ID. Use it to re-validate a stored
20694
+ `audioId` before a scheduled Reel publishes, or to refresh the preview
20695
+ `downloadUrl` (Meta expires preview URLs after roughly 1.5 days).
20696
+
20697
+ Same connection requirement as the search endpoint: Facebook-Login
20698
+ Instagram accounts only.
20699
+ parameters:
20700
+ - name: accountId
20701
+ in: path
20702
+ required: true
20703
+ description: The ID of the Instagram account
20704
+ schema: { type: string }
20705
+ - name: audioId
20706
+ in: path
20707
+ required: true
20708
+ description: Instagram audio asset ID
20709
+ schema: { type: string, pattern: '^\d{1,30}$' }
20710
+ responses:
20711
+ '200':
20712
+ description: The audio asset
20713
+ content:
20714
+ application/json:
20715
+ schema:
20716
+ type: object
20717
+ properties:
20718
+ audio: { $ref: '#/components/schemas/InstagramAudioAsset' }
20719
+ '400': { $ref: '#/components/responses/BadRequest' }
20720
+ '401': { $ref: '#/components/responses/Unauthorized' }
20721
+ '404': { description: Account not found }
20722
+ '502': { description: Instagram rejected the request }
20723
+
20594
20724
  /v1/accounts/{accountId}/instagram/stories/{storyId}/insights:
20595
20725
  get:
20596
20726
  x-resource-group: "analytics"
@@ -32,6 +32,19 @@ describe 'InstagramApi' do
32
32
  end
33
33
  end
34
34
 
35
+ # unit tests for get_instagram_audio
36
+ # Get Instagram audio metadata
37
+ # Fetch one audio asset&#39;s metadata by ID. Use it to re-validate a stored &#x60;audioId&#x60; before a scheduled Reel publishes, or to refresh the preview &#x60;downloadUrl&#x60; (Meta expires preview URLs after roughly 1.5 days). Same connection requirement as the search endpoint: Facebook-Login Instagram accounts only.
38
+ # @param account_id The ID of the Instagram account
39
+ # @param audio_id Instagram audio asset ID
40
+ # @param [Hash] opts the optional parameters
41
+ # @return [GetInstagramAudio200Response]
42
+ describe 'get_instagram_audio test' 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
+
35
48
  # unit tests for get_instagram_publishing_limit
36
49
  # Get Instagram publishing limit
37
50
  # Returns the account&#39;s remaining content-publishing quota for Instagram&#39;s rolling 24-hour window, so you can pace publishing and warn before the cap is reached. &#x60;quotaUsage&#x60; counts containers published since the start of the window. Always compare against the returned &#x60;quotaTotal&#x60; rather than hardcoding a number: Meta&#39;s prose documentation and the live API disagree on the value, and the live value is authoritative.
@@ -69,4 +82,18 @@ describe 'InstagramApi' do
69
82
  end
70
83
  end
71
84
 
85
+ # unit tests for search_instagram_audio
86
+ # Search Instagram audio
87
+ # Search Instagram&#39;s audio catalog (licensed music or original sounds), or list what is currently trending by omitting &#x60;q&#x60;. Returns up to ~30 assets; Meta exposes no pagination on this edge. Pass the returned &#x60;audioId&#x60; as &#x60;platformSpecificData.audioConfiguration.audioId&#x60; when creating a Reel to publish it with that track. Requires an Instagram account connected via **Facebook Login**. Meta hosts this catalog on graph.facebook.com only, so accounts connected with classic Instagram Login receive a 400 (&#x60;instagram_audio_requires_facebook_login&#x60;) and must be reconnected choosing the Facebook option.
88
+ # @param account_id The ID of the Instagram account
89
+ # @param audio_type Catalog to search: licensed music or original sounds from Reels.
90
+ # @param [Hash] opts the optional parameters
91
+ # @option opts [String] :q Search keywords. Omit to get the current trending list.
92
+ # @return [SearchInstagramAudio200Response]
93
+ describe 'search_instagram_audio test' do
94
+ it 'should work' do
95
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
96
+ end
97
+ end
98
+
72
99
  end