Context
direct-cli 0.3.11 added typed flags for most TextAdUpdateBase fields via issue #202 / PR #216 (--title2, --sitelink-set-id, --vcard-id, --turbo-page-id, --display-url-path). One field from the same base type was left out: CalloutSetting — and it is the only WSDL-supported way to manage callout extensions on an existing ad.
WSDL evidence (https://api.direct.yandex.com/v5/ads?wsdl):
<!-- TextAdUpdateBase, line 777 -->
<xsd:complexType name="TextAdUpdateBase">
<xsd:sequence>
<xsd:element name="VCardId" type="xsd:long" .../>
<xsd:element name="AdImageHash" type="xsd:string" .../>
<xsd:element name="SitelinkSetId" type="xsd:long" .../>
<xsd:element name="CalloutSetting" type="ext:AdExtensionSetting" .../>
</xsd:sequence>
</xsd:complexType>
CalloutSetting is also present in ResponsiveAdUpdate (line 815).
AdExtensionSetting (https://soap.direct.yandex.ru/v5/adextensiontypes.xsd):
<xsd:complexType name="AdExtensionSettingItem">
<xsd:sequence>
<xsd:element name="AdExtensionId" type="xsd:long" minOccurs="1" maxOccurs="1"/>
<xsd:element name="Operation" type="general:OperationEnum" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="AdExtensionSetting">
<xsd:sequence>
<xsd:element name="AdExtensions" type="ext:AdExtensionSettingItem"
minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
Operation is ADD | REMOVE | SET. SET is mutually exclusive with ADD / REMOVE in the same request.
Verified by the downstream user against live JSON API:
{
"method": "update",
"params": {
"Ads": [{
"Id": 17722952445,
"TextAd": {
"CalloutSetting": {
"AdExtensions": [
{"AdExtensionId": 19718116, "Operation": "ADD"},
{"AdExtensionId": 19718117, "Operation": "ADD"},
{"AdExtensionId": 19718118, "Operation": "ADD"}
]
}
}
}]
}
}
After the call, ads.get returns AdExtensions: [{AdExtensionId, Type: "CALLOUT"}, ...] as expected.
Current behaviour in CLI 0.3.11
direct ads update --help exposes no flag mapped to CalloutSetting. There is no way to attach / detach / replace callouts on an existing ad through CLI — the user has to bypass CLI and call the JSON API directly, which breaks the strict-WSDL-parity policy and the downstream yandex-direct-mcp-plugin's "never bypass CLI" rule.
(Issue #125 in the downstream plugin was misdiagnosed earlier as "API doesn't support this" because the wrong payload key was used (TextAd.AdExtensions instead of TextAd.CalloutSetting). The hint added in CLI 0.3.10 ("--ad-extensions is for ads add, not ads update") is good but doesn't help the user find the real way.)
Proposed flags
--callouts-add TEXT Comma-separated AdExtension IDs of type CALLOUT to attach (Operation=ADD)
--callouts-remove TEXT Comma-separated AdExtension IDs to detach (Operation=REMOVE)
--callouts-set TEXT Comma-separated AdExtension IDs to replace the full set (Operation=SET)
Validation:
--callouts-set is mutually exclusive with --callouts-add / --callouts-remove in a single invocation (matches WSDL: SET cannot mix with ADD/REMOVE).
- TEXT_AD only (matches
TextAdUpdateBase); same per---type gating as existing flags.
The plugin would pass them as comma-separated lists and CLI builds the CalloutSetting.AdExtensions[] payload, splitting --callouts-add + --callouts-remove into a single array with the right Operation per item.
Scope (out)
VideoExtension, PriceExtension (also *UpdateItem wrappers on TextAdUpdate) — separate issue if needed. This issue is scoped to CalloutSetting, which is the most common case.
ResponsiveAdUpdate.CalloutSetting — direct ads update only supports TEXT_AD / TEXT_IMAGE_AD / MOBILE_APP_AD subtypes today. If responsive ads land later in CLI, the same flags would apply.
Downstream
Tracked in yandex-direct-mcp-plugin: axisrow/yandex-direct-mcp-plugin#127
🤖 Generated with Claude Code
Context
direct-cli0.3.11 added typed flags for mostTextAdUpdateBasefields via issue #202 / PR #216 (--title2,--sitelink-set-id,--vcard-id,--turbo-page-id,--display-url-path). One field from the same base type was left out:CalloutSetting— and it is the only WSDL-supported way to manage callout extensions on an existing ad.WSDL evidence (
https://api.direct.yandex.com/v5/ads?wsdl):CalloutSettingis also present inResponsiveAdUpdate(line 815).AdExtensionSetting(https://soap.direct.yandex.ru/v5/adextensiontypes.xsd):OperationisADD | REMOVE | SET.SETis mutually exclusive withADD/REMOVEin the same request.Verified by the downstream user against live JSON API:
{ "method": "update", "params": { "Ads": [{ "Id": 17722952445, "TextAd": { "CalloutSetting": { "AdExtensions": [ {"AdExtensionId": 19718116, "Operation": "ADD"}, {"AdExtensionId": 19718117, "Operation": "ADD"}, {"AdExtensionId": 19718118, "Operation": "ADD"} ] } } }] } }After the call,
ads.getreturnsAdExtensions: [{AdExtensionId, Type: "CALLOUT"}, ...]as expected.Current behaviour in CLI 0.3.11
direct ads update --helpexposes no flag mapped toCalloutSetting. There is no way to attach / detach / replace callouts on an existing ad through CLI — the user has to bypass CLI and call the JSON API directly, which breaks the strict-WSDL-parity policy and the downstreamyandex-direct-mcp-plugin's "never bypass CLI" rule.(Issue #125 in the downstream plugin was misdiagnosed earlier as "API doesn't support this" because the wrong payload key was used (
TextAd.AdExtensionsinstead ofTextAd.CalloutSetting). The hint added in CLI 0.3.10 ("--ad-extensionsis forads add, notads update") is good but doesn't help the user find the real way.)Proposed flags
Validation:
--callouts-setis mutually exclusive with--callouts-add/--callouts-removein a single invocation (matches WSDL:SETcannot mix withADD/REMOVE).TextAdUpdateBase); same per---typegating as existing flags.The plugin would pass them as comma-separated lists and CLI builds the
CalloutSetting.AdExtensions[]payload, splitting--callouts-add+--callouts-removeinto a single array with the rightOperationper item.Scope (out)
VideoExtension,PriceExtension(also*UpdateItemwrappers onTextAdUpdate) — separate issue if needed. This issue is scoped toCalloutSetting, which is the most common case.ResponsiveAdUpdate.CalloutSetting—direct ads updateonly supports TEXT_AD / TEXT_IMAGE_AD / MOBILE_APP_AD subtypes today. If responsive ads land later in CLI, the same flags would apply.Downstream
Tracked in
yandex-direct-mcp-plugin: axisrow/yandex-direct-mcp-plugin#127🤖 Generated with Claude Code