late-sdk 0.0.706 → 0.0.708

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/docs/AdInsightsApi.md +84 -0
  4. data/docs/BoostPostRequest.md +4 -4
  5. data/docs/BoostPostRequestPlatformSpecificData.md +49 -0
  6. data/docs/CreateStandaloneAdRequest.md +4 -4
  7. data/docs/GetAdsSearchTerms200Response.md +22 -0
  8. data/docs/GetAdsSearchTerms200ResponseDataInner.md +40 -0
  9. data/docs/GetAdsSearchTerms200ResponsePaging.md +18 -0
  10. data/docs/InstagramApi.md +1 -1
  11. data/docs/MetaAdsPlatformData.md +22 -0
  12. data/docs/WebhookPayloadCommentPost.md +7 -1
  13. data/lib/zernio-sdk/api/ad_insights_api.rb +82 -0
  14. data/lib/zernio-sdk/api/instagram_api.rb +2 -2
  15. data/lib/zernio-sdk/models/boost_post_request.rb +4 -4
  16. data/lib/zernio-sdk/models/boost_post_request_platform_specific_data.rb +105 -0
  17. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +4 -4
  18. data/lib/zernio-sdk/models/get_ads_search_terms200_response.rb +167 -0
  19. data/lib/zernio-sdk/models/get_ads_search_terms200_response_data_inner.rb +256 -0
  20. data/lib/zernio-sdk/models/get_ads_search_terms200_response_paging.rb +149 -0
  21. data/lib/zernio-sdk/models/meta_ads_platform_data.rb +190 -0
  22. data/lib/zernio-sdk/models/webhook_payload_comment_post.rb +43 -4
  23. data/lib/zernio-sdk/version.rb +1 -1
  24. data/lib/zernio-sdk.rb +5 -0
  25. data/openapi.yaml +117 -6
  26. data/spec/api/ad_insights_api_spec.rb +18 -0
  27. data/spec/api/instagram_api_spec.rb +1 -1
  28. data/spec/models/boost_post_request_platform_specific_data_spec.rb +32 -0
  29. data/spec/models/get_ads_search_terms200_response_data_inner_spec.rb +102 -0
  30. data/spec/models/get_ads_search_terms200_response_paging_spec.rb +36 -0
  31. data/spec/models/get_ads_search_terms200_response_spec.rb +48 -0
  32. data/spec/models/meta_ads_platform_data_spec.rb +48 -0
  33. data/spec/models/webhook_payload_comment_post_spec.rb +18 -0
  34. data/zernio-sdk-0.0.708.gem +0 -0
  35. metadata +22 -2
  36. data/zernio-sdk-0.0.706.gem +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23493505389729d733a3b114769588beb167d3deade4ec9608ac268f533646e2
4
- data.tar.gz: e801174f0890775b789ba99e0431b60fb68974b59f44bdb625f3d58239bb8321
3
+ metadata.gz: 3c34dfdabf2f2c5dafd46432a84beaca01e810c064ebb93c47efc104472a8c3e
4
+ data.tar.gz: 1182e68c0b5942deb1272d01696f2d125811a2ee03df7ce661b30d4a907ad1fe
5
5
  SHA512:
6
- metadata.gz: 0fa5f8ec5def8d794451a547435cc33ea44d4629d054a63224cbdfcb17e0ebad089d7b3506c54d6e2e2a745d937e743accd72dce81675aa6a4c86b7f6e042ef1
7
- data.tar.gz: 30afe3646f4e3e36bda0acdaf7961d0023fe4814d56b83f305e5ecf48493b079ab873f6906ba6920a70ee67572a937df7ce74bbeb3c24994ca4f40099d75d6d4
6
+ metadata.gz: 8589db83792f8f9304bd33ac6dfefcec042e36c22acfc8fa77014488eda10bbea423c6b7ad55eea02a515ce3b995313a03a6ce3db5370dae1d29eb1fb1d835a7
7
+ data.tar.gz: bb1a8a8af527ab0a383c7d6f92c9d9713ae91a4ca7ef675a713abc68eda372ac24b17780bab29b5770ee202c0d9d07d978fe489b43471be144a6955395a1b054
data/README.md CHANGED
@@ -158,6 +158,7 @@ Class | Method | HTTP request | Description
158
158
  *Zernio::AdInsightsApi* | [**generate_keyword_ideas**](docs/AdInsightsApi.md#generate_keyword_ideas) | **POST** /v1/ads/keywords/ideas | Generate keyword ideas (Google Keyword Planner)
159
159
  *Zernio::AdInsightsApi* | [**get_ad_analytics**](docs/AdInsightsApi.md#get_ad_analytics) | **GET** /v1/ads/{adId}/analytics | Get ad analytics
160
160
  *Zernio::AdInsightsApi* | [**get_ad_insights_report**](docs/AdInsightsApi.md#get_ad_insights_report) | **GET** /v1/ads/insights/reports/{reportRunId} | Poll an async insights report run
161
+ *Zernio::AdInsightsApi* | [**get_ads_search_terms**](docs/AdInsightsApi.md#get_ads_search_terms) | **GET** /v1/ads/search-terms | Google Ads search terms report
161
162
  *Zernio::AdInsightsApi* | [**get_campaign_analytics**](docs/AdInsightsApi.md#get_campaign_analytics) | **GET** /v1/ads/campaigns/{campaignId}/analytics | Get campaign analytics
162
163
  *Zernio::AdInsightsApi* | [**query_ad_insights**](docs/AdInsightsApi.md#query_ad_insights) | **GET** /v1/ads/insights | Flexible live insights query
163
164
  *Zernio::AdTargetingApi* | [**estimate_ad_reach**](docs/AdTargetingApi.md#estimate_ad_reach) | **POST** /v1/ads/targeting/reach-estimate | Estimate audience reach
@@ -703,6 +704,7 @@ Class | Method | HTTP request | Description
703
704
  - [Zernio::BookmarkPostRequest](docs/BookmarkPostRequest.md)
704
705
  - [Zernio::BoostPostRequest](docs/BoostPostRequest.md)
705
706
  - [Zernio::BoostPostRequestBudget](docs/BoostPostRequestBudget.md)
707
+ - [Zernio::BoostPostRequestPlatformSpecificData](docs/BoostPostRequestPlatformSpecificData.md)
706
708
  - [Zernio::BoostPostRequestSchedule](docs/BoostPostRequestSchedule.md)
707
709
  - [Zernio::BoostPostRequestTargeting](docs/BoostPostRequestTargeting.md)
708
710
  - [Zernio::BoostPostRequestTargetingCitiesInner](docs/BoostPostRequestTargetingCitiesInner.md)
@@ -1065,6 +1067,9 @@ Class | Method | HTTP request | Description
1065
1067
  - [Zernio::GetAdTree200Response](docs/GetAdTree200Response.md)
1066
1068
  - [Zernio::GetAdsActivityLog200Response](docs/GetAdsActivityLog200Response.md)
1067
1069
  - [Zernio::GetAdsActivityLog200ResponsePaging](docs/GetAdsActivityLog200ResponsePaging.md)
1070
+ - [Zernio::GetAdsSearchTerms200Response](docs/GetAdsSearchTerms200Response.md)
1071
+ - [Zernio::GetAdsSearchTerms200ResponseDataInner](docs/GetAdsSearchTerms200ResponseDataInner.md)
1072
+ - [Zernio::GetAdsSearchTerms200ResponsePaging](docs/GetAdsSearchTerms200ResponsePaging.md)
1068
1073
  - [Zernio::GetAdsTimeline200Response](docs/GetAdsTimeline200Response.md)
1069
1074
  - [Zernio::GetAdsTimeline200ResponseRowsInner](docs/GetAdsTimeline200ResponseRowsInner.md)
1070
1075
  - [Zernio::GetAllAccountsHealth200Response](docs/GetAllAccountsHealth200Response.md)
@@ -1602,6 +1607,7 @@ Class | Method | HTTP request | Description
1602
1607
  - [Zernio::MarkConversationRead200Response](docs/MarkConversationRead200Response.md)
1603
1608
  - [Zernio::MediaItem](docs/MediaItem.md)
1604
1609
  - [Zernio::MediaUploadResponse](docs/MediaUploadResponse.md)
1610
+ - [Zernio::MetaAdsPlatformData](docs/MetaAdsPlatformData.md)
1605
1611
  - [Zernio::MetaLeadFormPlatformData](docs/MetaLeadFormPlatformData.md)
1606
1612
  - [Zernio::MetaLeadFormPlatformDataContextCard](docs/MetaLeadFormPlatformDataContextCard.md)
1607
1613
  - [Zernio::Money](docs/Money.md)
@@ -9,6 +9,7 @@ All URIs are relative to *https://zernio.com/api*
9
9
  | [**generate_keyword_ideas**](AdInsightsApi.md#generate_keyword_ideas) | **POST** /v1/ads/keywords/ideas | Generate keyword ideas (Google Keyword Planner) |
10
10
  | [**get_ad_analytics**](AdInsightsApi.md#get_ad_analytics) | **GET** /v1/ads/{adId}/analytics | Get ad analytics |
11
11
  | [**get_ad_insights_report**](AdInsightsApi.md#get_ad_insights_report) | **GET** /v1/ads/insights/reports/{reportRunId} | Poll an async insights report run |
12
+ | [**get_ads_search_terms**](AdInsightsApi.md#get_ads_search_terms) | **GET** /v1/ads/search-terms | Google Ads search terms report |
12
13
  | [**get_campaign_analytics**](AdInsightsApi.md#get_campaign_analytics) | **GET** /v1/ads/campaigns/{campaignId}/analytics | Get campaign analytics |
13
14
  | [**query_ad_insights**](AdInsightsApi.md#query_ad_insights) | **GET** /v1/ads/insights | Flexible live insights query |
14
15
 
@@ -374,6 +375,89 @@ end
374
375
  - **Accept**: application/json
375
376
 
376
377
 
378
+ ## get_ads_search_terms
379
+
380
+ > <GetAdsSearchTerms200Response> get_ads_search_terms(account_id, opts)
381
+
382
+ Google Ads search terms report
383
+
384
+ The actual search queries that triggered your ads, with matched-keyword status and spend metrics — the raw material for wasted-spend analysis and negative-keyword lists. Reads Google's `search_term_view` live; defaults to the last 30 days. Rows are ordered by cost, descending. Draws on the shared Google Ads operations budget.
385
+
386
+ ### Examples
387
+
388
+ ```ruby
389
+ require 'time'
390
+ require 'zernio-sdk'
391
+ # setup authorization
392
+ Zernio.configure do |config|
393
+ # Configure Bearer authorization (JWT): bearerAuth
394
+ config.access_token = 'YOUR_BEARER_TOKEN'
395
+ end
396
+
397
+ api_instance = Zernio::AdInsightsApi.new
398
+ account_id = 'account_id_example' # String | Google ads SocialAccount id.
399
+ opts = {
400
+ customer_id: 'customer_id_example', # String | Numeric Google Ads customer id (no dashes). Defaults to the account's connected customer.
401
+ from_date: Date.parse('2013-10-20'), # Date | Defaults to 30 days ago.
402
+ to_date: Date.parse('2013-10-20'), # Date | Defaults to today.
403
+ campaign_id: 'campaign_id_example', # String | Numeric Google campaign id filter.
404
+ ad_group_id: 'ad_group_id_example', # String | Numeric Google ad group id filter.
405
+ page_token: 'page_token_example' # String | Cursor from paging.nextPageToken of the previous page.
406
+ }
407
+
408
+ begin
409
+ # Google Ads search terms report
410
+ result = api_instance.get_ads_search_terms(account_id, opts)
411
+ p result
412
+ rescue Zernio::ApiError => e
413
+ puts "Error when calling AdInsightsApi->get_ads_search_terms: #{e}"
414
+ end
415
+ ```
416
+
417
+ #### Using the get_ads_search_terms_with_http_info variant
418
+
419
+ This returns an Array which contains the response data, status code and headers.
420
+
421
+ > <Array(<GetAdsSearchTerms200Response>, Integer, Hash)> get_ads_search_terms_with_http_info(account_id, opts)
422
+
423
+ ```ruby
424
+ begin
425
+ # Google Ads search terms report
426
+ data, status_code, headers = api_instance.get_ads_search_terms_with_http_info(account_id, opts)
427
+ p status_code # => 2xx
428
+ p headers # => { ... }
429
+ p data # => <GetAdsSearchTerms200Response>
430
+ rescue Zernio::ApiError => e
431
+ puts "Error when calling AdInsightsApi->get_ads_search_terms_with_http_info: #{e}"
432
+ end
433
+ ```
434
+
435
+ ### Parameters
436
+
437
+ | Name | Type | Description | Notes |
438
+ | ---- | ---- | ----------- | ----- |
439
+ | **account_id** | **String** | Google ads SocialAccount id. | |
440
+ | **customer_id** | **String** | Numeric Google Ads customer id (no dashes). Defaults to the account&#39;s connected customer. | [optional] |
441
+ | **from_date** | **Date** | Defaults to 30 days ago. | [optional] |
442
+ | **to_date** | **Date** | Defaults to today. | [optional] |
443
+ | **campaign_id** | **String** | Numeric Google campaign id filter. | [optional] |
444
+ | **ad_group_id** | **String** | Numeric Google ad group id filter. | [optional] |
445
+ | **page_token** | **String** | Cursor from paging.nextPageToken of the previous page. | [optional] |
446
+
447
+ ### Return type
448
+
449
+ [**GetAdsSearchTerms200Response**](GetAdsSearchTerms200Response.md)
450
+
451
+ ### Authorization
452
+
453
+ [bearerAuth](../README.md#bearerAuth)
454
+
455
+ ### HTTP request headers
456
+
457
+ - **Content-Type**: Not defined
458
+ - **Accept**: application/json
459
+
460
+
377
461
  ## get_campaign_analytics
378
462
 
379
463
  > <GetCampaignAnalytics200Response> get_campaign_analytics(campaign_id, opts)
@@ -18,10 +18,10 @@
18
18
  | **schedule** | [**BoostPostRequestSchedule**](BoostPostRequestSchedule.md) | | [optional] |
19
19
  | **targeting** | [**BoostPostRequestTargeting**](BoostPostRequestTargeting.md) | | [optional] |
20
20
  | **raw_targeting** | **Hash&lt;String, Object&gt;** | Meta only. A Meta-native targeting spec (e.g. &#x60;{ \&quot;geo_locations\&quot;: { \&quot;cities\&quot;: [{ \&quot;key\&quot;: \&quot;...\&quot;, \&quot;radius\&quot;: 15, \&quot;distance_unit\&quot;: \&quot;kilometer\&quot; }] } }&#x60;). Sent alone it is forwarded unchanged. Use for advanced fields the structured object does not expose (flexible_spec, excluded audiences, business places, user_os, wireless_carrier). Can be combined with &#x60;targeting&#x60;: rawTargeting is the BASE layer and the built camelCase spec is merged on top, key by key (camelCase wins on collision). The merge goes one level deep inside &#x60;geo_locations&#x60; and &#x60;excluded_geo_locations&#x60; (built sub-keys win; raw-only sub-keys such as &#x60;location_types&#x60; survive). Array values (&#x60;flexible_spec&#x60;, ...) are replaced as a whole key, never element-merged. When &#x60;rawTargeting&#x60; is present the &#x60;advantage_audience: 0&#x60; default that Zernio normally applies is no longer emitted, so it cannot clobber a &#x60;targeting_automation&#x60; sent in the raw spec. Meta requires &#x60;targeting_automation&#x60; on ad set creation, so include it in the raw spec, or send &#x60;targeting.advantage_audience&#x60; (0 or 1), which is merged over raw as &#x60;targeting_automation&#x60;. | [optional] |
21
- | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | Meta bid strategy applied to the ad set. On TikTok, mapped to &#x60;bid_type&#x60; / &#x60;bid_price&#x60; / &#x60;deep_bid_type&#x60; automatically. | [optional] |
22
- | **bid_amount** | **Float** | Bid cap in WHOLE currency units (USD: 5 &#x3D; $5.00; JPY: 100 &#x3D; ¥100). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_BID_CAP&#x60; or &#x60;COST_CAP&#x60;. Backward-compat: providing &#x60;bidAmount&#x60; without &#x60;bidStrategy&#x60; is treated as &#x60;LOWEST_COST_WITH_BID_CAP&#x60;. | [optional] |
23
- | **roas_average_floor** | **Float** | Minimum ROAS as a decimal multiplier (e.g. 2.0 &#x3D; 2.0x ROAS). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_MIN_ROAS&#x60;. Sent to Meta as &#x60;bid_constraints.roas_average_floor&#x60; × 10000 (Meta uses fixed-point integers). | [optional] |
24
- | **platform_specific_data** | [**LinkedInAdsPlatformData**](LinkedInAdsPlatformData.md) | | [optional] |
21
+ | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | Deprecated: send it inside &#x60;platformSpecificData&#x60; instead (Meta today; TikTok&#39;s nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Meta bid strategy applied to the ad set. On TikTok, mapped to &#x60;bid_type&#x60; / &#x60;bid_price&#x60; / &#x60;deep_bid_type&#x60; automatically. | [optional] |
22
+ | **bid_amount** | **Float** | Deprecated: send it inside &#x60;platformSpecificData&#x60; instead (Meta today; TikTok&#39;s nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Bid cap in WHOLE currency units (USD: 5 &#x3D; $5.00; JPY: 100 &#x3D; ¥100). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_BID_CAP&#x60; or &#x60;COST_CAP&#x60;. Backward-compat: providing &#x60;bidAmount&#x60; without &#x60;bidStrategy&#x60; is treated as &#x60;LOWEST_COST_WITH_BID_CAP&#x60;. | [optional] |
23
+ | **roas_average_floor** | **Float** | Deprecated: send it inside &#x60;platformSpecificData&#x60; instead (Meta today; TikTok&#39;s nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Minimum ROAS as a decimal multiplier (e.g. 2.0 &#x3D; 2.0x ROAS). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_MIN_ROAS&#x60;. Sent to Meta as &#x60;bid_constraints.roas_average_floor&#x60; × 10000 (Meta uses fixed-point integers). | [optional] |
24
+ | **platform_specific_data** | [**BoostPostRequestPlatformSpecificData**](BoostPostRequestPlatformSpecificData.md) | | [optional] |
25
25
  | **tracking** | [**BoostPostRequestTracking**](BoostPostRequestTracking.md) | | [optional] |
26
26
  | **special_ad_categories** | **Array&lt;String&gt;** | Meta only. Required for housing, employment, credit, or political ads. | [optional] |
27
27
  | **special_ad_category_country** | **Array&lt;String&gt;** | Meta (metaads) only. 2-letter ISO country codes the special ad category applies to. Requires specialAdCategories to be set (400 otherwise). | [optional] |
@@ -0,0 +1,49 @@
1
+ # Zernio::BoostPostRequestPlatformSpecificData
2
+
3
+ ## Class instance methods
4
+
5
+ ### `openapi_one_of`
6
+
7
+ Returns the list of classes defined in oneOf.
8
+
9
+ #### Example
10
+
11
+ ```ruby
12
+ require 'zernio-sdk'
13
+
14
+ Zernio::BoostPostRequestPlatformSpecificData.openapi_one_of
15
+ # =>
16
+ # [
17
+ # :'LinkedInAdsPlatformData',
18
+ # :'MetaAdsPlatformData'
19
+ # ]
20
+ ```
21
+
22
+ ### build
23
+
24
+ Find the appropriate object from the `openapi_one_of` list and casts the data into it.
25
+
26
+ #### Example
27
+
28
+ ```ruby
29
+ require 'zernio-sdk'
30
+
31
+ Zernio::BoostPostRequestPlatformSpecificData.build(data)
32
+ # => #<LinkedInAdsPlatformData:0x00007fdd4aab02a0>
33
+
34
+ Zernio::BoostPostRequestPlatformSpecificData.build(data_that_doesnt_match)
35
+ # => nil
36
+ ```
37
+
38
+ #### Parameters
39
+
40
+ | Name | Type | Description |
41
+ | ---- | ---- | ----------- |
42
+ | **data** | **Mixed** | data to be matched against the list of oneOf items |
43
+
44
+ #### Return type
45
+
46
+ - `LinkedInAdsPlatformData`
47
+ - `MetaAdsPlatformData`
48
+ - `nil` (if no type matches)
49
+
@@ -75,12 +75,12 @@
75
75
  | **advantage_audience** | **Integer** | Meta only. Controls the Advantage audience feature (targeting_automation). 0 &#x3D; disabled (default), 1 &#x3D; enabled. Meta Marketing API requires this field on all ad set creation requests. | [optional] |
76
76
  | **attribution_spec** | [**Array&lt;CreateStandaloneAdRequestAttributionSpecInner&gt;**](CreateStandaloneAdRequestAttributionSpecInner.md) | Meta only. Conversion attribution window for the ad set — maps 1:1 to Meta&#39;s ad-set &#x60;attribution_spec&#x60;. Only honored for conversion goals (&#x60;conversions&#x60;, &#x60;lead_generation&#x60;, &#x60;app_promotion&#x60;); ignored for awareness/traffic/engagement. Omit to use Meta&#39;s default (&#x60;7-day click&#x60; + &#x60;1-day view&#x60;). Meta enforces the valid combinations: &#x60;VIEW_THROUGH&#x60; only allows &#x60;windowDays: 1&#x60; (7d/28d view windows were removed Jan 2026); &#x60;ENGAGED_VIDEO_VIEW&#x60; only &#x60;1&#x60; and only alongside &#x60;VIEW_THROUGH: 1&#x60;; &#x60;CLICK_THROUGH: 28&#x60; only on certain objectives. Invalid combos surface as a Meta 400. Example: &#x60;[{ \&quot;eventType\&quot;: \&quot;CLICK_THROUGH\&quot;, \&quot;windowDays\&quot;: 7 }, { \&quot;eventType\&quot;: \&quot;VIEW_THROUGH\&quot;, \&quot;windowDays\&quot;: 1 }]&#x60; | [optional] |
77
77
  | **gender** | **String** | Restrict the audience by gender. &#39;male&#39; targets men only, &#39;female&#39; targets women only, &#39;all&#39; (default) targets everyone. Applied on Meta, TikTok and Pinterest. Ignored on Google, LinkedIn and X. | [optional][default to &#39;all&#39;] |
78
- | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | Meta bid strategy applied to the ad set. | [optional] |
79
- | **bid_amount** | **Float** | Bid cap in WHOLE currency units (USD: 5 &#x3D; $5.00; JPY: 100 &#x3D; ¥100). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_BID_CAP&#x60; or &#x60;COST_CAP&#x60;. | [optional] |
80
- | **roas_average_floor** | **Float** | Minimum ROAS as a decimal multiplier (e.g. 2.0 &#x3D; 2.0x ROAS). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_MIN_ROAS&#x60;. Sent to Meta as &#x60;bid_constraints.roas_average_floor&#x60; × 10000. | [optional] |
78
+ | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | Deprecated: send it inside &#x60;platformSpecificData&#x60; instead (Meta today; TikTok&#39;s nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Meta bid strategy applied to the ad set. | [optional] |
79
+ | **bid_amount** | **Float** | Deprecated: send it inside &#x60;platformSpecificData&#x60; instead (Meta today; TikTok&#39;s nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Bid cap in WHOLE currency units (USD: 5 &#x3D; $5.00; JPY: 100 &#x3D; ¥100). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_BID_CAP&#x60; or &#x60;COST_CAP&#x60;. | [optional] |
80
+ | **roas_average_floor** | **Float** | Deprecated: send it inside &#x60;platformSpecificData&#x60; instead (Meta today; TikTok&#39;s nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Minimum ROAS as a decimal multiplier (e.g. 2.0 &#x3D; 2.0x ROAS). Required when &#x60;bidStrategy&#x60; is &#x60;LOWEST_COST_WITH_MIN_ROAS&#x60;. Sent to Meta as &#x60;bid_constraints.roas_average_floor&#x60; × 10000. | [optional] |
81
81
  | **value_rule_set_id** | **String** | Meta only (facebook, instagram; other platforms return 400). Value rule set to attach to the new ad set, from &#x60;/v1/ads/value-rule-sets&#x60;. Attachment is driven by this id, so &#x60;valueRulesApplied&#x60; is optional alongside it. Rejected with 400 in &#x60;adSetId&#x60; attach mode: that shape inherits the existing ad set&#39;s attachment, so the field would be silently ignored. Use &#x60;PUT /v1/ads/ad-sets/{adSetId}&#x60; there instead. Ignored (stripped before the ad-set create) when &#x60;buyingType&#x60; is &#x60;RESERVED&#x60;: value rules only apply to auction ad sets on &#x60;LOWEST_COST_WITHOUT_CAP&#x60; or &#x60;COST_CAP&#x60;, and a Reach &amp; Frequency reservation has no auction bid strategy. Read back with &#x60;GET /v1/ads/ad-sets/{adSetId}?fields&#x3D;value_rule_set_id&#x60;; the attachment is not mirrored onto Zernio&#39;s ad documents. | [optional] |
82
82
  | **value_rules_applied** | **Boolean** | Meta only (facebook, instagram; other platforms return 400). Optional when attaching, and requires &#x60;valueRuleSetId&#x60;. &#x60;false&#x60; is REJECTED here with 400: a newly created ad set has nothing to detach, so detaching lives on &#x60;PUT /v1/ads/ad-sets/{adSetId}&#x60;. | [optional] |
83
- | **platform_specific_data** | [**LinkedInAdsPlatformData**](LinkedInAdsPlatformData.md) | | [optional] |
83
+ | **platform_specific_data** | [**BoostPostRequestPlatformSpecificData**](BoostPostRequestPlatformSpecificData.md) | | [optional] |
84
84
  | **dsa_beneficiary** | **String** | Legal entity that benefits from the ad. Required when targeting EU users (EU DSA, Article 26). Optional if the ad account has a default beneficiary: set it once via &#x60;PATCH /v1/ads/accounts&#x60; or in Meta Ads Manager, and Meta fills it in whenever the field is omitted. | [optional] |
85
85
  | **dsa_payor** | **String** | Legal entity that pays for the ad. Can differ from &#x60;dsaBeneficiary&#x60; (for example, an agency paying for a client&#39;s ads). Same rules as &#x60;dsaBeneficiary&#x60;: required for EU targeting unless the ad account has a default payor. | [optional] |
86
86
  | **brand_identity** | [**CreateStandaloneAdRequestBrandIdentity**](CreateStandaloneAdRequestBrandIdentity.md) | | [optional] |
@@ -0,0 +1,22 @@
1
+ # Zernio::GetAdsSearchTerms200Response
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **customer_id** | **String** | | [optional] |
8
+ | **data** | [**Array&lt;GetAdsSearchTerms200ResponseDataInner&gt;**](GetAdsSearchTerms200ResponseDataInner.md) | | [optional] |
9
+ | **paging** | [**GetAdsSearchTerms200ResponsePaging**](GetAdsSearchTerms200ResponsePaging.md) | | [optional] |
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ require 'zernio-sdk'
15
+
16
+ instance = Zernio::GetAdsSearchTerms200Response.new(
17
+ customer_id: null,
18
+ data: null,
19
+ paging: null
20
+ )
21
+ ```
22
+
@@ -0,0 +1,40 @@
1
+ # Zernio::GetAdsSearchTerms200ResponseDataInner
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **search_term** | **String** | | [optional] |
8
+ | **status** | **String** | ADDED / EXCLUDED / ADDED_EXCLUDED / NONE — whether the term is already a keyword or a negative. | [optional] |
9
+ | **match_type** | **String** | How the term matched (BROAD, PHRASE, EXACT, NEAR_PHRASE, NEAR_EXACT). | [optional] |
10
+ | **campaign_id** | **String** | | [optional] |
11
+ | **campaign_name** | **String** | | [optional] |
12
+ | **ad_group_id** | **String** | | [optional] |
13
+ | **ad_group_name** | **String** | | [optional] |
14
+ | **impressions** | **Integer** | | [optional] |
15
+ | **clicks** | **Integer** | | [optional] |
16
+ | **cost_micros** | **Integer** | Cost in micros of the account currency (divide by 1,000,000). | [optional] |
17
+ | **conversions** | **Float** | | [optional] |
18
+ | **conversions_value** | **Float** | | [optional] |
19
+
20
+ ## Example
21
+
22
+ ```ruby
23
+ require 'zernio-sdk'
24
+
25
+ instance = Zernio::GetAdsSearchTerms200ResponseDataInner.new(
26
+ search_term: null,
27
+ status: null,
28
+ match_type: null,
29
+ campaign_id: null,
30
+ campaign_name: null,
31
+ ad_group_id: null,
32
+ ad_group_name: null,
33
+ impressions: null,
34
+ clicks: null,
35
+ cost_micros: null,
36
+ conversions: null,
37
+ conversions_value: null
38
+ )
39
+ ```
40
+
@@ -0,0 +1,18 @@
1
+ # Zernio::GetAdsSearchTerms200ResponsePaging
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **next_page_token** | **String** | Null when the last page was returned. | [optional] |
8
+
9
+ ## Example
10
+
11
+ ```ruby
12
+ require 'zernio-sdk'
13
+
14
+ instance = Zernio::GetAdsSearchTerms200ResponsePaging.new(
15
+ next_page_token: null
16
+ )
17
+ ```
18
+
data/docs/InstagramApi.md CHANGED
@@ -84,7 +84,7 @@ end
84
84
 
85
85
  Get Instagram story insights
86
86
 
87
- Returns metrics for a single story. The `source` field discriminates between three states: - `live` — fetched from Meta in real time (story is still active) - `cached` — fetched from a persisted `story_insights` webhook payload (story has expired but we received its final-state metrics from Meta) - `unavailable` — story has expired and we never received its webhook payload (for example, the account connected after the story expired) Field semantics follow Meta's API. Counts below 5 may be returned as 0 due to Meta's privacy floor on small audiences. The `navigation` field is the sum of `tapsForward + tapsBack + exits + swipesForward`.
87
+ Returns metrics for a single story. The `source` field discriminates between three states: - `live` — fetched from Meta in real time (story is still active) - `cached` — fetched from a persisted `story_insights` webhook payload (story has expired but we received its final-state metrics from Meta) - `unavailable` — story has expired and we never received its webhook payload (for example, the account connected after the story expired) Meta can report an expired story as an empty successful result rather than an error, so an expired story resolves to `cached` or `unavailable` even though the upstream request itself succeeded. Field semantics follow Meta's API. Counts below 5 may be returned as 0 due to Meta's privacy floor on small audiences. The `navigation` field is the sum of `tapsForward + tapsBack + exits + swipesForward`.
88
88
 
89
89
  ### Examples
90
90
 
@@ -0,0 +1,22 @@
1
+ # Zernio::MetaAdsPlatformData
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | | [optional] |
8
+ | **bid_amount** | **Float** | Whole currency units (USD: 5 &#x3D; $5.00). Required when bidStrategy is LOWEST_COST_WITH_BID_CAP or COST_CAP. | [optional] |
9
+ | **roas_average_floor** | **Float** | Decimal ROAS multiplier (2.0 &#x3D; 2.0x). Required when bidStrategy is LOWEST_COST_WITH_MIN_ROAS. | [optional] |
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ require 'zernio-sdk'
15
+
16
+ instance = Zernio::MetaAdsPlatformData.new(
17
+ bid_strategy: null,
18
+ bid_amount: null,
19
+ roas_average_floor: null
20
+ )
21
+ ```
22
+
@@ -6,6 +6,9 @@
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **id** | **String** | Internal post ID (null for posts not published through Zernio) | |
8
8
  | **platform_post_id** | **String** | Platform&#39;s post ID | |
9
+ | **content** | **String** | Post text, from our synced copy — no platform call is made on the comment path, so null when the post was never synced. | |
10
+ | **image_url** | **String** | Post thumbnail or first media item URL. Platform CDN URLs expire, fetch promptly. | |
11
+ | **permalink** | **String** | Public URL of the post. Null for posts published through Zernio that were never re-synced. | |
9
12
 
10
13
  ## Example
11
14
 
@@ -14,7 +17,10 @@ require 'zernio-sdk'
14
17
 
15
18
  instance = Zernio::WebhookPayloadCommentPost.new(
16
19
  id: null,
17
- platform_post_id: null
20
+ platform_post_id: null,
21
+ content: null,
22
+ image_url: null,
23
+ permalink: null
18
24
  )
19
25
  ```
20
26
 
@@ -379,6 +379,88 @@ module Zernio
379
379
  return data, status_code, headers
380
380
  end
381
381
 
382
+ # Google Ads search terms report
383
+ # The actual search queries that triggered your ads, with matched-keyword status and spend metrics — the raw material for wasted-spend analysis and negative-keyword lists. Reads Google's `search_term_view` live; defaults to the last 30 days. Rows are ordered by cost, descending. Draws on the shared Google Ads operations budget.
384
+ # @param account_id [String] Google ads SocialAccount id.
385
+ # @param [Hash] opts the optional parameters
386
+ # @option opts [String] :customer_id Numeric Google Ads customer id (no dashes). Defaults to the account&#39;s connected customer.
387
+ # @option opts [Date] :from_date Defaults to 30 days ago.
388
+ # @option opts [Date] :to_date Defaults to today.
389
+ # @option opts [String] :campaign_id Numeric Google campaign id filter.
390
+ # @option opts [String] :ad_group_id Numeric Google ad group id filter.
391
+ # @option opts [String] :page_token Cursor from paging.nextPageToken of the previous page.
392
+ # @return [GetAdsSearchTerms200Response]
393
+ def get_ads_search_terms(account_id, opts = {})
394
+ data, _status_code, _headers = get_ads_search_terms_with_http_info(account_id, opts)
395
+ data
396
+ end
397
+
398
+ # Google Ads search terms report
399
+ # The actual search queries that triggered your ads, with matched-keyword status and spend metrics — the raw material for wasted-spend analysis and negative-keyword lists. Reads Google&#39;s &#x60;search_term_view&#x60; live; defaults to the last 30 days. Rows are ordered by cost, descending. Draws on the shared Google Ads operations budget.
400
+ # @param account_id [String] Google ads SocialAccount id.
401
+ # @param [Hash] opts the optional parameters
402
+ # @option opts [String] :customer_id Numeric Google Ads customer id (no dashes). Defaults to the account&#39;s connected customer.
403
+ # @option opts [Date] :from_date Defaults to 30 days ago.
404
+ # @option opts [Date] :to_date Defaults to today.
405
+ # @option opts [String] :campaign_id Numeric Google campaign id filter.
406
+ # @option opts [String] :ad_group_id Numeric Google ad group id filter.
407
+ # @option opts [String] :page_token Cursor from paging.nextPageToken of the previous page.
408
+ # @return [Array<(GetAdsSearchTerms200Response, Integer, Hash)>] GetAdsSearchTerms200Response data, response status code and response headers
409
+ def get_ads_search_terms_with_http_info(account_id, opts = {})
410
+ if @api_client.config.debugging
411
+ @api_client.config.logger.debug 'Calling API: AdInsightsApi.get_ads_search_terms ...'
412
+ end
413
+ # verify the required parameter 'account_id' is set
414
+ if @api_client.config.client_side_validation && account_id.nil?
415
+ fail ArgumentError, "Missing the required parameter 'account_id' when calling AdInsightsApi.get_ads_search_terms"
416
+ end
417
+ # resource path
418
+ local_var_path = '/v1/ads/search-terms'
419
+
420
+ # query parameters
421
+ query_params = opts[:query_params] || {}
422
+ query_params[:'accountId'] = account_id
423
+ query_params[:'customerId'] = opts[:'customer_id'] if !opts[:'customer_id'].nil?
424
+ query_params[:'fromDate'] = opts[:'from_date'] if !opts[:'from_date'].nil?
425
+ query_params[:'toDate'] = opts[:'to_date'] if !opts[:'to_date'].nil?
426
+ query_params[:'campaignId'] = opts[:'campaign_id'] if !opts[:'campaign_id'].nil?
427
+ query_params[:'adGroupId'] = opts[:'ad_group_id'] if !opts[:'ad_group_id'].nil?
428
+ query_params[:'pageToken'] = opts[:'page_token'] if !opts[:'page_token'].nil?
429
+
430
+ # header parameters
431
+ header_params = opts[:header_params] || {}
432
+ # HTTP header 'Accept' (if needed)
433
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
434
+
435
+ # form parameters
436
+ form_params = opts[:form_params] || {}
437
+
438
+ # http body (model)
439
+ post_body = opts[:debug_body]
440
+
441
+ # return_type
442
+ return_type = opts[:debug_return_type] || 'GetAdsSearchTerms200Response'
443
+
444
+ # auth_names
445
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
446
+
447
+ new_options = opts.merge(
448
+ :operation => :"AdInsightsApi.get_ads_search_terms",
449
+ :header_params => header_params,
450
+ :query_params => query_params,
451
+ :form_params => form_params,
452
+ :body => post_body,
453
+ :auth_names => auth_names,
454
+ :return_type => return_type
455
+ )
456
+
457
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
458
+ if @api_client.config.debugging
459
+ @api_client.config.logger.debug "API called: AdInsightsApi#get_ads_search_terms\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
460
+ end
461
+ return data, status_code, headers
462
+ end
463
+
382
464
  # Get campaign analytics
383
465
  # Returns performance analytics for a whole campaign in one call: summary metrics, a daily timeline over the requested date range (summed across the campaign's ads), and optional demographic breakdowns. Breakdowns are fetched live from Meta at the campaign level (one call per dimension, no per-ad fan-out), so an agency dashboard gets campaign-level age/gender/etc. without summing thousands of per-ad reads. `campaignId` is the platform campaign id; pass `platform` when a campaign id could be ambiguous across platforms. If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max.
384
466
  # @param campaign_id [String] Platform campaign id (platformCampaignId).
@@ -83,7 +83,7 @@ module Zernio
83
83
  end
84
84
 
85
85
  # Get Instagram story insights
86
- # Returns metrics for a single story. The `source` field discriminates between three states: - `live` — fetched from Meta in real time (story is still active) - `cached` — fetched from a persisted `story_insights` webhook payload (story has expired but we received its final-state metrics from Meta) - `unavailable` — story has expired and we never received its webhook payload (for example, the account connected after the story expired) Field semantics follow Meta's API. Counts below 5 may be returned as 0 due to Meta's privacy floor on small audiences. The `navigation` field is the sum of `tapsForward + tapsBack + exits + swipesForward`.
86
+ # Returns metrics for a single story. The `source` field discriminates between three states: - `live` — fetched from Meta in real time (story is still active) - `cached` — fetched from a persisted `story_insights` webhook payload (story has expired but we received its final-state metrics from Meta) - `unavailable` — story has expired and we never received its webhook payload (for example, the account connected after the story expired) Meta can report an expired story as an empty successful result rather than an error, so an expired story resolves to `cached` or `unavailable` even though the upstream request itself succeeded. Field semantics follow Meta's API. Counts below 5 may be returned as 0 due to Meta's privacy floor on small audiences. The `navigation` field is the sum of `tapsForward + tapsBack + exits + swipesForward`.
87
87
  # @param account_id [String] The Instagram account ID
88
88
  # @param story_id [String] The Instagram media ID of the story.
89
89
  # @param [Hash] opts the optional parameters
@@ -94,7 +94,7 @@ module Zernio
94
94
  end
95
95
 
96
96
  # Get Instagram story insights
97
- # Returns metrics for a single story. The &#x60;source&#x60; field discriminates between three states: - &#x60;live&#x60; — fetched from Meta in real time (story is still active) - &#x60;cached&#x60; — fetched from a persisted &#x60;story_insights&#x60; webhook payload (story has expired but we received its final-state metrics from Meta) - &#x60;unavailable&#x60; — story has expired and we never received its webhook payload (for example, the account connected after the story expired) Field semantics follow Meta&#39;s API. Counts below 5 may be returned as 0 due to Meta&#39;s privacy floor on small audiences. The &#x60;navigation&#x60; field is the sum of &#x60;tapsForward + tapsBack + exits + swipesForward&#x60;.
97
+ # Returns metrics for a single story. The &#x60;source&#x60; field discriminates between three states: - &#x60;live&#x60; — fetched from Meta in real time (story is still active) - &#x60;cached&#x60; — fetched from a persisted &#x60;story_insights&#x60; webhook payload (story has expired but we received its final-state metrics from Meta) - &#x60;unavailable&#x60; — story has expired and we never received its webhook payload (for example, the account connected after the story expired) Meta can report an expired story as an empty successful result rather than an error, so an expired story resolves to &#x60;cached&#x60; or &#x60;unavailable&#x60; even though the upstream request itself succeeded. Field semantics follow Meta&#39;s API. Counts below 5 may be returned as 0 due to Meta&#39;s privacy floor on small audiences. The &#x60;navigation&#x60; field is the sum of &#x60;tapsForward + tapsBack + exits + swipesForward&#x60;.
98
98
  # @param account_id [String] The Instagram account ID
99
99
  # @param story_id [String] The Instagram media ID of the story.
100
100
  # @param [Hash] opts the optional parameters
@@ -52,13 +52,13 @@ module Zernio
52
52
  # Meta only. A Meta-native targeting spec (e.g. `{ \"geo_locations\": { \"cities\": [{ \"key\": \"...\", \"radius\": 15, \"distance_unit\": \"kilometer\" }] } }`). Sent alone it is forwarded unchanged. Use for advanced fields the structured object does not expose (flexible_spec, excluded audiences, business places, user_os, wireless_carrier). Can be combined with `targeting`: rawTargeting is the BASE layer and the built camelCase spec is merged on top, key by key (camelCase wins on collision). The merge goes one level deep inside `geo_locations` and `excluded_geo_locations` (built sub-keys win; raw-only sub-keys such as `location_types` survive). Array values (`flexible_spec`, ...) are replaced as a whole key, never element-merged. When `rawTargeting` is present the `advantage_audience: 0` default that Zernio normally applies is no longer emitted, so it cannot clobber a `targeting_automation` sent in the raw spec. Meta requires `targeting_automation` on ad set creation, so include it in the raw spec, or send `targeting.advantage_audience` (0 or 1), which is merged over raw as `targeting_automation`.
53
53
  attr_accessor :raw_targeting
54
54
 
55
- # Meta bid strategy applied to the ad set. On TikTok, mapped to `bid_type` / `bid_price` / `deep_bid_type` automatically.
55
+ # Deprecated: send it inside `platformSpecificData` instead (Meta today; TikTok's nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Meta bid strategy applied to the ad set. On TikTok, mapped to `bid_type` / `bid_price` / `deep_bid_type` automatically.
56
56
  attr_accessor :bid_strategy
57
57
 
58
- # Bid cap in WHOLE currency units (USD: 5 = $5.00; JPY: 100 = ¥100). Required when `bidStrategy` is `LOWEST_COST_WITH_BID_CAP` or `COST_CAP`. Backward-compat: providing `bidAmount` without `bidStrategy` is treated as `LOWEST_COST_WITH_BID_CAP`.
58
+ # Deprecated: send it inside `platformSpecificData` instead (Meta today; TikTok's nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Bid cap in WHOLE currency units (USD: 5 = $5.00; JPY: 100 = ¥100). Required when `bidStrategy` is `LOWEST_COST_WITH_BID_CAP` or `COST_CAP`. Backward-compat: providing `bidAmount` without `bidStrategy` is treated as `LOWEST_COST_WITH_BID_CAP`.
59
59
  attr_accessor :bid_amount
60
60
 
61
- # Minimum ROAS as a decimal multiplier (e.g. 2.0 = 2.0x ROAS). Required when `bidStrategy` is `LOWEST_COST_WITH_MIN_ROAS`. Sent to Meta as `bid_constraints.roas_average_floor` × 10000 (Meta uses fixed-point integers).
61
+ # Deprecated: send it inside `platformSpecificData` instead (Meta today; TikTok's nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400. Minimum ROAS as a decimal multiplier (e.g. 2.0 = 2.0x ROAS). Required when `bidStrategy` is `LOWEST_COST_WITH_MIN_ROAS`. Sent to Meta as `bid_constraints.roas_average_floor` × 10000 (Meta uses fixed-point integers).
62
62
  attr_accessor :roas_average_floor
63
63
 
64
64
  attr_accessor :platform_specific_data
@@ -174,7 +174,7 @@ module Zernio
174
174
  :'bid_strategy' => :'BidStrategy',
175
175
  :'bid_amount' => :'Float',
176
176
  :'roas_average_floor' => :'Float',
177
- :'platform_specific_data' => :'LinkedInAdsPlatformData',
177
+ :'platform_specific_data' => :'BoostPostRequestPlatformSpecificData',
178
178
  :'tracking' => :'BoostPostRequestTracking',
179
179
  :'special_ad_categories' => :'Array<String>',
180
180
  :'special_ad_category_country' => :'Array<String>',
@@ -0,0 +1,105 @@
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
+ # Platform-specific options. The platform is derived from `accountId`; sending options for a different platform returns a 400. LinkedIn (campaign bidding and delivery controls) and Meta (the bid trio) have options today. **Meta**: `bidStrategy`, `bidAmount` and `roasAverageFloor` may be sent here instead of at the root — the preferred home going forward. Sending the bid fields in BOTH places returns a 400 (`mutually_exclusive_fields`).
18
+ module BoostPostRequestPlatformSpecificData
19
+ class << self
20
+ # List of class defined in oneOf (OpenAPI v3)
21
+ def openapi_one_of
22
+ [
23
+ :'LinkedInAdsPlatformData',
24
+ :'MetaAdsPlatformData'
25
+ ]
26
+ end
27
+
28
+ # Builds the object
29
+ # @param [Mixed] Data to be matched against the list of oneOf items
30
+ # @return [Object] Returns the model or the data itself
31
+ def build(data)
32
+ # Go through the list of oneOf items and attempt to identify the appropriate one.
33
+ # Note:
34
+ # - We do not attempt to check whether exactly one item matches.
35
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
36
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
37
+ # - TODO: scalar values are de facto behaving as if they were nullable.
38
+ # - TODO: logging when debugging is set.
39
+ openapi_one_of.each do |klass|
40
+ begin
41
+ next if klass == :AnyType # "nullable: true"
42
+ return find_and_cast_into_type(klass, data)
43
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
44
+ end
45
+ end
46
+
47
+ openapi_one_of.include?(:AnyType) ? data : nil
48
+ end
49
+
50
+ private
51
+
52
+ SchemaMismatchError = Class.new(StandardError)
53
+
54
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
55
+ def find_and_cast_into_type(klass, data)
56
+ return if data.nil?
57
+
58
+ case klass.to_s
59
+ when 'Boolean'
60
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
61
+ when 'Float'
62
+ return data if data.instance_of?(Float)
63
+ when 'Integer'
64
+ return data if data.instance_of?(Integer)
65
+ when 'Time'
66
+ return Time.parse(data)
67
+ when 'Date'
68
+ return Date.iso8601(data)
69
+ when 'String'
70
+ return data if data.instance_of?(String)
71
+ when 'Object' # "type: object"
72
+ return data if data.instance_of?(Hash)
73
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
74
+ if data.instance_of?(Array)
75
+ sub_type = Regexp.last_match[:sub_type]
76
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
77
+ end
78
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
79
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
80
+ sub_type = Regexp.last_match[:sub_type]
81
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
82
+ end
83
+ else # model
84
+ const = Zernio.const_get(klass)
85
+ if const
86
+ if const.respond_to?(:openapi_one_of) # nested oneOf model
87
+ model = const.build(data)
88
+ return model if model
89
+ else
90
+ # raise if data contains keys that are not known to the model
91
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
92
+ model = const.build_from_hash(data)
93
+ return model if model
94
+ end
95
+ end
96
+ end
97
+
98
+ raise # if no match by now, raise
99
+ rescue
100
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
101
+ end
102
+ end
103
+ end
104
+
105
+ end