late-sdk 0.0.690 → 0.0.692

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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/docs/AdCampaignsApi.md +2 -2
  4. data/docs/MoveWhatsAppNumberToProfile200Response.md +22 -0
  5. data/docs/MoveWhatsAppNumberToProfileRequest.md +18 -0
  6. data/docs/UpdateAdCampaign200Response.md +5 -1
  7. data/docs/UpdateAdCampaignRequest.md +10 -6
  8. data/docs/UpdateAdCampaignRequestPlatformSpecificData.md +1 -1
  9. data/docs/WhatsAppPhoneNumbersApi.md +72 -0
  10. data/lib/zernio-sdk/api/ad_campaigns_api.rb +4 -4
  11. data/lib/zernio-sdk/api/whats_app_phone_numbers_api.rb +74 -0
  12. data/lib/zernio-sdk/models/move_whats_app_number_to_profile200_response.rb +169 -0
  13. data/lib/zernio-sdk/models/move_whats_app_number_to_profile_request.rb +165 -0
  14. data/lib/zernio-sdk/models/update_ad_campaign200_response.rb +21 -1
  15. data/lib/zernio-sdk/models/update_ad_campaign_request.rb +42 -21
  16. data/lib/zernio-sdk/models/update_ad_campaign_request_budget.rb +1 -0
  17. data/lib/zernio-sdk/models/update_ad_campaign_request_platform_specific_data.rb +2 -2
  18. data/lib/zernio-sdk/version.rb +1 -1
  19. data/lib/zernio-sdk.rb +2 -0
  20. data/openapi.yaml +96 -33
  21. data/spec/api/ad_campaigns_api_spec.rb +2 -2
  22. data/spec/api/whats_app_phone_numbers_api_spec.rb +13 -0
  23. data/spec/models/move_whats_app_number_to_profile200_response_spec.rb +48 -0
  24. data/spec/models/move_whats_app_number_to_profile_request_spec.rb +36 -0
  25. data/spec/models/update_ad_campaign200_response_spec.rb +12 -0
  26. data/spec/models/update_ad_campaign_request_spec.rb +19 -7
  27. data/zernio-sdk-0.0.692.gem +0 -0
  28. metadata +10 -2
  29. data/zernio-sdk-0.0.690.gem +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4489d0c507f3d38fec9b2a37431974b9f46cdd3d4b1bf90515a70a36cbba8871
4
- data.tar.gz: 2d992d7b5b7c13a1756281fd353a065c90a027ac7085830035e8afd7f9ebdb58
3
+ metadata.gz: c1cad9d861cb0ac0fc5c0af16cfa251ea0a7595ce69406b3cce31013fa5bff78
4
+ data.tar.gz: a7f1f3ce3eb84b7fb9cacfd6f13fc37d8970fb8e6cc15e2266cabf6fab182682
5
5
  SHA512:
6
- metadata.gz: a6615a350d3c26e4ce22ec63eb6d98d2e18b4aaefcde031cb0acc543aed830fcf2e109080cc33bfd1d84a9fd231724d2cb88d731846f4b9c10584fffc76b547f
7
- data.tar.gz: a884e66a2bf5f944cecf3f6476f26d8fcfb65f44736b380cb3845c0ad85b25ab42b3a7a298c8a66f5905817ed3b02c71643a1b335f916c531d657079dde137c5
6
+ metadata.gz: 412a9f4221a6051ddbf32962d32eb35fbe8f86bf34ba08c809934b12dfe272b6c0d3353fa0f67b1911e3561dbbe7c3d5f5d6538631e00e9196b7a9d05e431956
7
+ data.tar.gz: b18b82d898eeba1ff42e571eb783038e7682592ae2e0cfd256e50d1825528cb5db400b13dec41fee9663ada7380ca26799f659d60281b9899ac32bef8e0d9c31
data/README.md CHANGED
@@ -583,6 +583,7 @@ Class | Method | HTTP request | Description
583
583
  *Zernio::WhatsAppPhoneNumbersApi* | [**get_whats_app_phone_number**](docs/WhatsAppPhoneNumbersApi.md#get_whats_app_phone_number) | **GET** /v1/whatsapp/phone-numbers/{phoneNumberId} | Get phone number
584
584
  *Zernio::WhatsAppPhoneNumbersApi* | [**get_whats_app_phone_numbers**](docs/WhatsAppPhoneNumbersApi.md#get_whats_app_phone_numbers) | **GET** /v1/whatsapp/phone-numbers | List phone numbers
585
585
  *Zernio::WhatsAppPhoneNumbersApi* | [**list_whats_app_number_countries**](docs/WhatsAppPhoneNumbersApi.md#list_whats_app_number_countries) | **GET** /v1/whatsapp/phone-numbers/countries | List offerable number countries
586
+ *Zernio::WhatsAppPhoneNumbersApi* | [**move_whats_app_number_to_profile**](docs/WhatsAppPhoneNumbersApi.md#move_whats_app_number_to_profile) | **PATCH** /v1/whatsapp/phone-numbers/{id}/profile | Move a number to another profile
586
587
  *Zernio::WhatsAppPhoneNumbersApi* | [**purchase_whats_app_phone_number**](docs/WhatsAppPhoneNumbersApi.md#purchase_whats_app_phone_number) | **POST** /v1/whatsapp/phone-numbers/purchase | Purchase phone number
587
588
  *Zernio::WhatsAppPhoneNumbersApi* | [**release_whats_app_phone_number**](docs/WhatsAppPhoneNumbersApi.md#release_whats_app_phone_number) | **DELETE** /v1/whatsapp/phone-numbers/{phoneNumberId} | Release phone number
588
589
  *Zernio::WhatsAppPhoneNumbersApi* | [**remediate_whats_app_number**](docs/WhatsAppPhoneNumbersApi.md#remediate_whats_app_number) | **POST** /v1/whatsapp/phone-numbers/{id}/remediate | Resubmit a declined number
@@ -1587,6 +1588,8 @@ Class | Method | HTTP request | Description
1587
1588
  - [Zernio::MoneyAmount](docs/MoneyAmount.md)
1588
1589
  - [Zernio::MoveAccountToProfile200Response](docs/MoveAccountToProfile200Response.md)
1589
1590
  - [Zernio::MoveAccountToProfileRequest](docs/MoveAccountToProfileRequest.md)
1591
+ - [Zernio::MoveWhatsAppNumberToProfile200Response](docs/MoveWhatsAppNumberToProfile200Response.md)
1592
+ - [Zernio::MoveWhatsAppNumberToProfileRequest](docs/MoveWhatsAppNumberToProfileRequest.md)
1590
1593
  - [Zernio::OnVerificationApprovedRequest](docs/OnVerificationApprovedRequest.md)
1591
1594
  - [Zernio::OnVerificationApprovedRequestVerification](docs/OnVerificationApprovedRequestVerification.md)
1592
1595
  - [Zernio::OnVerificationFailedRequest](docs/OnVerificationFailedRequest.md)
@@ -387,7 +387,7 @@ end
387
387
 
388
388
  Delete a campaign
389
389
 
390
- Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked `status: cancelled`. Meta-only for now. Other platforms return 501 Not Implemented — fall back to DELETE /v1/ads/{adId} per ad in the meantime. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so it is invisible to `/v1/ads/tree` and this endpoint would 404. That state is produced by the two-step create flow (campaign, then ads via `existingCampaignId`) whenever Meta rejects the ad step. To delete such a shell, send `accountId` in the body: we skip the local lookup entirely and forward the delete to Meta. `accountId` is ignored when the campaign does have ads.
390
+ Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked `status: cancelled`. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so it is invisible to `/v1/ads/tree` and this endpoint would 404. That state is produced by the two-step create flow (campaign, then ads via `existingCampaignId`) whenever Meta rejects the ad step. To delete such a shell, send `accountId` in the body: we skip the local lookup entirely and forward the delete to Meta. `accountId` is ignored when the campaign does have ads.
391
391
 
392
392
  ### Examples
393
393
 
@@ -1359,7 +1359,7 @@ end
1359
1359
 
1360
1360
  Update a campaign
1361
1361
 
1362
- Campaign-level edits. At least one of `budget`, `bidStrategy`, `name` or `platformSpecificData` is required. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so this would 404 even though it exists on Meta. Send `accountId` in the body to skip the local lookup and forward the update to Meta. The response then carries `updated: 0`, since there are no local rows to mirror onto. `accountId` is ignored when the campaign does have ads. - `budget` updates the CBO (Campaign Budget Optimization) budget. For ABO campaigns (where the budget lives on the ad set), use PUT /v1/ads/ad-sets/{adSetId} instead this endpoint will return 409 with code BUDGET_LEVEL_MISMATCH. - `bidStrategy` sets the campaign-level default bid strategy. Per Meta's spec, `bid_amount` and `bid_constraints` do NOT exist at the campaign level pass them via PUT /v1/ads/ad-sets/{adSetId}. - `platformSpecificData.spendCap` (Meta only) sets the campaign's lifetime spend cap, in the ad account's currency. Meta-only for now. Other platforms return 501 Not Implemented.
1362
+ Campaign-level edits. Send at least one of `budget`, `bidStrategy`, `name` or `platformSpecificData`. An unsupported field is always an error, never a silent drop. | Body field | Meta | Google | Others | |---|---|---|---| | `bidStrategy` | Yes | Yes | 501 | | `bidAmount`, `roasAverageFloor` | 400 ad-set level | Yes | 400 | | `budget` (CBO; ABO returns 409) | Yes | 501 | 501 | | `name` | Yes | 501 | 501 | | `platformSpecificData.spendCap` | Yes | 400 | 400 | | `accountId` (empty campaigns) | Yes | - | - | Google maps the shared enum onto its own strategies: `LOWEST_COST_WITHOUT_CAP` to Maximize Clicks, `LOWEST_COST_WITH_BID_CAP` to Maximize Clicks with a max CPC (`bidAmount`), `COST_CAP` to Target CPA (`bidAmount`), `LOWEST_COST_WITH_MIN_ROAS` to Target ROAS (`roasAverageFloor`). A campaign on a PORTFOLIO bidding strategy is rejected: detach it in Google Ads first, since it is shared across campaigns. `accountId` forwards the update straight to Meta for a campaign with zero ads, which would otherwise 404; the response then carries `updated: 0`.
1363
1363
 
1364
1364
  ### Examples
1365
1365
 
@@ -0,0 +1,22 @@
1
+ # Zernio::MoveWhatsAppNumberToProfile200Response
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **message** | **String** | | [optional] |
8
+ | **profile_id** | **String** | The profile the number is now on. | [optional] |
9
+ | **moved_platforms** | **Array<String>** | Platforms whose accounts travelled with the number (phone, sms, whatsapp). Absent when the number was already on the destination profile. | [optional] |
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ require 'zernio-sdk'
15
+
16
+ instance = Zernio::MoveWhatsAppNumberToProfile200Response.new(
17
+ message: null,
18
+ profile_id: null,
19
+ moved_platforms: null
20
+ )
21
+ ```
22
+
@@ -0,0 +1,18 @@
1
+ # Zernio::MoveWhatsAppNumberToProfileRequest
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **profile_id** | **String** | Destination profile id. Must belong to the same team. | |
8
+
9
+ ## Example
10
+
11
+ ```ruby
12
+ require 'zernio-sdk'
13
+
14
+ instance = Zernio::MoveWhatsAppNumberToProfileRequest.new(
15
+ profile_id: null
16
+ )
17
+ ```
18
+
@@ -4,10 +4,12 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **updated** | **Integer** | | [optional] |
7
+ | **updated** | **Integer** | Local Ad documents mirrored. 0 on the empty-campaign path. | [optional] |
8
8
  | **budget** | [**AdBudget**](AdBudget.md) | | [optional] |
9
9
  | **budget_level** | **String** | | [optional] |
10
10
  | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | | [optional] |
11
+ | **bid_amount** | **Float** | | [optional] |
12
+ | **roas_average_floor** | **Float** | | [optional] |
11
13
  | **platform_specific_data** | **Object** | | [optional] |
12
14
 
13
15
  ## Example
@@ -20,6 +22,8 @@ instance = Zernio::UpdateAdCampaign200Response.new(
20
22
  budget: null,
21
23
  budget_level: null,
22
24
  bid_strategy: null,
25
+ bid_amount: null,
26
+ roas_average_floor: null,
23
27
  platform_specific_data: null
24
28
  )
25
29
  ```
@@ -4,11 +4,13 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **account_id** | **String** | Zernio SocialAccount id owning the ad account. Required only to update an EMPTY campaign (zero ads), which has no local Ad documents to resolve a token from. | [optional] |
8
- | **platform** | **String** | | |
7
+ | **platform** | **String** | Required: platform campaign IDs are not globally unique. | |
8
+ | **account_id** | **String** | **Meta only.** Zernio SocialAccount id owning the ad account. Needed only for an EMPTY campaign (zero ads); ignored otherwise. | [optional] |
9
+ | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | **Meta + Google.** On Meta, the campaign default that ad sets inherit unless they override it. On Google, the campaign's own bidding strategy. | [optional] |
10
+ | **bid_amount** | **Float** | **Google only.** Whole currency units (USD: 12 = $12.00). Max CPC for LOWEST_COST_WITH_BID_CAP, CPA target for COST_CAP; required for both. | [optional] |
11
+ | **roas_average_floor** | **Float** | **Google only.** Decimal ROAS multiplier (2.0 = 2.0x), required for LOWEST_COST_WITH_MIN_ROAS. | [optional] |
9
12
  | **budget** | [**UpdateAdCampaignRequestBudget**](UpdateAdCampaignRequestBudget.md) | | [optional] |
10
- | **bid_strategy** | [**BidStrategy**](BidStrategy.md) | Campaign-level default. Ad sets inherit this unless they override. | [optional] |
11
- | **name** | **String** | Rename the campaign (Meta only; other platforms return 501). At least one of budget/bidStrategy/name/platformSpecificData is required. | [optional] |
13
+ | **name** | **String** | **Meta only.** Rename the campaign. | [optional] |
12
14
  | **platform_specific_data** | [**UpdateAdCampaignRequestPlatformSpecificData**](UpdateAdCampaignRequestPlatformSpecificData.md) | | [optional] |
13
15
 
14
16
  ## Example
@@ -17,10 +19,12 @@
17
19
  require 'zernio-sdk'
18
20
 
19
21
  instance = Zernio::UpdateAdCampaignRequest.new(
20
- account_id: null,
21
22
  platform: null,
22
- budget: null,
23
+ account_id: null,
23
24
  bid_strategy: null,
25
+ bid_amount: null,
26
+ roas_average_floor: null,
27
+ budget: null,
24
28
  name: null,
25
29
  platform_specific_data: null
26
30
  )
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **spend_cap** | **Float** | Campaign lifetime spend cap, in the ad account's currency (Meta `spend_cap`). Pass null to remove the cap (0 is rejected by Meta). | [optional] |
7
+ | **spend_cap** | **Float** | Campaign lifetime spend cap, in the ad account's currency (Meta `spend_cap`). Pass null to remove the cap; 0 is rejected by Meta. | [optional] |
8
8
 
9
9
  ## Example
10
10
 
@@ -12,6 +12,7 @@ All URIs are relative to *https://zernio.com/api*
12
12
  | [**get_whats_app_phone_number**](WhatsAppPhoneNumbersApi.md#get_whats_app_phone_number) | **GET** /v1/whatsapp/phone-numbers/{phoneNumberId} | Get phone number |
13
13
  | [**get_whats_app_phone_numbers**](WhatsAppPhoneNumbersApi.md#get_whats_app_phone_numbers) | **GET** /v1/whatsapp/phone-numbers | List phone numbers |
14
14
  | [**list_whats_app_number_countries**](WhatsAppPhoneNumbersApi.md#list_whats_app_number_countries) | **GET** /v1/whatsapp/phone-numbers/countries | List offerable number countries |
15
+ | [**move_whats_app_number_to_profile**](WhatsAppPhoneNumbersApi.md#move_whats_app_number_to_profile) | **PATCH** /v1/whatsapp/phone-numbers/{id}/profile | Move a number to another profile |
15
16
  | [**purchase_whats_app_phone_number**](WhatsAppPhoneNumbersApi.md#purchase_whats_app_phone_number) | **POST** /v1/whatsapp/phone-numbers/purchase | Purchase phone number |
16
17
  | [**release_whats_app_phone_number**](WhatsAppPhoneNumbersApi.md#release_whats_app_phone_number) | **DELETE** /v1/whatsapp/phone-numbers/{phoneNumberId} | Release phone number |
17
18
  | [**remediate_whats_app_number**](WhatsAppPhoneNumbersApi.md#remediate_whats_app_number) | **POST** /v1/whatsapp/phone-numbers/{id}/remediate | Resubmit a declined number |
@@ -582,6 +583,77 @@ This endpoint does not need any parameter.
582
583
  - **Accept**: application/json
583
584
 
584
585
 
586
+ ## move_whats_app_number_to_profile
587
+
588
+ > <MoveWhatsAppNumberToProfile200Response> move_whats_app_number_to_profile(id, move_whats_app_number_to_profile_request)
589
+
590
+ Move a number to another profile
591
+
592
+ Move a provisioned number to a different profile. A number is not a single record. Alongside the number itself there are hidden telephony owner accounts (platform `phone`, plus `sms` when SMS is enabled) and, once WhatsApp is connected, the `whatsapp` account. They all carry a profileId and this endpoint moves them together. Use this instead of `PATCH /v1/accounts/{accountId}`: that one moves the social account only and leaves the number itself pinned to its original profile, which splits the number across two profiles. Connecting a provisioned number always places it on the profile the NUMBER is on, so a `profileId` passed to `GET /v1/connect/whatsapp` cannot re-home it and a later reconnect pulls the account back. This endpoint is how you re-home it. `id` is the number record id from `GET /v1/phone-numbers`, not an account id. A profile holds at most one account per platform, so the destination must be free of every platform this number occupies.
593
+
594
+ ### Examples
595
+
596
+ ```ruby
597
+ require 'time'
598
+ require 'zernio-sdk'
599
+ # setup authorization
600
+ Zernio.configure do |config|
601
+ # Configure Bearer authorization (JWT): bearerAuth
602
+ config.access_token = 'YOUR_BEARER_TOKEN'
603
+ end
604
+
605
+ api_instance = Zernio::WhatsAppPhoneNumbersApi.new
606
+ id = 'id_example' # String | WhatsAppPhoneNumber id.
607
+ move_whats_app_number_to_profile_request = Zernio::MoveWhatsAppNumberToProfileRequest.new({profile_id: 'profile_id_example'}) # MoveWhatsAppNumberToProfileRequest |
608
+
609
+ begin
610
+ # Move a number to another profile
611
+ result = api_instance.move_whats_app_number_to_profile(id, move_whats_app_number_to_profile_request)
612
+ p result
613
+ rescue Zernio::ApiError => e
614
+ puts "Error when calling WhatsAppPhoneNumbersApi->move_whats_app_number_to_profile: #{e}"
615
+ end
616
+ ```
617
+
618
+ #### Using the move_whats_app_number_to_profile_with_http_info variant
619
+
620
+ This returns an Array which contains the response data, status code and headers.
621
+
622
+ > <Array(<MoveWhatsAppNumberToProfile200Response>, Integer, Hash)> move_whats_app_number_to_profile_with_http_info(id, move_whats_app_number_to_profile_request)
623
+
624
+ ```ruby
625
+ begin
626
+ # Move a number to another profile
627
+ data, status_code, headers = api_instance.move_whats_app_number_to_profile_with_http_info(id, move_whats_app_number_to_profile_request)
628
+ p status_code # => 2xx
629
+ p headers # => { ... }
630
+ p data # => <MoveWhatsAppNumberToProfile200Response>
631
+ rescue Zernio::ApiError => e
632
+ puts "Error when calling WhatsAppPhoneNumbersApi->move_whats_app_number_to_profile_with_http_info: #{e}"
633
+ end
634
+ ```
635
+
636
+ ### Parameters
637
+
638
+ | Name | Type | Description | Notes |
639
+ | ---- | ---- | ----------- | ----- |
640
+ | **id** | **String** | WhatsAppPhoneNumber id. | |
641
+ | **move_whats_app_number_to_profile_request** | [**MoveWhatsAppNumberToProfileRequest**](MoveWhatsAppNumberToProfileRequest.md) | | |
642
+
643
+ ### Return type
644
+
645
+ [**MoveWhatsAppNumberToProfile200Response**](MoveWhatsAppNumberToProfile200Response.md)
646
+
647
+ ### Authorization
648
+
649
+ [bearerAuth](../README.md#bearerAuth)
650
+
651
+ ### HTTP request headers
652
+
653
+ - **Content-Type**: application/json
654
+ - **Accept**: application/json
655
+
656
+
585
657
  ## purchase_whats_app_phone_number
586
658
 
587
659
  > <PurchaseWhatsAppPhoneNumber200Response> purchase_whats_app_phone_number(purchase_whats_app_phone_number_request)
@@ -369,7 +369,7 @@ module Zernio
369
369
  end
370
370
 
371
371
  # Delete a campaign
372
- # Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked `status: cancelled`. Meta-only for now. Other platforms return 501 Not Implemented — fall back to DELETE /v1/ads/{adId} per ad in the meantime. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so it is invisible to `/v1/ads/tree` and this endpoint would 404. That state is produced by the two-step create flow (campaign, then ads via `existingCampaignId`) whenever Meta rejects the ad step. To delete such a shell, send `accountId` in the body: we skip the local lookup entirely and forward the delete to Meta. `accountId` is ignored when the campaign does have ads.
372
+ # Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked `status: cancelled`. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so it is invisible to `/v1/ads/tree` and this endpoint would 404. That state is produced by the two-step create flow (campaign, then ads via `existingCampaignId`) whenever Meta rejects the ad step. To delete such a shell, send `accountId` in the body: we skip the local lookup entirely and forward the delete to Meta. `accountId` is ignored when the campaign does have ads.
373
373
  # @param campaign_id [String] Platform campaign ID
374
374
  # @param delete_ad_campaign_request [DeleteAdCampaignRequest]
375
375
  # @param [Hash] opts the optional parameters
@@ -380,7 +380,7 @@ module Zernio
380
380
  end
381
381
 
382
382
  # Delete a campaign
383
- # Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked &#x60;status: cancelled&#x60;. Meta-only for now. Other platforms return 501 Not Implemented — fall back to DELETE /v1/ads/{adId} per ad in the meantime. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so it is invisible to &#x60;/v1/ads/tree&#x60; and this endpoint would 404. That state is produced by the two-step create flow (campaign, then ads via &#x60;existingCampaignId&#x60;) whenever Meta rejects the ad step. To delete such a shell, send &#x60;accountId&#x60; in the body: we skip the local lookup entirely and forward the delete to Meta. &#x60;accountId&#x60; is ignored when the campaign does have ads.
383
+ # Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked &#x60;status: cancelled&#x60;. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so it is invisible to &#x60;/v1/ads/tree&#x60; and this endpoint would 404. That state is produced by the two-step create flow (campaign, then ads via &#x60;existingCampaignId&#x60;) whenever Meta rejects the ad step. To delete such a shell, send &#x60;accountId&#x60; in the body: we skip the local lookup entirely and forward the delete to Meta. &#x60;accountId&#x60; is ignored when the campaign does have ads.
384
384
  # @param campaign_id [String] Platform campaign ID
385
385
  # @param delete_ad_campaign_request [DeleteAdCampaignRequest]
386
386
  # @param [Hash] opts the optional parameters
@@ -1455,7 +1455,7 @@ module Zernio
1455
1455
  end
1456
1456
 
1457
1457
  # Update a campaign
1458
- # Campaign-level edits. At least one of `budget`, `bidStrategy`, `name` or `platformSpecificData` is required. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so this would 404 even though it exists on Meta. Send `accountId` in the body to skip the local lookup and forward the update to Meta. The response then carries `updated: 0`, since there are no local rows to mirror onto. `accountId` is ignored when the campaign does have ads. - `budget` updates the CBO (Campaign Budget Optimization) budget. For ABO campaigns (where the budget lives on the ad set), use PUT /v1/ads/ad-sets/{adSetId} instead this endpoint will return 409 with code BUDGET_LEVEL_MISMATCH. - `bidStrategy` sets the campaign-level default bid strategy. Per Meta's spec, `bid_amount` and `bid_constraints` do NOT exist at the campaign level pass them via PUT /v1/ads/ad-sets/{adSetId}. - `platformSpecificData.spendCap` (Meta only) sets the campaign's lifetime spend cap, in the ad account's currency. Meta-only for now. Other platforms return 501 Not Implemented.
1458
+ # Campaign-level edits. Send at least one of `budget`, `bidStrategy`, `name` or `platformSpecificData`. An unsupported field is always an error, never a silent drop. | Body field | Meta | Google | Others | |---|---|---|---| | `bidStrategy` | Yes | Yes | 501 | | `bidAmount`, `roasAverageFloor` | 400 ad-set level | Yes | 400 | | `budget` (CBO; ABO returns 409) | Yes | 501 | 501 | | `name` | Yes | 501 | 501 | | `platformSpecificData.spendCap` | Yes | 400 | 400 | | `accountId` (empty campaigns) | Yes | - | - | Google maps the shared enum onto its own strategies: `LOWEST_COST_WITHOUT_CAP` to Maximize Clicks, `LOWEST_COST_WITH_BID_CAP` to Maximize Clicks with a max CPC (`bidAmount`), `COST_CAP` to Target CPA (`bidAmount`), `LOWEST_COST_WITH_MIN_ROAS` to Target ROAS (`roasAverageFloor`). A campaign on a PORTFOLIO bidding strategy is rejected: detach it in Google Ads first, since it is shared across campaigns. `accountId` forwards the update straight to Meta for a campaign with zero ads, which would otherwise 404; the response then carries `updated: 0`.
1459
1459
  # @param campaign_id [String] Platform campaign ID
1460
1460
  # @param update_ad_campaign_request [UpdateAdCampaignRequest]
1461
1461
  # @param [Hash] opts the optional parameters
@@ -1466,7 +1466,7 @@ module Zernio
1466
1466
  end
1467
1467
 
1468
1468
  # Update a campaign
1469
- # Campaign-level edits. At least one of &#x60;budget&#x60;, &#x60;bidStrategy&#x60;, &#x60;name&#x60; or &#x60;platformSpecificData&#x60; is required. **Empty campaigns.** A campaign with zero ads has no local Ad documents to resolve, so this would 404 even though it exists on Meta. Send &#x60;accountId&#x60; in the body to skip the local lookup and forward the update to Meta. The response then carries &#x60;updated: 0&#x60;, since there are no local rows to mirror onto. &#x60;accountId&#x60; is ignored when the campaign does have ads. - &#x60;budget&#x60; updates the CBO (Campaign Budget Optimization) budget. For ABO campaigns (where the budget lives on the ad set), use PUT /v1/ads/ad-sets/{adSetId} instead this endpoint will return 409 with code BUDGET_LEVEL_MISMATCH. - &#x60;bidStrategy&#x60; sets the campaign-level default bid strategy. Per Meta&#39;s spec, &#x60;bid_amount&#x60; and &#x60;bid_constraints&#x60; do NOT exist at the campaign level pass them via PUT /v1/ads/ad-sets/{adSetId}. - &#x60;platformSpecificData.spendCap&#x60; (Meta only) sets the campaign&#39;s lifetime spend cap, in the ad account&#39;s currency. Meta-only for now. Other platforms return 501 Not Implemented.
1469
+ # Campaign-level edits. Send at least one of &#x60;budget&#x60;, &#x60;bidStrategy&#x60;, &#x60;name&#x60; or &#x60;platformSpecificData&#x60;. An unsupported field is always an error, never a silent drop. | Body field | Meta | Google | Others | |---|---|---|---| | &#x60;bidStrategy&#x60; | Yes | Yes | 501 | | &#x60;bidAmount&#x60;, &#x60;roasAverageFloor&#x60; | 400 ad-set level | Yes | 400 | | &#x60;budget&#x60; (CBO; ABO returns 409) | Yes | 501 | 501 | | &#x60;name&#x60; | Yes | 501 | 501 | | &#x60;platformSpecificData.spendCap&#x60; | Yes | 400 | 400 | | &#x60;accountId&#x60; (empty campaigns) | Yes | - | - | Google maps the shared enum onto its own strategies: &#x60;LOWEST_COST_WITHOUT_CAP&#x60; to Maximize Clicks, &#x60;LOWEST_COST_WITH_BID_CAP&#x60; to Maximize Clicks with a max CPC (&#x60;bidAmount&#x60;), &#x60;COST_CAP&#x60; to Target CPA (&#x60;bidAmount&#x60;), &#x60;LOWEST_COST_WITH_MIN_ROAS&#x60; to Target ROAS (&#x60;roasAverageFloor&#x60;). A campaign on a PORTFOLIO bidding strategy is rejected: detach it in Google Ads first, since it is shared across campaigns. &#x60;accountId&#x60; forwards the update straight to Meta for a campaign with zero ads, which would otherwise 404; the response then carries &#x60;updated: 0&#x60;.
1470
1470
  # @param campaign_id [String] Platform campaign ID
1471
1471
  # @param update_ad_campaign_request [UpdateAdCampaignRequest]
1472
1472
  # @param [Hash] opts the optional parameters
@@ -546,6 +546,80 @@ module Zernio
546
546
  return data, status_code, headers
547
547
  end
548
548
 
549
+ # Move a number to another profile
550
+ # Move a provisioned number to a different profile. A number is not a single record. Alongside the number itself there are hidden telephony owner accounts (platform `phone`, plus `sms` when SMS is enabled) and, once WhatsApp is connected, the `whatsapp` account. They all carry a profileId and this endpoint moves them together. Use this instead of `PATCH /v1/accounts/{accountId}`: that one moves the social account only and leaves the number itself pinned to its original profile, which splits the number across two profiles. Connecting a provisioned number always places it on the profile the NUMBER is on, so a `profileId` passed to `GET /v1/connect/whatsapp` cannot re-home it and a later reconnect pulls the account back. This endpoint is how you re-home it. `id` is the number record id from `GET /v1/phone-numbers`, not an account id. A profile holds at most one account per platform, so the destination must be free of every platform this number occupies.
551
+ # @param id [String] WhatsAppPhoneNumber id.
552
+ # @param move_whats_app_number_to_profile_request [MoveWhatsAppNumberToProfileRequest]
553
+ # @param [Hash] opts the optional parameters
554
+ # @return [MoveWhatsAppNumberToProfile200Response]
555
+ def move_whats_app_number_to_profile(id, move_whats_app_number_to_profile_request, opts = {})
556
+ data, _status_code, _headers = move_whats_app_number_to_profile_with_http_info(id, move_whats_app_number_to_profile_request, opts)
557
+ data
558
+ end
559
+
560
+ # Move a number to another profile
561
+ # Move a provisioned number to a different profile. A number is not a single record. Alongside the number itself there are hidden telephony owner accounts (platform &#x60;phone&#x60;, plus &#x60;sms&#x60; when SMS is enabled) and, once WhatsApp is connected, the &#x60;whatsapp&#x60; account. They all carry a profileId and this endpoint moves them together. Use this instead of &#x60;PATCH /v1/accounts/{accountId}&#x60;: that one moves the social account only and leaves the number itself pinned to its original profile, which splits the number across two profiles. Connecting a provisioned number always places it on the profile the NUMBER is on, so a &#x60;profileId&#x60; passed to &#x60;GET /v1/connect/whatsapp&#x60; cannot re-home it and a later reconnect pulls the account back. This endpoint is how you re-home it. &#x60;id&#x60; is the number record id from &#x60;GET /v1/phone-numbers&#x60;, not an account id. A profile holds at most one account per platform, so the destination must be free of every platform this number occupies.
562
+ # @param id [String] WhatsAppPhoneNumber id.
563
+ # @param move_whats_app_number_to_profile_request [MoveWhatsAppNumberToProfileRequest]
564
+ # @param [Hash] opts the optional parameters
565
+ # @return [Array<(MoveWhatsAppNumberToProfile200Response, Integer, Hash)>] MoveWhatsAppNumberToProfile200Response data, response status code and response headers
566
+ def move_whats_app_number_to_profile_with_http_info(id, move_whats_app_number_to_profile_request, opts = {})
567
+ if @api_client.config.debugging
568
+ @api_client.config.logger.debug 'Calling API: WhatsAppPhoneNumbersApi.move_whats_app_number_to_profile ...'
569
+ end
570
+ # verify the required parameter 'id' is set
571
+ if @api_client.config.client_side_validation && id.nil?
572
+ fail ArgumentError, "Missing the required parameter 'id' when calling WhatsAppPhoneNumbersApi.move_whats_app_number_to_profile"
573
+ end
574
+ # verify the required parameter 'move_whats_app_number_to_profile_request' is set
575
+ if @api_client.config.client_side_validation && move_whats_app_number_to_profile_request.nil?
576
+ fail ArgumentError, "Missing the required parameter 'move_whats_app_number_to_profile_request' when calling WhatsAppPhoneNumbersApi.move_whats_app_number_to_profile"
577
+ end
578
+ # resource path
579
+ local_var_path = '/v1/whatsapp/phone-numbers/{id}/profile'.sub('{' + 'id' + '}', CGI.escape(id.to_s))
580
+
581
+ # query parameters
582
+ query_params = opts[:query_params] || {}
583
+
584
+ # header parameters
585
+ header_params = opts[:header_params] || {}
586
+ # HTTP header 'Accept' (if needed)
587
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
588
+ # HTTP header 'Content-Type'
589
+ content_type = @api_client.select_header_content_type(['application/json'])
590
+ if !content_type.nil?
591
+ header_params['Content-Type'] = content_type
592
+ end
593
+
594
+ # form parameters
595
+ form_params = opts[:form_params] || {}
596
+
597
+ # http body (model)
598
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(move_whats_app_number_to_profile_request)
599
+
600
+ # return_type
601
+ return_type = opts[:debug_return_type] || 'MoveWhatsAppNumberToProfile200Response'
602
+
603
+ # auth_names
604
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
605
+
606
+ new_options = opts.merge(
607
+ :operation => :"WhatsAppPhoneNumbersApi.move_whats_app_number_to_profile",
608
+ :header_params => header_params,
609
+ :query_params => query_params,
610
+ :form_params => form_params,
611
+ :body => post_body,
612
+ :auth_names => auth_names,
613
+ :return_type => return_type
614
+ )
615
+
616
+ data, status_code, headers = @api_client.call_api(:PATCH, local_var_path, new_options)
617
+ if @api_client.config.debugging
618
+ @api_client.config.logger.debug "API called: WhatsAppPhoneNumbersApi#move_whats_app_number_to_profile\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
619
+ end
620
+ return data, status_code, headers
621
+ end
622
+
549
623
  # Purchase phone number
550
624
  # Deprecated alias of `/v1/phone-numbers/purchase`; same contract. New integrations should use that path. Payment-first: you do not pick a specific number, the system provisions one and auto-assigns it. With usage-based billing active and a payment method on file, the number provisions inline and bills per month on your usage-based invoice (there is no checkout redirect). No payment method on file returns `402 PAYMENT_REQUIRED`; a regulated country returns `202` with `status: \"kyc_required\"` and a `kycUrl`. Requires usage-based billing (the Usage plan). The maximum number of phone numbers is determined by the user's plan.
551
625
  # @param purchase_whats_app_phone_number_request [PurchaseWhatsAppPhoneNumberRequest]
@@ -0,0 +1,169 @@
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 MoveWhatsAppNumberToProfile200Response < ApiModelBase
18
+ attr_accessor :message
19
+
20
+ # The profile the number is now on.
21
+ attr_accessor :profile_id
22
+
23
+ # Platforms whose accounts travelled with the number (phone, sms, whatsapp). Absent when the number was already on the destination profile.
24
+ attr_accessor :moved_platforms
25
+
26
+ # Attribute mapping from ruby-style variable name to JSON key.
27
+ def self.attribute_map
28
+ {
29
+ :'message' => :'message',
30
+ :'profile_id' => :'profileId',
31
+ :'moved_platforms' => :'movedPlatforms'
32
+ }
33
+ end
34
+
35
+ # Returns attribute mapping this model knows about
36
+ def self.acceptable_attribute_map
37
+ attribute_map
38
+ end
39
+
40
+ # Returns all the JSON keys this model knows about
41
+ def self.acceptable_attributes
42
+ acceptable_attribute_map.values
43
+ end
44
+
45
+ # Attribute type mapping.
46
+ def self.openapi_types
47
+ {
48
+ :'message' => :'String',
49
+ :'profile_id' => :'String',
50
+ :'moved_platforms' => :'Array<String>'
51
+ }
52
+ end
53
+
54
+ # List of attributes with nullable: true
55
+ def self.openapi_nullable
56
+ Set.new([
57
+ ])
58
+ end
59
+
60
+ # Initializes the object
61
+ # @param [Hash] attributes Model attributes in the form of hash
62
+ def initialize(attributes = {})
63
+ if (!attributes.is_a?(Hash))
64
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::MoveWhatsAppNumberToProfile200Response` initialize method"
65
+ end
66
+
67
+ # check to see if the attribute exists and convert string to symbol for hash key
68
+ acceptable_attribute_map = self.class.acceptable_attribute_map
69
+ attributes = attributes.each_with_object({}) { |(k, v), h|
70
+ if (!acceptable_attribute_map.key?(k.to_sym))
71
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::MoveWhatsAppNumberToProfile200Response`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
72
+ end
73
+ h[k.to_sym] = v
74
+ }
75
+
76
+ if attributes.key?(:'message')
77
+ self.message = attributes[:'message']
78
+ end
79
+
80
+ if attributes.key?(:'profile_id')
81
+ self.profile_id = attributes[:'profile_id']
82
+ end
83
+
84
+ if attributes.key?(:'moved_platforms')
85
+ if (value = attributes[:'moved_platforms']).is_a?(Array)
86
+ self.moved_platforms = value
87
+ end
88
+ end
89
+ end
90
+
91
+ # Show invalid properties with the reasons. Usually used together with valid?
92
+ # @return Array for valid properties with the reasons
93
+ def list_invalid_properties
94
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
95
+ invalid_properties = Array.new
96
+ invalid_properties
97
+ end
98
+
99
+ # Check to see if the all the properties in the model are valid
100
+ # @return true if the model is valid
101
+ def valid?
102
+ warn '[DEPRECATED] the `valid?` method is obsolete'
103
+ true
104
+ end
105
+
106
+ # Checks equality by comparing each attribute.
107
+ # @param [Object] Object to be compared
108
+ def ==(o)
109
+ return true if self.equal?(o)
110
+ self.class == o.class &&
111
+ message == o.message &&
112
+ profile_id == o.profile_id &&
113
+ moved_platforms == o.moved_platforms
114
+ end
115
+
116
+ # @see the `==` method
117
+ # @param [Object] Object to be compared
118
+ def eql?(o)
119
+ self == o
120
+ end
121
+
122
+ # Calculates hash code according to all attributes.
123
+ # @return [Integer] Hash code
124
+ def hash
125
+ [message, profile_id, moved_platforms].hash
126
+ end
127
+
128
+ # Builds the object from hash
129
+ # @param [Hash] attributes Model attributes in the form of hash
130
+ # @return [Object] Returns the model itself
131
+ def self.build_from_hash(attributes)
132
+ return nil unless attributes.is_a?(Hash)
133
+ attributes = attributes.transform_keys(&:to_sym)
134
+ transformed_hash = {}
135
+ openapi_types.each_pair do |key, type|
136
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
137
+ transformed_hash["#{key}"] = nil
138
+ elsif type =~ /\AArray<(.*)>/i
139
+ # check to ensure the input is an array given that the attribute
140
+ # is documented as an array but the input is not
141
+ if attributes[attribute_map[key]].is_a?(Array)
142
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
143
+ end
144
+ elsif !attributes[attribute_map[key]].nil?
145
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
146
+ end
147
+ end
148
+ new(transformed_hash)
149
+ end
150
+
151
+ # Returns the object in the form of hash
152
+ # @return [Hash] Returns the object in the form of hash
153
+ def to_hash
154
+ hash = {}
155
+ self.class.attribute_map.each_pair do |attr, param|
156
+ value = self.send(attr)
157
+ if value.nil?
158
+ is_nullable = self.class.openapi_nullable.include?(attr)
159
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
160
+ end
161
+
162
+ hash[param] = _to_hash(value)
163
+ end
164
+ hash
165
+ end
166
+
167
+ end
168
+
169
+ end