late-sdk 0.0.899 → 0.0.901

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 (223) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +81 -8
  3. data/docs/AdAccountsApi.md +1375 -277
  4. data/docs/AdCampaignsApi.md +525 -13
  5. data/docs/AdCreative.md +6 -0
  6. data/docs/AdTracking.md +20 -0
  7. data/docs/AddAccountCalloutsRequest.md +3 -3
  8. data/docs/AddAccountSitelinks201Response.md +20 -0
  9. data/docs/AddAccountSitelinks201ResponseSitelinksInner.md +26 -0
  10. data/docs/AddAccountSitelinksRequest.md +22 -0
  11. data/docs/AddAccountStructuredSnippets201Response.md +20 -0
  12. data/docs/AddAccountStructuredSnippets201ResponseStructuredSnippetsInner.md +22 -0
  13. data/docs/AddAccountStructuredSnippetsRequest.md +22 -0
  14. data/docs/AttachAdGroupAssets201Response.md +24 -0
  15. data/docs/AttachCampaignAssetsRequest.md +4 -4
  16. data/docs/CreateAdCampaign200Response.md +26 -0
  17. data/docs/CreateAdCampaignRequest.md +8 -0
  18. data/docs/CreateCallAdRequest.md +2 -0
  19. data/docs/CreateMessagingAdRequest.md +2 -0
  20. data/docs/CreateStandaloneAdRequest.md +15 -7
  21. data/docs/CreateStandaloneAdRequestAdditionalDescriptionsInner.md +49 -0
  22. data/docs/CreateStandaloneAdRequestAdditionalHeadlinesInner.md +49 -0
  23. data/docs/CtwaAdRequestBody.md +2 -0
  24. data/docs/GetAd200Response.md +5 -1
  25. data/docs/GetAdComments200ResponseMeta.md +10 -4
  26. data/docs/GetIosFourteenCampaignLimits200Response.md +18 -0
  27. data/docs/GetIosFourteenCampaignLimits200ResponseLimits.md +22 -0
  28. data/docs/GoogleAssetUpdate.md +26 -0
  29. data/docs/GoogleRsaDescription.md +20 -0
  30. data/docs/GoogleRsaHeadline.md +20 -0
  31. data/docs/{AttachCampaignAssetsRequestSitelinksInner.md → GoogleSitelink.md} +2 -2
  32. data/docs/{AttachCampaignAssetsRequestStructuredSnippetsInner.md → GoogleStructuredSnippet.md} +2 -2
  33. data/docs/HideAdComment200Response.md +22 -0
  34. data/docs/HideAdCommentRequest.md +18 -0
  35. data/docs/ListAccountCallouts200Response.md +2 -2
  36. data/docs/ListAccountCallouts200ResponseCalloutsInner.md +3 -3
  37. data/docs/ListAccountSitelinks200Response.md +24 -0
  38. data/docs/ListAccountSitelinks200ResponseSitelinksInner.md +32 -0
  39. data/docs/ListAccountStructuredSnippets200Response.md +24 -0
  40. data/docs/ListAccountStructuredSnippets200ResponseStructuredSnippetsInner.md +28 -0
  41. data/docs/ListAdGroupAssets200Response.md +28 -0
  42. data/docs/ListAdGroupAssets200ResponseCalloutsInner.md +22 -0
  43. data/docs/ListAdGroupAssets200ResponseSitelinksInner.md +28 -0
  44. data/docs/ListAdGroupAssets200ResponseStructuredSnippetsInner.md +24 -0
  45. data/docs/ListAdsInstagramAccounts200Response.md +22 -0
  46. data/docs/ListAdsInstagramAccounts200ResponseAccountsInner.md +26 -0
  47. data/docs/ListAdsInstagramAccounts200ResponsePagesInner.md +24 -0
  48. data/docs/ListAdsInstagramAccounts200ResponseResolved.md +22 -0
  49. data/docs/ListAdvertisableApplications200Response.md +18 -0
  50. data/docs/ListAdvertisableApplications200ResponseApplicationsInner.md +24 -0
  51. data/docs/ListCampaignAssets200Response.md +28 -0
  52. data/docs/ListCampaignAssets200ResponseCalloutsInner.md +22 -0
  53. data/docs/ListCampaignAssets200ResponseSitelinksInner.md +28 -0
  54. data/docs/ListCampaignAssets200ResponseStructuredSnippetsInner.md +24 -0
  55. data/docs/MetaInstagramIdentityRef.md +22 -0
  56. data/docs/RemoveAccountCalloutRequest.md +3 -3
  57. data/docs/RemoveAdGroupAssetsRequest.md +24 -0
  58. data/docs/RemoveCampaignAssets200Response.md +18 -0
  59. data/docs/RemoveCampaignAssetsRequest.md +24 -0
  60. data/docs/ReplyToAdComment200Response.md +20 -0
  61. data/docs/ReplyToAdCommentRequest.md +18 -0
  62. data/docs/TargetingSpec.md +4 -0
  63. data/docs/UpdateAccountCallouts200Response.md +20 -0
  64. data/docs/UpdateAccountCalloutsRequest.md +22 -0
  65. data/docs/UpdateAccountCalloutsRequestUpdatesInner.md +20 -0
  66. data/docs/UpdateAccountCalloutsRequestUpdatesInnerCalloutAsset.md +18 -0
  67. data/docs/UpdateAccountSitelinksRequest.md +22 -0
  68. data/docs/UpdateAccountSitelinksRequestUpdatesInner.md +22 -0
  69. data/docs/UpdateAccountSitelinksRequestUpdatesInnerSitelinkAsset.md +24 -0
  70. data/docs/UpdateAccountStructuredSnippetsRequest.md +22 -0
  71. data/docs/UpdateAccountStructuredSnippetsRequestUpdatesInner.md +20 -0
  72. data/docs/UpdateAdRequest.md +6 -0
  73. data/docs/UpdateCampaignAssets200Response.md +18 -0
  74. data/docs/UpdateCampaignAssetsRequest.md +22 -0
  75. data/lib/zernio-sdk/api/ad_accounts_api.rb +1511 -363
  76. data/lib/zernio-sdk/api/ad_campaigns_api.rb +589 -13
  77. data/lib/zernio-sdk/models/ad_creative.rb +112 -1
  78. data/lib/zernio-sdk/models/{create_standalone_ad_request_tracking.rb → ad_tracking.rb} +5 -5
  79. data/lib/zernio-sdk/models/add_account_callouts_request.rb +34 -3
  80. data/lib/zernio-sdk/models/add_account_sitelinks201_response.rb +158 -0
  81. data/lib/zernio-sdk/models/add_account_sitelinks201_response_sitelinks_inner.rb +267 -0
  82. data/lib/zernio-sdk/models/add_account_sitelinks_request.rb +253 -0
  83. data/lib/zernio-sdk/models/add_account_structured_snippets201_response.rb +158 -0
  84. data/lib/zernio-sdk/models/add_account_structured_snippets201_response_structured_snippets_inner.rb +229 -0
  85. data/lib/zernio-sdk/models/add_account_structured_snippets_request.rb +253 -0
  86. data/lib/zernio-sdk/models/attach_ad_group_assets201_response.rb +180 -0
  87. data/lib/zernio-sdk/models/attach_campaign_assets_request.rb +37 -5
  88. data/lib/zernio-sdk/models/create_ad_campaign200_response.rb +231 -0
  89. data/lib/zernio-sdk/models/create_ad_campaign_request.rb +52 -1
  90. data/lib/zernio-sdk/models/create_call_ad_request.rb +10 -1
  91. data/lib/zernio-sdk/models/create_messaging_ad_request.rb +10 -1
  92. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +102 -8
  93. data/lib/zernio-sdk/models/create_standalone_ad_request_additional_descriptions_inner.rb +104 -0
  94. data/lib/zernio-sdk/models/create_standalone_ad_request_additional_headlines_inner.rb +104 -0
  95. data/lib/zernio-sdk/models/ctwa_ad_request_body.rb +10 -1
  96. data/lib/zernio-sdk/models/get_ad200_response.rb +25 -4
  97. data/lib/zernio-sdk/models/get_ad_comments200_response_meta.rb +36 -46
  98. data/lib/zernio-sdk/models/get_ios_fourteen_campaign_limits200_response.rb +164 -0
  99. data/lib/zernio-sdk/models/get_ios_fourteen_campaign_limits200_response_limits.rb +172 -0
  100. data/lib/zernio-sdk/models/google_asset_update.rb +234 -0
  101. data/lib/zernio-sdk/models/google_rsa_description.rb +226 -0
  102. data/lib/zernio-sdk/models/google_rsa_headline.rb +226 -0
  103. data/lib/zernio-sdk/models/{attach_campaign_assets_request_sitelinks_inner.rb → google_sitelink.rb} +3 -3
  104. data/lib/zernio-sdk/models/{attach_campaign_assets_request_structured_snippets_inner.rb → google_structured_snippet.rb} +3 -3
  105. data/lib/zernio-sdk/models/hide_ad_comment200_response.rb +225 -0
  106. data/lib/zernio-sdk/models/hide_ad_comment_request.rb +165 -0
  107. data/lib/zernio-sdk/models/list_account_callouts200_response.rb +2 -2
  108. data/lib/zernio-sdk/models/list_account_callouts200_response_callouts_inner.rb +13 -14
  109. data/lib/zernio-sdk/models/list_account_sitelinks200_response.rb +179 -0
  110. data/lib/zernio-sdk/models/list_account_sitelinks200_response_sitelinks_inner.rb +210 -0
  111. data/lib/zernio-sdk/models/list_account_structured_snippets200_response.rb +179 -0
  112. data/lib/zernio-sdk/models/list_account_structured_snippets200_response_structured_snippets_inner.rb +194 -0
  113. data/lib/zernio-sdk/models/list_ad_group_assets200_response.rb +201 -0
  114. data/lib/zernio-sdk/models/list_ad_group_assets200_response_callouts_inner.rb +165 -0
  115. data/lib/zernio-sdk/models/list_ad_group_assets200_response_sitelinks_inner.rb +192 -0
  116. data/lib/zernio-sdk/models/list_ad_group_assets200_response_structured_snippets_inner.rb +176 -0
  117. data/lib/zernio-sdk/models/list_ads_instagram_accounts200_response.rb +220 -0
  118. data/lib/zernio-sdk/models/list_ads_instagram_accounts200_response_accounts_inner.rb +287 -0
  119. data/lib/zernio-sdk/models/list_ads_instagram_accounts200_response_pages_inner.rb +210 -0
  120. data/lib/zernio-sdk/models/list_ads_instagram_accounts200_response_resolved.rb +211 -0
  121. data/lib/zernio-sdk/models/list_advertisable_applications200_response.rb +166 -0
  122. data/lib/zernio-sdk/models/list_advertisable_applications200_response_applications_inner.rb +250 -0
  123. data/lib/zernio-sdk/models/list_campaign_assets200_response.rb +201 -0
  124. data/lib/zernio-sdk/models/list_campaign_assets200_response_callouts_inner.rb +165 -0
  125. data/lib/zernio-sdk/models/list_campaign_assets200_response_sitelinks_inner.rb +192 -0
  126. data/lib/zernio-sdk/models/list_campaign_assets200_response_structured_snippets_inner.rb +176 -0
  127. data/lib/zernio-sdk/models/meta_instagram_identity_ref.rb +202 -0
  128. data/lib/zernio-sdk/models/remove_account_callout_request.rb +45 -3
  129. data/lib/zernio-sdk/models/remove_ad_group_assets_request.rb +281 -0
  130. data/lib/zernio-sdk/models/remove_campaign_assets200_response.rb +147 -0
  131. data/lib/zernio-sdk/models/remove_campaign_assets_request.rb +281 -0
  132. data/lib/zernio-sdk/models/reply_to_ad_comment200_response.rb +215 -0
  133. data/lib/zernio-sdk/models/reply_to_ad_comment_request.rb +174 -0
  134. data/lib/zernio-sdk/models/targeting_spec.rb +63 -1
  135. data/lib/zernio-sdk/models/update_account_callouts200_response.rb +156 -0
  136. data/lib/zernio-sdk/models/update_account_callouts_request.rb +253 -0
  137. data/lib/zernio-sdk/models/update_account_callouts_request_updates_inner.rb +186 -0
  138. data/lib/zernio-sdk/models/update_account_callouts_request_updates_inner_callout_asset.rb +182 -0
  139. data/lib/zernio-sdk/models/update_account_sitelinks_request.rb +253 -0
  140. data/lib/zernio-sdk/models/update_account_sitelinks_request_updates_inner.rb +216 -0
  141. data/lib/zernio-sdk/models/update_account_sitelinks_request_updates_inner_sitelink_asset.rb +241 -0
  142. data/lib/zernio-sdk/models/update_account_structured_snippets_request.rb +253 -0
  143. data/lib/zernio-sdk/models/update_account_structured_snippets_request_updates_inner.rb +186 -0
  144. data/lib/zernio-sdk/models/update_ad_request.rb +112 -1
  145. data/lib/zernio-sdk/models/update_campaign_assets200_response.rb +147 -0
  146. data/lib/zernio-sdk/models/update_campaign_assets_request.rb +253 -0
  147. data/lib/zernio-sdk/version.rb +1 -1
  148. data/lib/zernio-sdk.rb +55 -4
  149. data/openapi.yaml +2898 -733
  150. data/spec/api/ad_accounts_api_spec.rb +209 -10
  151. data/spec/api/ad_campaigns_api_spec.rb +99 -6
  152. data/spec/models/ad_creative_spec.rb +18 -0
  153. data/spec/models/{create_standalone_ad_request_tracking_spec.rb → ad_tracking_spec.rb} +6 -6
  154. data/spec/models/add_account_sitelinks201_response_sitelinks_inner_spec.rb +60 -0
  155. data/spec/models/add_account_sitelinks201_response_spec.rb +42 -0
  156. data/spec/models/add_account_sitelinks_request_spec.rb +48 -0
  157. data/spec/models/add_account_structured_snippets201_response_spec.rb +42 -0
  158. data/spec/models/add_account_structured_snippets201_response_structured_snippets_inner_spec.rb +52 -0
  159. data/spec/models/add_account_structured_snippets_request_spec.rb +48 -0
  160. data/spec/models/attach_ad_group_assets201_response_spec.rb +54 -0
  161. data/spec/models/create_ad_campaign200_response_spec.rb +68 -0
  162. data/spec/models/create_ad_campaign_request_spec.rb +28 -0
  163. data/spec/models/create_call_ad_request_spec.rb +6 -0
  164. data/spec/models/create_messaging_ad_request_spec.rb +6 -0
  165. data/spec/models/create_standalone_ad_request_additional_descriptions_inner_spec.rb +32 -0
  166. data/spec/models/create_standalone_ad_request_additional_headlines_inner_spec.rb +32 -0
  167. data/spec/models/create_standalone_ad_request_spec.rb +28 -0
  168. data/spec/models/ctwa_ad_request_body_spec.rb +6 -0
  169. data/spec/models/get_ad200_response_spec.rb +12 -0
  170. data/spec/models/get_ad_comments200_response_meta_spec.rb +19 -1
  171. data/spec/models/get_ios_fourteen_campaign_limits200_response_limits_spec.rb +48 -0
  172. data/spec/models/get_ios_fourteen_campaign_limits200_response_spec.rb +36 -0
  173. data/spec/models/google_asset_update_spec.rb +60 -0
  174. data/spec/models/google_rsa_description_spec.rb +46 -0
  175. data/spec/models/google_rsa_headline_spec.rb +46 -0
  176. data/spec/models/{attach_campaign_assets_request_sitelinks_inner_spec.rb → google_sitelink_spec.rb} +6 -6
  177. data/spec/models/{attach_campaign_assets_request_structured_snippets_inner_spec.rb → google_structured_snippet_spec.rb} +6 -6
  178. data/spec/models/hide_ad_comment200_response_spec.rb +52 -0
  179. data/spec/models/hide_ad_comment_request_spec.rb +36 -0
  180. data/spec/models/list_account_callouts200_response_callouts_inner_spec.rb +2 -2
  181. data/spec/models/{create_standalone_ad_request_promoted_object_spec.rb → list_account_sitelinks200_response_sitelinks_inner_spec.rb} +14 -32
  182. data/spec/models/list_account_sitelinks200_response_spec.rb +54 -0
  183. data/spec/models/list_account_structured_snippets200_response_spec.rb +54 -0
  184. data/spec/models/list_account_structured_snippets200_response_structured_snippets_inner_spec.rb +66 -0
  185. data/spec/models/list_ad_group_assets200_response_callouts_inner_spec.rb +48 -0
  186. data/spec/models/list_ad_group_assets200_response_sitelinks_inner_spec.rb +66 -0
  187. data/spec/models/list_ad_group_assets200_response_spec.rb +66 -0
  188. data/spec/models/list_ad_group_assets200_response_structured_snippets_inner_spec.rb +54 -0
  189. data/spec/models/list_ads_instagram_accounts200_response_accounts_inner_spec.rb +64 -0
  190. data/spec/models/list_ads_instagram_accounts200_response_pages_inner_spec.rb +54 -0
  191. data/spec/models/list_ads_instagram_accounts200_response_resolved_spec.rb +52 -0
  192. data/spec/models/list_ads_instagram_accounts200_response_spec.rb +48 -0
  193. data/spec/models/list_advertisable_applications200_response_applications_inner_spec.rb +54 -0
  194. data/spec/models/list_advertisable_applications200_response_spec.rb +36 -0
  195. data/spec/models/list_campaign_assets200_response_callouts_inner_spec.rb +48 -0
  196. data/spec/models/list_campaign_assets200_response_sitelinks_inner_spec.rb +66 -0
  197. data/spec/models/list_campaign_assets200_response_spec.rb +66 -0
  198. data/spec/models/list_campaign_assets200_response_structured_snippets_inner_spec.rb +54 -0
  199. data/spec/models/meta_instagram_identity_ref_spec.rb +48 -0
  200. data/spec/models/remove_ad_group_assets_request_spec.rb +54 -0
  201. data/spec/models/remove_campaign_assets200_response_spec.rb +36 -0
  202. data/spec/models/remove_campaign_assets_request_spec.rb +54 -0
  203. data/spec/models/reply_to_ad_comment200_response_spec.rb +46 -0
  204. data/spec/models/reply_to_ad_comment_request_spec.rb +36 -0
  205. data/spec/models/targeting_spec_spec.rb +12 -0
  206. data/spec/models/update_account_callouts200_response_spec.rb +42 -0
  207. data/spec/models/update_account_callouts_request_spec.rb +48 -0
  208. data/spec/models/update_account_callouts_request_updates_inner_callout_asset_spec.rb +36 -0
  209. data/spec/models/update_account_callouts_request_updates_inner_spec.rb +42 -0
  210. data/spec/models/update_account_sitelinks_request_spec.rb +48 -0
  211. data/spec/models/update_account_sitelinks_request_updates_inner_sitelink_asset_spec.rb +54 -0
  212. data/spec/models/update_account_sitelinks_request_updates_inner_spec.rb +48 -0
  213. data/spec/models/update_account_structured_snippets_request_spec.rb +48 -0
  214. data/spec/models/update_account_structured_snippets_request_updates_inner_spec.rb +42 -0
  215. data/spec/models/update_ad_request_spec.rb +18 -0
  216. data/spec/models/update_campaign_assets200_response_spec.rb +36 -0
  217. data/spec/models/update_campaign_assets_request_spec.rb +48 -0
  218. data/zernio-sdk-0.0.901.gem +0 -0
  219. metadata +222 -18
  220. data/docs/CreateStandaloneAdRequestPromotedObject.md +0 -38
  221. data/docs/CreateStandaloneAdRequestTracking.md +0 -20
  222. data/lib/zernio-sdk/models/create_standalone_ad_request_promoted_object.rb +0 -249
  223. data/zernio-sdk-0.0.899.gem +0 -0
@@ -55,7 +55,7 @@ module Zernio
55
55
  # Meta only. Multi-advertiser ads: whether Meta may show this ad alongside other advertisers' in one unit. Meta auto-enrols since Aug 2024, so send OPT_OUT to leave. It is a top-level creative field, NOT a `creativeFeatures` key, and Meta rejects it there.
56
56
  attr_accessor :multi_advertiser
57
57
 
58
- # Meta only, single standalone shape only (no creatives[], adSetId, or RESERVED). Dry-run: each node runs Meta's execution_options validate_only and NOTHING is created or persisted. Children need real parents, so a fresh tree validates the campaign + creative (the ad set needs its campaign to exist, so pass existingCampaignId to validate it too; the ad itself is never validatable pre-create). A Meta validation failure returns the 400 verbatim; success returns 200 with per-node results instead of an ad.
58
+ # Meta only. Validates the complete inline campaign, ad set, creative and ad with execution_options validate_only. Nothing is uploaded or created, and validation bypasses Idempotency-Key storage. Supports a single image, existing video.id or existingCreativeId; media pools, new video uploads, creatives[], adSetId and RESERVED buying return 400. Existing campaign or creative nodes are marked skipped. Success returns 200 with per-node results; Meta rejection returns an error.
59
59
  attr_accessor :validate_only
60
60
 
61
61
  # Budget in WHOLE currency units (USD: 50 = $50.00), NOT cents. Meta's own Marketing API takes this same number in minor units, so it is an easy and expensive mix-up. Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType).
@@ -237,10 +237,10 @@ module Zernio
237
237
  # Google Search only; other platforms return 400. Campaign-level negative keywords (campaign_criterion.negative), created alongside the ad group. Editable later via PUT /v1/ads/campaigns/{campaignId}/negative-keywords.
238
238
  attr_accessor :campaign_negative_keywords
239
239
 
240
- # Google Search RSA only. Extra headlines.
240
+ # Google Search RSA only. Extra text assets as strings or objects with text and optional pinnedField. Existing string input remains supported. The effective create lists, including primary text and deduplication, must contain 3-15 headlines and 2-4 descriptions; excess entries return 400.
241
241
  attr_accessor :additional_headlines
242
242
 
243
- # Google Search RSA only. Extra descriptions.
243
+ # Google Search RSA only. Extra text assets as strings or objects with text and optional pinnedField. Existing string input remains supported. The effective create lists, including primary text and deduplication, must contain 3-15 headlines and 2-4 descriptions; excess entries return 400.
244
244
  attr_accessor :additional_descriptions
245
245
 
246
246
  # Google Search only. Sitelink assets to create and attach at the campaign level. Each entry becomes an Asset (with sitelink_asset + Asset.final_urls) plus a CampaignAsset link (field_type SITELINK). Approval is async: Google reviews assets after creation; poll asset.policy_summary later to read the verdict. Google requires at least two sitelinks to surface them on an ad; four or more is Google's own recommendation for maximum visibility. The response's creative.sitelinks[] echoes each input plus its Google resourceName.
@@ -295,6 +295,18 @@ module Zernio
295
295
  # TikTok only. Creates the ad as a TikTok Upgraded Smart+ campaign: TikTok automates targeting, bidding and delivery. Supports goals `conversions` (Smart+ Web Conversions), `lead_generation` (Smart+ Lead Generation with a website form on `linkUrl`; TikTok Instant Forms not supported) and `app_promotion` (Smart+ App installs; the ad's destination is the app store, so `linkUrl` is not used). The web goals require `promotedObject.pixelId` AND `promotedObject.customEventType`; `app_promotion` requires `promotedObject.applicationId` instead. Targeting works like on any TikTok ad (defaults to `countries: [\"US\"]` when omitted); TikTok automates delivery within it. The budget lives on the Smart+ campaign (Campaign Budget Optimization); a `lifetime` budget additionally requires `endDate`. Cannot be combined with `adSetId`.
296
296
  attr_accessor :smart_plus
297
297
 
298
+ # Meta only. Operating systems and version ranges, such as iOS_ver_14.0_and_above or Android. Emitted as user_os. May also be supplied inside targeting.
299
+ attr_accessor :user_os
300
+
301
+ # Meta only. Device models such as iPhone. Emitted as user_device. May also be supplied inside targeting.
302
+ attr_accessor :user_device
303
+
304
+ # Meta app promotion only. Immutable campaign flag. Set true for iOS 14+ SKAdNetwork campaigns and supply promotedObject.applicationId plus promotedObject.objectStoreUrl. The campaign receives promotedObject only when this flag is true. Cannot be changed on an existing campaign.
305
+ attr_accessor :is_skadnetwork_attribution
306
+
307
+ # Meta ad-set attribution. Required as SKADNETWORK for iOS 14+ app promotion or a SKAdNetwork campaign. Requires AUCTION buying. Standalone Meta ad-set creation is not supported; use this field on /v1/ads/create.
308
+ attr_accessor :campaign_attribution
309
+
298
310
  attr_accessor :promoted_object
299
311
 
300
312
  class EnumAttributeValidator
@@ -420,6 +432,10 @@ module Zernio
420
432
  :'brand_identity' => :'brandIdentity',
421
433
  :'identity_type' => :'identityType',
422
434
  :'smart_plus' => :'smartPlus',
435
+ :'user_os' => :'userOs',
436
+ :'user_device' => :'userDevice',
437
+ :'is_skadnetwork_attribution' => :'isSkadnetworkAttribution',
438
+ :'campaign_attribution' => :'campaignAttribution',
423
439
  :'promoted_object' => :'promotedObject'
424
440
  }
425
441
  end
@@ -443,7 +459,7 @@ module Zernio
443
459
  :'campaign_name' => :'String',
444
460
  :'ad_set_name' => :'String',
445
461
  :'ad_name' => :'String',
446
- :'tracking' => :'CreateStandaloneAdRequestTracking',
462
+ :'tracking' => :'AdTracking',
447
463
  :'goal' => :'String',
448
464
  :'optimization_goal' => :'String',
449
465
  :'billing_event' => :'String',
@@ -515,8 +531,8 @@ module Zernio
515
531
  :'keywords' => :'Array<KeywordEntry>',
516
532
  :'negative_keywords' => :'Array<KeywordEntry>',
517
533
  :'campaign_negative_keywords' => :'Array<KeywordEntry>',
518
- :'additional_headlines' => :'Array<String>',
519
- :'additional_descriptions' => :'Array<String>',
534
+ :'additional_headlines' => :'Array<CreateStandaloneAdRequestAdditionalHeadlinesInner>',
535
+ :'additional_descriptions' => :'Array<CreateStandaloneAdRequestAdditionalDescriptionsInner>',
520
536
  :'sitelinks' => :'Array<CreateStandaloneAdRequestSitelinksInner>',
521
537
  :'callouts' => :'Array<String>',
522
538
  :'structured_snippets' => :'Array<CreateStandaloneAdRequestStructuredSnippetsInner>',
@@ -535,7 +551,11 @@ module Zernio
535
551
  :'brand_identity' => :'CreateStandaloneAdRequestBrandIdentity',
536
552
  :'identity_type' => :'String',
537
553
  :'smart_plus' => :'Boolean',
538
- :'promoted_object' => :'CreateStandaloneAdRequestPromotedObject'
554
+ :'user_os' => :'Array<String>',
555
+ :'user_device' => :'Array<String>',
556
+ :'is_skadnetwork_attribution' => :'Boolean',
557
+ :'campaign_attribution' => :'String',
558
+ :'promoted_object' => :'AdPromotedObject'
539
559
  }
540
560
  end
541
561
 
@@ -1031,6 +1051,26 @@ module Zernio
1031
1051
  self.smart_plus = attributes[:'smart_plus']
1032
1052
  end
1033
1053
 
1054
+ if attributes.key?(:'user_os')
1055
+ if (value = attributes[:'user_os']).is_a?(Array)
1056
+ self.user_os = value
1057
+ end
1058
+ end
1059
+
1060
+ if attributes.key?(:'user_device')
1061
+ if (value = attributes[:'user_device']).is_a?(Array)
1062
+ self.user_device = value
1063
+ end
1064
+ end
1065
+
1066
+ if attributes.key?(:'is_skadnetwork_attribution')
1067
+ self.is_skadnetwork_attribution = attributes[:'is_skadnetwork_attribution']
1068
+ end
1069
+
1070
+ if attributes.key?(:'campaign_attribution')
1071
+ self.campaign_attribution = attributes[:'campaign_attribution']
1072
+ end
1073
+
1034
1074
  if attributes.key?(:'promoted_object')
1035
1075
  self.promoted_object = attributes[:'promoted_object']
1036
1076
  end
@@ -1211,6 +1251,14 @@ module Zernio
1211
1251
  invalid_properties.push('invalid value for "dsa_payor", the character length must be smaller than or equal to 100.')
1212
1252
  end
1213
1253
 
1254
+ if !@user_os.nil? && @user_os.length < 1
1255
+ invalid_properties.push('invalid value for "user_os", number of items must be greater than or equal to 1.')
1256
+ end
1257
+
1258
+ if !@user_device.nil? && @user_device.length < 1
1259
+ invalid_properties.push('invalid value for "user_device", number of items must be greater than or equal to 1.')
1260
+ end
1261
+
1214
1262
  invalid_properties
1215
1263
  end
1216
1264
 
@@ -1286,6 +1334,10 @@ module Zernio
1286
1334
  return false if !@dsa_payor.nil? && @dsa_payor.to_s.length > 100
1287
1335
  identity_type_validator = EnumAttributeValidator.new('String', ["TT_USER", "CUSTOMIZED_USER"])
1288
1336
  return false unless identity_type_validator.valid?(@identity_type)
1337
+ return false if !@user_os.nil? && @user_os.length < 1
1338
+ return false if !@user_device.nil? && @user_device.length < 1
1339
+ campaign_attribution_validator = EnumAttributeValidator.new('String', ["AEM", "SKADNETWORK"])
1340
+ return false unless campaign_attribution_validator.valid?(@campaign_attribution)
1289
1341
  true
1290
1342
  end
1291
1343
 
@@ -1867,6 +1919,44 @@ module Zernio
1867
1919
  @identity_type = identity_type
1868
1920
  end
1869
1921
 
1922
+ # Custom attribute writer method with validation
1923
+ # @param [Object] user_os Value to be assigned
1924
+ def user_os=(user_os)
1925
+ if user_os.nil?
1926
+ fail ArgumentError, 'user_os cannot be nil'
1927
+ end
1928
+
1929
+ if user_os.length < 1
1930
+ fail ArgumentError, 'invalid value for "user_os", number of items must be greater than or equal to 1.'
1931
+ end
1932
+
1933
+ @user_os = user_os
1934
+ end
1935
+
1936
+ # Custom attribute writer method with validation
1937
+ # @param [Object] user_device Value to be assigned
1938
+ def user_device=(user_device)
1939
+ if user_device.nil?
1940
+ fail ArgumentError, 'user_device cannot be nil'
1941
+ end
1942
+
1943
+ if user_device.length < 1
1944
+ fail ArgumentError, 'invalid value for "user_device", number of items must be greater than or equal to 1.'
1945
+ end
1946
+
1947
+ @user_device = user_device
1948
+ end
1949
+
1950
+ # Custom attribute writer method checking allowed values (enum).
1951
+ # @param [Object] campaign_attribution Object to be assigned
1952
+ def campaign_attribution=(campaign_attribution)
1953
+ validator = EnumAttributeValidator.new('String', ["AEM", "SKADNETWORK"])
1954
+ unless validator.valid?(campaign_attribution)
1955
+ fail ArgumentError, "invalid value for \"campaign_attribution\", must be one of #{validator.allowable_values}."
1956
+ end
1957
+ @campaign_attribution = campaign_attribution
1958
+ end
1959
+
1870
1960
  # Checks equality by comparing each attribute.
1871
1961
  # @param [Object] Object to be compared
1872
1962
  def ==(o)
@@ -1970,6 +2060,10 @@ module Zernio
1970
2060
  brand_identity == o.brand_identity &&
1971
2061
  identity_type == o.identity_type &&
1972
2062
  smart_plus == o.smart_plus &&
2063
+ user_os == o.user_os &&
2064
+ user_device == o.user_device &&
2065
+ is_skadnetwork_attribution == o.is_skadnetwork_attribution &&
2066
+ campaign_attribution == o.campaign_attribution &&
1973
2067
  promoted_object == o.promoted_object
1974
2068
  end
1975
2069
 
@@ -1982,7 +2076,7 @@ module Zernio
1982
2076
  # Calculates hash code according to all attributes.
1983
2077
  # @return [Integer] Hash code
1984
2078
  def hash
1985
- [account_id, ad_account_id, name, campaign_name, ad_set_name, ad_name, tracking, goal, optimization_goal, billing_event, buying_type, rf_prediction_id, promotion, creative_features, multi_advertiser, validate_only, budget_amount, budget_type, status, campaign_status, budget_level, currency, headline, long_headline, body, description, bodies, headlines, descriptions, call_to_action, link_url, lead_gen_form_id, image_url, images, video, creatives, ad_set_id, existing_campaign_id, existing_creative_id, business_name, board_id, organization_id, targeting, countries, cities, regions, age_min, age_max, interests, zips, metros, custom_locations, behaviors, work_positions, work_employers, work_industries, income_tier, languages, placements, saved_targeting_id, raw_targeting, special_ad_categories, special_ad_category_country, regional_regulated_categories, regional_regulation_identities, end_date, start_date, instagram_account_id, dynamic_creative, carousel_cards, default_locale, translations, placement_assets, audience_id, campaign_type, keywords, negative_keywords, campaign_negative_keywords, additional_headlines, additional_descriptions, sitelinks, callouts, structured_snippets, advantage_audience, attribution_spec, gender, bid_strategy, bid_amount, roas_average_floor, portfolio_bid_strategy_id, value_rule_set_id, value_rules_applied, platform_specific_data, dsa_beneficiary, dsa_payor, brand_identity, identity_type, smart_plus, promoted_object].hash
2079
+ [account_id, ad_account_id, name, campaign_name, ad_set_name, ad_name, tracking, goal, optimization_goal, billing_event, buying_type, rf_prediction_id, promotion, creative_features, multi_advertiser, validate_only, budget_amount, budget_type, status, campaign_status, budget_level, currency, headline, long_headline, body, description, bodies, headlines, descriptions, call_to_action, link_url, lead_gen_form_id, image_url, images, video, creatives, ad_set_id, existing_campaign_id, existing_creative_id, business_name, board_id, organization_id, targeting, countries, cities, regions, age_min, age_max, interests, zips, metros, custom_locations, behaviors, work_positions, work_employers, work_industries, income_tier, languages, placements, saved_targeting_id, raw_targeting, special_ad_categories, special_ad_category_country, regional_regulated_categories, regional_regulation_identities, end_date, start_date, instagram_account_id, dynamic_creative, carousel_cards, default_locale, translations, placement_assets, audience_id, campaign_type, keywords, negative_keywords, campaign_negative_keywords, additional_headlines, additional_descriptions, sitelinks, callouts, structured_snippets, advantage_audience, attribution_spec, gender, bid_strategy, bid_amount, roas_average_floor, portfolio_bid_strategy_id, value_rule_set_id, value_rules_applied, platform_specific_data, dsa_beneficiary, dsa_payor, brand_identity, identity_type, smart_plus, user_os, user_device, is_skadnetwork_attribution, campaign_attribution, promoted_object].hash
1986
2080
  end
1987
2081
 
1988
2082
  # Builds the object from hash
@@ -0,0 +1,104 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
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
+ module CreateStandaloneAdRequestAdditionalDescriptionsInner
18
+ class << self
19
+ # List of class defined in oneOf (OpenAPI v3)
20
+ def openapi_one_of
21
+ [
22
+ :'GoogleRsaDescription',
23
+ :'String'
24
+ ]
25
+ end
26
+
27
+ # Builds the object
28
+ # @param [Mixed] Data to be matched against the list of oneOf items
29
+ # @return [Object] Returns the model or the data itself
30
+ def build(data)
31
+ # Go through the list of oneOf items and attempt to identify the appropriate one.
32
+ # Note:
33
+ # - We do not attempt to check whether exactly one item matches.
34
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
35
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
36
+ # - TODO: scalar values are de facto behaving as if they were nullable.
37
+ # - TODO: logging when debugging is set.
38
+ openapi_one_of.each do |klass|
39
+ begin
40
+ next if klass == :AnyType # "nullable: true"
41
+ return find_and_cast_into_type(klass, data)
42
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
43
+ end
44
+ end
45
+
46
+ openapi_one_of.include?(:AnyType) ? data : nil
47
+ end
48
+
49
+ private
50
+
51
+ SchemaMismatchError = Class.new(StandardError)
52
+
53
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
54
+ def find_and_cast_into_type(klass, data)
55
+ return if data.nil?
56
+
57
+ case klass.to_s
58
+ when 'Boolean'
59
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
60
+ when 'Float'
61
+ return data if data.instance_of?(Float)
62
+ when 'Integer'
63
+ return data if data.instance_of?(Integer)
64
+ when 'Time'
65
+ return Time.parse(data)
66
+ when 'Date'
67
+ return Date.iso8601(data)
68
+ when 'String'
69
+ return data if data.instance_of?(String)
70
+ when 'Object' # "type: object"
71
+ return data if data.instance_of?(Hash)
72
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
73
+ if data.instance_of?(Array)
74
+ sub_type = Regexp.last_match[:sub_type]
75
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
76
+ end
77
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
78
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
79
+ sub_type = Regexp.last_match[:sub_type]
80
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
81
+ end
82
+ else # model
83
+ const = Zernio.const_get(klass)
84
+ if const
85
+ if const.respond_to?(:openapi_one_of) # nested oneOf model
86
+ model = const.build(data)
87
+ return model if model
88
+ else
89
+ # raise if data contains keys that are not known to the model
90
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
91
+ model = const.build_from_hash(data)
92
+ return model if model
93
+ end
94
+ end
95
+ end
96
+
97
+ raise # if no match by now, raise
98
+ rescue
99
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
100
+ end
101
+ end
102
+ end
103
+
104
+ end
@@ -0,0 +1,104 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
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
+ module CreateStandaloneAdRequestAdditionalHeadlinesInner
18
+ class << self
19
+ # List of class defined in oneOf (OpenAPI v3)
20
+ def openapi_one_of
21
+ [
22
+ :'GoogleRsaHeadline',
23
+ :'String'
24
+ ]
25
+ end
26
+
27
+ # Builds the object
28
+ # @param [Mixed] Data to be matched against the list of oneOf items
29
+ # @return [Object] Returns the model or the data itself
30
+ def build(data)
31
+ # Go through the list of oneOf items and attempt to identify the appropriate one.
32
+ # Note:
33
+ # - We do not attempt to check whether exactly one item matches.
34
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
35
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
36
+ # - TODO: scalar values are de facto behaving as if they were nullable.
37
+ # - TODO: logging when debugging is set.
38
+ openapi_one_of.each do |klass|
39
+ begin
40
+ next if klass == :AnyType # "nullable: true"
41
+ return find_and_cast_into_type(klass, data)
42
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
43
+ end
44
+ end
45
+
46
+ openapi_one_of.include?(:AnyType) ? data : nil
47
+ end
48
+
49
+ private
50
+
51
+ SchemaMismatchError = Class.new(StandardError)
52
+
53
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
54
+ def find_and_cast_into_type(klass, data)
55
+ return if data.nil?
56
+
57
+ case klass.to_s
58
+ when 'Boolean'
59
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
60
+ when 'Float'
61
+ return data if data.instance_of?(Float)
62
+ when 'Integer'
63
+ return data if data.instance_of?(Integer)
64
+ when 'Time'
65
+ return Time.parse(data)
66
+ when 'Date'
67
+ return Date.iso8601(data)
68
+ when 'String'
69
+ return data if data.instance_of?(String)
70
+ when 'Object' # "type: object"
71
+ return data if data.instance_of?(Hash)
72
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
73
+ if data.instance_of?(Array)
74
+ sub_type = Regexp.last_match[:sub_type]
75
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
76
+ end
77
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
78
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
79
+ sub_type = Regexp.last_match[:sub_type]
80
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
81
+ end
82
+ else # model
83
+ const = Zernio.const_get(klass)
84
+ if const
85
+ if const.respond_to?(:openapi_one_of) # nested oneOf model
86
+ model = const.build(data)
87
+ return model if model
88
+ else
89
+ # raise if data contains keys that are not known to the model
90
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
91
+ model = const.build_from_hash(data)
92
+ return model if model
93
+ end
94
+ end
95
+ end
96
+
97
+ raise # if no match by now, raise
98
+ rescue
99
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
100
+ end
101
+ end
102
+ end
103
+
104
+ end
@@ -19,6 +19,8 @@ module Zernio
19
19
  # Meta enhancement settings for single or attached ads, and defaults for creatives[]. An item replaces the entire map, including with an empty object.
20
20
  attr_accessor :creative_features
21
21
 
22
+ attr_accessor :tracking
23
+
22
24
  # Facebook or Instagram SocialAccount ID.
23
25
  attr_accessor :account_id
24
26
 
@@ -156,6 +158,7 @@ module Zernio
156
158
  def self.attribute_map
157
159
  {
158
160
  :'creative_features' => :'creativeFeatures',
161
+ :'tracking' => :'tracking',
159
162
  :'account_id' => :'accountId',
160
163
  :'ad_account_id' => :'adAccountId',
161
164
  :'name' => :'name',
@@ -212,6 +215,7 @@ module Zernio
212
215
  def self.openapi_types
213
216
  {
214
217
  :'creative_features' => :'Hash<String, String>',
218
+ :'tracking' => :'AdTracking',
215
219
  :'account_id' => :'String',
216
220
  :'ad_account_id' => :'String',
217
221
  :'name' => :'String',
@@ -282,6 +286,10 @@ module Zernio
282
286
  end
283
287
  end
284
288
 
289
+ if attributes.key?(:'tracking')
290
+ self.tracking = attributes[:'tracking']
291
+ end
292
+
285
293
  if attributes.key?(:'account_id')
286
294
  self.account_id = attributes[:'account_id']
287
295
  else
@@ -879,6 +887,7 @@ module Zernio
879
887
  return true if self.equal?(o)
880
888
  self.class == o.class &&
881
889
  creative_features == o.creative_features &&
890
+ tracking == o.tracking &&
882
891
  account_id == o.account_id &&
883
892
  ad_account_id == o.ad_account_id &&
884
893
  name == o.name &&
@@ -929,7 +938,7 @@ module Zernio
929
938
  # Calculates hash code according to all attributes.
930
939
  # @return [Integer] Hash code
931
940
  def hash
932
- [creative_features, account_id, ad_account_id, name, existing_post_id, object_story_id, whatsapp_phone_number, headline, body, image_url, video, welcome_message, creatives, ad_set_id, budget_amount, budget_type, currency, end_date, countries, cities, regions, zips, metros, custom_locations, age_min, age_max, interests, audience_id, placements, advantage_audience, objective, status, campaign_status, bid_strategy, bid_amount, roas_average_floor, dsa_beneficiary, dsa_payor, regional_regulated_categories, regional_regulation_identities].hash
941
+ [creative_features, tracking, account_id, ad_account_id, name, existing_post_id, object_story_id, whatsapp_phone_number, headline, body, image_url, video, welcome_message, creatives, ad_set_id, budget_amount, budget_type, currency, end_date, countries, cities, regions, zips, metros, custom_locations, age_min, age_max, interests, audience_id, placements, advantage_audience, objective, status, campaign_status, bid_strategy, bid_amount, roas_average_floor, dsa_beneficiary, dsa_payor, regional_regulated_categories, regional_regulation_identities].hash
933
942
  end
934
943
 
935
944
  # Builds the object from hash
@@ -17,10 +17,18 @@ module Zernio
17
17
  class GetAd200Response < ApiModelBase
18
18
  attr_accessor :ad
19
19
 
20
+ # Google RSA details cache timestamp.
21
+ attr_accessor :cached_at
22
+
23
+ # Whether Google RSA details use the last successful cached response.
24
+ attr_accessor :stale
25
+
20
26
  # Attribute mapping from ruby-style variable name to JSON key.
21
27
  def self.attribute_map
22
28
  {
23
- :'ad' => :'ad'
29
+ :'ad' => :'ad',
30
+ :'cached_at' => :'cachedAt',
31
+ :'stale' => :'stale'
24
32
  }
25
33
  end
26
34
 
@@ -37,13 +45,16 @@ module Zernio
37
45
  # Attribute type mapping.
38
46
  def self.openapi_types
39
47
  {
40
- :'ad' => :'Ad'
48
+ :'ad' => :'Ad',
49
+ :'cached_at' => :'Time',
50
+ :'stale' => :'Boolean'
41
51
  }
42
52
  end
43
53
 
44
54
  # List of attributes with nullable: true
45
55
  def self.openapi_nullable
46
56
  Set.new([
57
+ :'cached_at',
47
58
  ])
48
59
  end
49
60
 
@@ -66,6 +77,14 @@ module Zernio
66
77
  if attributes.key?(:'ad')
67
78
  self.ad = attributes[:'ad']
68
79
  end
80
+
81
+ if attributes.key?(:'cached_at')
82
+ self.cached_at = attributes[:'cached_at']
83
+ end
84
+
85
+ if attributes.key?(:'stale')
86
+ self.stale = attributes[:'stale']
87
+ end
69
88
  end
70
89
 
71
90
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -88,7 +107,9 @@ module Zernio
88
107
  def ==(o)
89
108
  return true if self.equal?(o)
90
109
  self.class == o.class &&
91
- ad == o.ad
110
+ ad == o.ad &&
111
+ cached_at == o.cached_at &&
112
+ stale == o.stale
92
113
  end
93
114
 
94
115
  # @see the `==` method
@@ -100,7 +121,7 @@ module Zernio
100
121
  # Calculates hash code according to all attributes.
101
122
  # @return [Integer] Hash code
102
123
  def hash
103
- [ad].hash
124
+ [ad, cached_at, stale].hash
104
125
  end
105
126
 
106
127
  # Builds the object from hash