Skip to content

Commit c82ad24

Browse files
committed
fix: remove hardcoded destination_type validation that rejected WHATSAPP
The create_adset allowlist only had APP_STORE, DEEPLINK, APP_INSTALL, ON_AD — blocking valid values like WHATSAPP, MESSENGER, and INSTAGRAM_DIRECT. Meta's SDK defines 23+ destination types. Let Meta's API handle validation instead.
1 parent 3f05345 commit c82ad24

File tree

2 files changed

+22
-24
lines changed

2 files changed

+22
-24
lines changed

meta_ads_mcp/core/adsets.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ async def create_adset(
138138
end_time: End time in ISO 8601 format
139139
dsa_beneficiary: DSA beneficiary for European compliance
140140
promoted_object: App config for APP_INSTALLS. Required: application_id, object_store_url.
141-
destination_type: Where users go after click (e.g., 'APP_STORE', 'ON_AD').
141+
destination_type: Where users go after click. Common values: 'WEBSITE', 'WHATSAPP', 'MESSENGER',
142+
'INSTAGRAM_DIRECT', 'ON_AD', 'APP', 'FACEBOOK', 'SHOP_AUTOMATIC'.
143+
Also supports multi-channel combos like 'MESSAGING_MESSENGER_WHATSAPP'.
142144
is_dynamic_creative: Enable Dynamic Creative for this ad set.
143145
access_token: Meta API access token (optional - will use cached token if not provided)
144146
"""
@@ -202,15 +204,12 @@ async def create_adset(
202204
"provided_url": store_url
203205
}, indent=2)
204206

205-
# Validate destination_type if provided
206-
if destination_type:
207-
valid_destination_types = ["APP_STORE", "DEEPLINK", "APP_INSTALL", "ON_AD"]
208-
if destination_type not in valid_destination_types:
209-
return json.dumps({
210-
"error": f"Invalid destination_type: {destination_type}",
211-
"valid_values": valid_destination_types
212-
}, indent=2)
213-
207+
# destination_type is passed through to Meta's API without client-side validation.
208+
# Meta supports 23+ values (WHATSAPP, MESSENGER, INSTAGRAM_DIRECT, ON_AD, WEBSITE,
209+
# APP, FACEBOOK, SHOP_AUTOMATIC, multi-channel MESSAGING_* combos, etc.)
210+
# and may add more. Let Meta's API reject invalid values.
211+
# See: facebook-python-business-sdk AdSet.DestinationType
212+
214213
# Basic targeting is required if not provided
215214
if not targeting:
216215
targeting = {

tests/test_mobile_app_adset_creation.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,27 +253,26 @@ async def test_invalid_promoted_object_missing_store_url(
253253
assert 'object_store_url' in result_data['error'].lower()
254254

255255
@pytest.mark.asyncio
256-
async def test_invalid_destination_type(
256+
async def test_invalid_destination_type_passes_through_to_meta(
257257
self, mock_api_request, mock_auth_manager, valid_mobile_app_params, ios_promoted_object
258258
):
259-
"""Test validation error for invalid destination_type value"""
260-
259+
"""Test that invalid destination_type is passed through to Meta API (not rejected by middleware).
260+
261+
Client-side validation was removed because Meta supports 23+ destination_type values
262+
and maintaining a hardcoded allowlist caused false rejections (e.g. WHATSAPP).
263+
"""
264+
261265
result = await create_adset(
262266
**valid_mobile_app_params,
263267
promoted_object=ios_promoted_object,
264268
destination_type="INVALID_TYPE"
265269
)
266-
267-
result_data = json.loads(result)
268-
269-
# Should return validation error - check for data wrapper format
270-
if "data" in result_data:
271-
error_data = json.loads(result_data["data"])
272-
assert 'error' in error_data
273-
assert 'destination_type' in error_data['error'].lower()
274-
else:
275-
assert 'error' in result_data
276-
assert 'destination_type' in result_data['error'].lower()
270+
271+
# The request should reach the Meta API (mock_api_request should be called)
272+
# rather than being rejected by our middleware
273+
call_args = mock_api_request.call_args
274+
params = call_args[0][2]
275+
assert params['destination_type'] == "INVALID_TYPE"
277276

278277
@pytest.mark.asyncio
279278
async def test_app_installs_requires_promoted_object(

0 commit comments

Comments
 (0)