Releases: axisrow/direct-cli
Release list
0.4.3 — batch ads/adgroups add & update
Features — batch ads add via --from-file / --ads-json (#562, #558 follow-up):
ads addnow accepts a batch of flag-form ad rows from a JSONL file
(--from-file) or an inline JSON array (--ads-json); each row is the same
flag set keyed by the kebab flag name without the leading dashes (e.g.
{"type":"TEXT_AD","title":"...","text":"...","href":"...","adgroup-id":1}).
--adgroup-idbecomes the batch default and may be overridden per row. Single
typed-flag mode is unchanged.- The ~400-line flag→object logic of
ads addwas extracted into a reusable,
ctx-freebuild_ad_object()so the single-flag command and the batch
normalizer emit byte-identical ad objects (golden-tested across every
subtype). - New shared
direct_cli/commands/_batch.pyengine (JSONL/inline loading,
chunking, per-chunk send with partial-success reporting, dry-run preview,
add/update-aware result key).keywords addwas migrated onto it with no
behavior change (its existing batch suite is the proof). - Chunk size
ADS_ADD_MAX_BATCH = 100(conservative chunk, not the 1000-object
API ceiling — a partial failure rolls back at most 100 ads).
Features — batch ads update via --from-file / --ads-json (#563, #558 follow-up):
ads updatenow accepts a batch of flag-form ad-update rows from a JSONL file
(--from-file) or an inline JSON array (--ads-json); each row is the same
flag set keyed by the kebab flag name without the leading dashes plus its own
idandtype(e.g.{"id":5,"type":"TEXT_AD","title":"New"}). The
--clear-image-hashmechanic works per row as a JSON boolean. Single
typed-flag mode is unchanged.- The subtype-dispatch body of
ads update(type validation, the
incompatible-flag / "does not convert between subtypes" guard, per-subtype
assembly, and the empty-subtype no-op guard) was extracted into a reusable,
ctx-freebuild_ad_update_object()so the single-flag command and the batch
normalizer emit byte-identical ad-update objects (golden-tested across every
subtype). Reuses the shared_batch.pyengine withmethod="update"/
result_key="UpdateResults". --idand--typebecome per-row in batch mode (each row carries its own);
single-item mode still requires both. The per-row normalizer reproduces the
command's--id/--typerequired checks, the--image-hash/
--clear-image-hashmutex, and the same Click-type coercion as the single
path (a JSON floatidis rejected, not truncated).
Features — batch adgroups add via --from-file / --adgroups-json (#564, #558 follow-up):
adgroups addnow accepts a batch of flag-form ad-group rows from a JSONL
file (--from-file) or an inline JSON array (--adgroups-json); each row is
the same flag set keyed by the kebab flag name without the leading dashes
(e.g.{"name":"G","campaign-id":12,"region-ids":"225","type":"TEXT_AD_GROUP"}).
--campaign-idbecomes the batch default and may be overridden per row.
Single typed-flag mode is unchanged.- The flag→object logic of
adgroups add(type validation, the
incompatible-flag guard, the negative-keyword compatibility check, region IDs,
and per-subtype assembly) was extracted into a reusable, ctx-free
build_adgroup_object()so the single-flag command and the batch normalizer
emit byte-identical ad-group objects (golden-tested across every subtype).
--name/--campaign-id/--region-idsbecome per-row in batch mode;
single-item mode still requires them (parity-gateINTERNAL_VALIDATION
entries). Per-row coercion runs every typed field through its single-flag
Click type (a JSON floatcampaign-idis rejected, not truncated). - The shared
_batch.send_batchgained an optionalpostcallable so
adgroupskeeps its endpoint routing: aUnifiedAdGrouppayload must use API
v501 (_post_adgroups). Because that routing keys off the whole body, a batch
may not mixUNIFIED_AD_GROUPwith other ad-group types — the CLI refuses
the mix up front with a clearUsageErrorrather than send non-unified groups
to the v501 endpoint.
Features — batch adgroups update via --from-file / --adgroups-json (#565, #558 follow-up):
adgroups updatenow accepts a batch of flag-form ad-group-update rows from a
JSONL file (--from-file) or an inline JSON array (--adgroups-json); each
row is the same flag set keyed by the kebab flag name without the leading
dashes plus its ownid(e.g.{"id":5,"name":"New"}). The--dynamic-feed
routing works per row as a JSON boolean. Single typed-flag mode is unchanged.- The subtype-dispatch body of
adgroups update(the mixed-subtype reject
guard, per-subtype assembly, the--dynamic-feedDynamicTextAdGroup ↔
DynamicTextFeedAdGroup routing, and the empty-payload no-op guard) was
extracted into a reusable, ctx-freebuild_adgroup_update_object()so the
single-flag command and the batch normalizer emit byte-identical objects
(golden-tested across every subtype).--idbecomes per-row in batch mode;
single-item mode still requires it (parity-gateINTERNAL_VALIDATIONentry).
Per-row coercion runs every typed field through its single-flag Click type (a
JSON floatidis rejected, not truncated). - Reuses the shared
_batch.send_batchwithmethod="update"/
result_key="UpdateResults"and thepost=_post_adgroupsendpoint routing.
As withadgroups add, a batch may not mixUNIFIED_AD_GROUPwith other
ad-group types (unified groups use API v501) — the CLI refuses the mix up
front with a clearUsageError.
Fixes — reject non-positive IDs before the request (#558):
-
Mutating commands and lifecycle ops took their object-ID selector
(--id/--adgroup-id/--campaign-id/--keyword-id/--client-id)
as a bareint, which accepted0and negatives and forwarded them to the
API (opaque rejection). Every such selector now usesclick.IntRange(min=1)
and rejects a non-positive id with a clearUsageError(exit 2) before any
request. Coverage is the full mutation surface, not a subset:- every
delete/suspend/resume/archive/unarchive/
moderatelifecycle command (via the shared_lifecycle.pyfactory); ads add/ads update,adgroups add/adgroups update,
keywords add/keywords update;campaigns update,feeds update,strategies update,
retargeting update,negativekeywordsharedsets update,vcards add;smartadtargets add/update/set-bids,
audiencetargets add/set-bids,dynamicads add/set-bids,
dynamicfeedadtargets add/set-bids;- the bid setters
bids set/set-auto,keywordbids set/set-auto
(thecampaign-id/adgroup-id/keyword-id"exactly one of" trios),
bidmodifiers add/set; agencyclients update --client-id.
The ad-image lifecycle (
--hash, a string) is unchanged. Secondary
reference-ID flags that point at other objects inside a write payload
(e.g.--feed-id,--counter-id,--vcard-id,--region-id,
--retargeting-list-id) are left as-is for now and tracked as follow-up. - every
-
Batch-size caps (the docs allow up to 1000 objects per add/update and 10000
ids per delete) are intentionally not added: the CLI builds a
single-item payload for every mutation, so there is no caller-controllable
array to overflow. Multi-item batch mode (--from-file) for ads/adgroups is
tracked as follow-up work. -
De-staled the
KEYWORDS_ADD_MAX_BATCHcomment: it claimed the API caps a
keywords.addrequest at 10 (citing an outdated doc page that states no such
number). The real documented per-call limit is 1000; the value10is a
conservative chunk size for batch add, not the API ceiling — comment fixed,
value unchanged.
Fixes — explain Error 8300 on delete/moderate (#548):
raise_for_api_result_errorsnow appends a hint when the API returns code
8300, mirroring the existing 8800 hint: the ad is likely not inDRAFT
status, andStatus=UNKNOWNis an API fallback value (a status outside the
v5 enum), not a business status — such ads can only be archived/unarchived,
not deleted or sent to moderation. Coversads delete/ads moderateand
any command routing throughformat_output. English-only, matching the 8800
hint (output.pydoes not import i18n).
Docs — audiencetargets get requires a filter (#554):
- Clarified that
audiencetargets getcannot page the whole account: unlike
retargeting get --fetch-all, the live API hard-rejects an empty
SelectionCriteria(error 8000 with no criteria, 4001 with{}). The
required-filter guard now explains this and recommends thecampaigns get→
batchedcampaign_idssweep instead. No API behavior change; message only.
Fixes — preflight SelectionCriteria array limits on get (#555, P0):
keywordbids getnow rejects--campaign-ids>10,--adgroup-ids>1000,
--keyword-ids>10000;dynamicads get/smartadtargets getreject
--campaign-ids>2 — before the request, with a clearUsageError(exit 2)
naming the array and ceiling, instead of the opaque APIerror_code=4001.
These are runtime ceilings (the WSDL declares the arraysunbounded), pinned
next to each command with a doc/live-4001 citation, the same discipline as
KEYWORDS_ADD_MAX_BATCH. Verified live 2026-06-16. Othergetarrays
(AdGroupIds/Idson dynamic/smart, etc.) are intentionally not capped
because the live API accepts them.
Internal — dedup v4 Live output-option stack (#550):
- Replaced the byte-identical
--format/--output/--dry-runtrio across the
standard v4 Live andbalancecommands with a sharedv4_output_options
decorator (the v4 analogue ofget_options, epic #491). The CLI surface is
unchanged — same option order, names,click.Choice(["json","table","csv", "tsv"])format, defaults, and h...
0.4.2 — get requires SelectionCriteria + auth precedence
BREAKING CHANGES - get requires SelectionCriteria (#498):
adgroups/ads/keywords/strategies/creatives/dynamicads/
smartadtargets/audiencetargetsgetnow refuse an empty
SelectionCriteriabefore the API call, raising aUsageErrorthat asks for
at least one filter — instead of sending{"SelectionCriteria": {}}(which the
API rejects with the opaque error 4001 for ad-group/ad/keyword resources).
Extends the same guard already shipped forbids/keywordbidsin 0.4.1
(#483). WSDL declaresGetRequest.SelectionCriteriaasminOccurs=1for all
eight resources.retargeting getgains--dry-runand the shared read/pagination option
stack; itsSelectionCriteriastays optional (WSDLminOccurs=0), so a
no-filter call is still valid and now omits the empty criteria from the
payload.- All eight commands and
retargeting getbuild their request via the shared
build_common_paramshelper, completing the dedup epic #491 (B3c).
BREAKING CHANGES - auth precedence (#489):
- Base
YANDEX_DIRECT_TOKEN/YANDEX_DIRECT_LOGINcredentials from the
environment or current-directory.envnow win over the active OAuth profile
selected bydirect auth usewhen--profileis not passed. Explicit
--token,--login, and--profilestill take priority. direct auth statusreports the selected effective credentials, including
base env/.envand secret-manager fallbacks, instead of reporting only the
active OAuth profile.direct auth logincan now ask interactive users whether to save the OAuth
access token and resolved login into the current-directory.env; the default
answer is no.
Docs — live-write coverage limitation (#538):
- Documented why the SMART_CAMPAIGN / DYNAMIC_TEXT_CAMPAIGN /
adimages
live-write lifecycle (dynamicads,smartadtargets,adimages) stays
recorded only as 3500/5004 error cassettes. Verified via direct API calls that
the available sandbox agency account has no client accounts under it
(agencyclients.get→ empty), cannot create one (3001 "No rights to create
clients", access by request only), and that without a client login every
agency-scoped mutation returns 8000. Closed #538 as a documented account-tier
limitation; no CLI code change. Seetests/MANUAL_COVERAGE.md.
0.4.1
Russian-default CLI localization across all command modules (epic #466)
Fixed — bug hunt (#483)
bids get/keywordbids get: refuse an emptySelectionCriteriabefore the API call, raising aUsageErrorthat asks for at least one filter (--campaign-ids/--adgroup-ids/--keyword-ids/--serving-statuses) instead of letting the API reject it with the opaque error 4001.bids set-auto: require exactly one of--campaign-id,--adgroup-id, or--keyword-idvia the sharedadd_single_id_selector(the three are mutually exclusive per the API docs), matchingbids set.reports get: reject a--fieldsvalue that parses to an empty list (e.g.",,,") before building the request, instead of sending an invalidFieldNames: [](API error 8000).- Error-handling consistency:
get/lifecycle handlers acrossbids,keywordbids,negativekeywordsharedsets,balance,strategies,retargeting,ads(all 8 commands), andadvideosnow re-raiseclick.UsageError/click.ClickExceptionbefore the genericexcept Exception, so validation errors keep their Click formatting and exit code 2 instead of being downgraded to anAbort. - Vendor
tapi_yandex_direct:to_columns()no longer raisesIndexErroron report rows shorter than the header (pads with""); the error handler readserror_detailwith.get()so an unfamiliar error structure no longer masks the original API error with aKeyError. utils.parse_priority_goals_spec: corrected the item type annotation toList[Dict[str, Any]].
Fixed — --help hung on a client-login network call (#485)
- After #480,
get_credentialsresolved the bare Client-Login via a networkclients.geton every CLI invocation — including<group> --help. Help/version passes now skip the resolver, the resolver is capped with a hard timeout, and the unit suite neutralizes it so tests never touch the network.
Fixed — auth login saved Passport email, breaking v4 (#482)
direct auth loginstored the Passport email (<login>@yandex.ru) inauth.json, which Direct v4 rejects withFaultCode 259. Login now resolves the bare Client-Login via a one-shot v5clients.get, falling back to the Passport login only if that call fails. Older profiles are migrated in place (one-time).
Localized — interpolated error messages (#478)
- All 121 interpolated
UsageError/BadParameter/print_*messages rewritten into the stablet("<template>").format(**kwargs)pattern, with 96 unique English templates translated to Russian.
Localized — static error messages (#477)
- All 179 static
UsageError/BadParameterliterals across 33 command modules wrapped int(...), with Russian translations intranslations/*.json.
Added — scalable i18n mechanism (#467)
- Source-string-keyed translation catalog.
t()is source-keyed and context-free safe.--localeflag switches between Russian (default) and English.
Localized — Core search (#468)
- 510 unique strings across
campaigns,ads,adgroups,keywords,keywordbids,bids.
Localized — Targeting & creatives (#469)
- 247 unique strings across 16 modules (strategies, bidmodifiers, smartadtargets, vcards, feeds, etc.).
Localized — Account, clients, reporting (#470)
- 142 source strings across 10 modules (clients, agencyclients, reports, changes, auth, etc.). First modules with localized runtime messages.
Localized — v4 Live services (#471)
- 87 source strings across 9 v4 modules. All 42 CLI command groups now fully localized — closes epic #466.
Added — v4 Live deferred methods (#462)
GetKeywordsSuggestion,AdImageAssociation,PayCampaignsByCardexposed in the CLI.
Fixed — docs URLs (#464)
- Removed-doc services pointed at live WSDL.
Full Changelog: v0.4.0...v0.4.1
0.4.0 — typed v4 Live CLI + write-command coverage gates
Milestone release closing the 0.4.0 roadmap (#123): typed Yandex Direct API v4 Live CLI support and completion of the post-0.3.0 write-command coverage gates. All public v4 input stays typed and canonical — no --json passthrough — and mirrors dg-v4/live/* wire shapes 1:1.
Published to PyPI: https://pypi.org/project/direct-cli/0.4.0/
Added — typed v4 Live CLI
- v4 Live command foundation with typed Click groups and a
--dry-runseam that prints the{method, param}body before token/locale enrichment (#124, closes #111). v4financeandv4accounttyped finance and shared-account commands (#125).v4goals,v4events,v4wordstat, andv4forecasttyped commands (#126).v4events get-events-logandv4forecast create-new-forecastexpose every documented input field (#456).- Russian-default CLI help with English opt-in, starting with
v4finance(#458). - Remaining deferred v4 Live methods exposed:
v4keywords get-suggestion,v4adimage get/set, andv4finance pay-campaigns-by-card(dry-run-only). All v4 finance commands carry a "not tested against the live API" disclaimer (#459).
Changed — write-command coverage gates
- Extended the WSDL schema gate to mutating operations;
keywordbids.setis enum-validated against its WSDL*FieldEnum(#118). - Per-method
WRITE_SANDBOXintegration coverage completed (#122). - Closed the remaining mutating
DRY_RUN_PAYLOAD_EXCLUSIONS(#127).
Docs / tooling
- Offline VCR cassettes for all v5 read-only commands (#455).
- v4 Live read cassettes and a fix for an unbounded retry-loop (#457, closes #454).
- Docs/wire-shape scanner with the 2026-05-29 sweep (#451).
- Repointed 4 services (
dynamicads,dynamicfeedadtargets,smartadtargets,vcards) whose human-readable doc pages Yandex removed in Sep 2025 to their live WSDL endpoints; the services remain fully functional (#463). - Re-ran and triaged the wire-shape audit — no real code↔docs drift (#460).
strict_parity_ok, live_model_parity_ok, and schema_parity_ok all report true.
0.3.16 — v4finance Live-4 currency regression fix
BREAKING CHANGES (regression fix — reverts 0.3.15 wire-shape changes):
direct v4finance transfer-moneynow requires--currencyagain and
re-emitsCurrencyon everyFromCampaigns/ToCampaignsitem.
The 0.3.15 removal verified againstdg-v4/reference/TransferMoney
(legacy v4); the actual Live 4 docs at
dg-v4/live/TransferMoneydefinePayCampElementwith
CampaignID,Sum, andCurrency, and explicitly markCurrencyas
obligatory in the Live 4 changelog. The CLI now matches the live
docs 1:1. See audit comment on #125 for the reproducible diff.direct v4finance pay-campaignsnow requires--currencyagain and
re-emitsCurrencyon everyPayments[]item. Same root cause:
dg-v4/reference/PayCampaigns(legacy) lacksCurrency,
dg-v4/live/PayCampaigns(Live 4) requires it.direct v4finance pay-campaignsaccepts--pay-method Overdraft
again. The Live 4 changelog explicitly addsOverdraftfor direct
advertisers (paired withBankfor agencies). OnlyBankkeeps the
--contract-idrequirement.direct v4finance create-invoicenow requires--currencyagain and
re-emitsCurrencyon everyPayments[]item, mirroring
dg-v4/live/CreateInvoice.
This release reverts the wire-shape changes shipped by PRs #441, #442,
#443 (which closed #432, #433, #434). The CLI lives in the v4finance
Live group and must mirror dg-v4/live/*, not dg-v4/reference/*.
0.3.15 — v4finance docs-strict wire-shape (superseded by 0.3.16)
BREAKING CHANGES:
direct v4finance transfer-moneyno longer accepts--currency, and
the wire-body no longer carriesCurrencyonFromCampaigns/
ToCampaignsitems. The official v4 docs
(dg-v4/reference/TransferMoney) definePayCampElementwith only
CampaignIDandSum;Sumis in conventional units. The CLI now
matches the docs 1:1. Closes #432.direct v4finance pay-campaignsno longer accepts--currency. The
v4 documentation (dg-v4/reference/PayCampaigns) defines
PayCampElementwith onlyCampaignIDandSum—Currencyis not
part of the wire-body and was never forwarded to the API. The option
is removed entirely to make the CLI surface 1:1 with the docs.direct v4finance pay-campaignsno longer accepts--pay-method Overdraft. The v4 documentation
(dg-v4/reference/PayCampaigns#PayMethod) lists only"Bank"as a
supported value;Overdraftwas a historical undocumented value
retained by the CLI for sandbox flow. Strict 1:1 docs alignment
drops it.direct v4finance create-invoiceno longer accepts--currency. The
v4 documentation (dg-v4/reference/CreateInvoice) defines
PayCampElementwith onlyCampaignIDandSum—Currencyis not
part of the wire-body and was never forwarded to the API. The option
is removed entirely to make the CLI surface 1:1 with the docs.
0.3.14 — Reports docs-drift protection + Wave 2 nested FieldNames
Fixed:
- Reports drift checker now points at the canonical Yandex docs URLs
(/ru/type,/ru/period,/ru/fields-list,/ru/spec) after Yandex
retired the/ru/reports/<page>path layout and renamedspec.html
tospec. The pre-existingtests/reports_cache/raw/had silently
been captcha-poisoned for three of those pages (~14.6 KB Yandex
SmartCaptcha gateway in place of real docs); cache is now refetched
from the live canonical URLs andspec.jsonis byte-equivalent to
the pre-migration snapshot except for one updated description string. - Five
RESOURCE_MAPPING_V5[*]["docs"]URLs that Yandex moved from the
legacy…/ru/<group>/<group>to…/ru/<group>single-segment form
(dynamictextadtargets,dynamicfeedadtargets,reports,
smartadtargets,vcards). Closes #426.
Added (drift protection):
direct_cli/reports_coverage.py::fetch_reports_specand
direct_cli/wsdl_coverage.py::fetch_wsdl/fetch_live_wsdlnow
refuse responses that look like a Yandex SmartCaptcha gateway (markers
showcaptcha,smartcaptcha,<title>Captcha) or are suspiciously
short. This prevents silently poisoning the docs/WSDL cache with
rate-limited captcha HTML.tests/test_api_coverage.py::TestReportsCoverage::test_reports_cache_files_are_real_content
andTestWsdlCacheFreshness::test_wsdl_cache_files_are_real_content
guard the committed cache files against the same poisoning.scripts/check_all_docs_urls.py— health-checks every URL in
RESOURCE_MAPPING_V5andREPORTS_SPEC_URLS. Hard-fails on
redirect-to-captcha, canonical move (Locationwith a different path
segment), 4xx, or captcha body; soft-warns on 5xx; paces requests to
avoid Yandex rate-limit. Wired intoscripts/release_pypi.shas a
mandatory pre-release gate together withrefresh_reports_cache.py
and a focused pytest pass.
Contract (CLAUDE.md):
- New rule "No URL literals outside the registry" — every Yandex
docs/API URL is declared once inRESOURCE_MAPPING_V5or
REPORTS_SPEC_URLS; importers reference the constant. - New rule "Docs/cache freshness guard" — fetchers and cache files
enforce minimum-size and no-captcha invariants. - New section "PyPI Release" — documents the three pre-release health
checks executed byrelease_pypi.sh.
Breaking changes:
direct ads getflag--text-ad-fieldsis renamed to the
WSDL-canonical--text-ad-field-namesform matching the
TextAdFieldNamesrequest parameter declared byAdsGetRequest.
The old--text-ad-fieldsform is no longer accepted — update
scripts and automation accordingly. Closes #406.direct campaigns add/direct campaigns updateanddirect strategies add/direct strategies updatenow reject--priority-goals
/--priority-goalvalues below 100,000 (0.1 unit in micro-currency).
Per Yandex Direct API (add-text-campaign, strategies-types),
PriorityGoalsItem.Valueisxsd:longin advertiser currency
multiplied by 1,000,000 — the same contract as--budget,
--average-cpa, and other money flags after #399/#400. The error
message suggests the micro-currency conversion (e.g.Did you mean 500000000?). Negative values are also rejected up-front rather than
reaching the API. Both parsers share a single
validate_priority_goal_valuehelper. Closes #387.
Added:
direct sitelinks getnow exposes--sitelink-field-namesfor the
separate WSDLSitelinkFieldNamesrequest parameter
(SitelinkFieldEnum:Title,Href,Description,TurboPageId).
Previously only the top-level--fields(mapping toFieldNames)
was available, so the nestedSitelinks[]projection could not be
controlled from CLI.direct keywordbids getnow exposes--fields,
--search-field-names, and--network-field-namesfor the
separateFieldNames,SearchFieldNames, andNetworkFieldNames
request parameters declared byKeywordBidsGetRequest. Defaults
fromCOMMON_FIELDSare preserved when flags are absent.- Regression test
test_every_nested_fieldnames_param_has_cli_option
(tests/test_api_coverage.py) scans every cached WSDLget
request type for*FieldNamesparameters and verifies that each
one has a matching kebab-case CLI option. Acknowledged remaining
gaps are tracked inNESTED_FIELDNAMES_EXCLUSIONSand #402 so
future additions cannot silently slip in. direct feeds getnow exposes--file-feed-field-namesand
--url-feed-field-namesfor the separate WSDLFileFeedFieldNames
(FileFeedFieldEnum:Filename) andUrlFeedFieldNames
(UrlFeedFieldEnum:Login,Url,RemoveUtmTags) request
parameters declared byFeedsGetRequest. Previously only the
top-level--fields(mapping toFieldNames) was available, so
the nestedFileFeed/UrlFeedprojections could not be
controlled from CLI. Closes #412.direct keywords getnow exposes
--autotargeting-settings-brand-options-field-names
(AutotargetingBrandOptionsFieldEnum:WithoutBrands,
WithAdvertiserBrand,WithCompetitorsBrand) and
--autotargeting-settings-categories-field-names
(AutotargetingCategoriesFieldEnum:Exact,Narrow,
Alternative,Accessory,Broader) for the separate WSDL
*FieldNamesrequest parameters declared by
KeywordsGetRequest. Previously only the top-level--fields
(mapping toFieldNames) was available, so the nested
AutotargetingSettings.BrandOptions/Categoriesprojections
could not be controlled from CLI. Closes #413.direct creatives getnow exposes
--cpc-video-creative-field-names,
--cpm-video-creative-field-names,
--smart-creative-field-names, and
--video-extension-creative-field-namesfor the four nested
WSDL*FieldNamesrequest parameters declared by
CreativesGetRequest(CpcVideoCreativeFieldEnum,
CpmVideoCreativeFieldEnum,SmartCreativeFieldEnum,
VideoExtensionCreativeFieldEnum). Previously only the top-level
--fields(mapping toFieldNames) was available, so the
per-subtype projections could not be controlled from CLI.
Closes #411.direct clients getnow exposes--contract-field-names,
--contragent-field-names,--contragent-tin-info-field-names,
--organization-field-names, and--tin-info-field-namesfor
the five nested WSDL*FieldNamesrequest parameters declared
byClientsGetRequest(ContractInfoFieldEnum,
ContragentInfoFieldEnum,TinInfoFieldEnum,
OrgInfoFieldEnum,TinInfoFieldEnum). The command also gains
--dry-runfor parity with other read-path commands.
Previously only the top-level--fields(mapping toFieldNames)
was available, so the per-subtype ERIR projections could not be
controlled from CLI. Closes #410.direct agencyclients getnow exposes--contract-field-names,
--contragent-field-names,--contragent-tin-info-field-names,
--organization-field-names, and--tin-info-field-namesfor
the five nested WSDL*FieldNamesrequest parameters declared
byAgencyClientsGetRequest(ContractInfoFieldEnum,
ContragentInfoFieldEnum,TinInfoFieldEnum,
OrgInfoFieldEnum,TinInfoFieldEnum). The command also gains
--dry-runfor parity with other read-path commands.
Previously only the top-level--fields(mapping toFieldNames)
was available, so the per-subtype ERIR projections could not be
controlled from CLI. Closes #407.direct adgroups getnow exposes eight additional
--*-field-namesflags for the separate WSDL*FieldNames
request parameters declared byAdGroupsGetRequest:
--autotargeting-settings-brand-options-field-names,
--autotargeting-settings-categories-field-names,
--dynamic-text-ad-group-field-names,
--dynamic-text-feed-ad-group-field-names,
--mobile-app-ad-group-field-names,
--smart-ad-group-field-names,
--text-ad-group-feed-params-field-names, and
--unified-ad-group-field-names. Previously only the top-level
--fields(mapping toFieldNames) was available, so the
per-subtype ad-group projections could not be controlled from
CLI. Closes #405.direct ads getnow exposes sixteen additional--*-field-names
flags for the separate WSDL*FieldNamesrequest parameters
declared byAdsGetRequest:--cpc-video-ad-builder-ad-field-names,
--cpm-banner-ad-builder-ad-field-names,
--cpm-video-ad-builder-ad-field-names,
--dynamic-text-ad-field-names,--listing-ad-field-names,
--mobile-app-ad-builder-ad-field-names,
--mobile-app-ad-field-names,
--mobile-app-cpc-video-ad-builder-ad-field-names,
--mobile-app-image-ad-field-names,
--responsive-ad-field-names,--shopping-ad-field-names,
--smart-ad-builder-ad-field-names,
--text-ad-builder-ad-field-names,
--text-ad-field-names,
--text-ad-price-extension-field-names, and
--text-image-ad-field-names. Previously only the top-level
--fields(mapping toFieldNames) and non-canonical
--text-ad-fieldswere available, so the per-ad-subtype projections
could not be controlled from CLI. Closes #406.
BREAKING CHANGES:
direct campaigns getflags--text-campaign-fields,
--mobile-app-campaign-fields,--dynamic-text-campaign-fields,
--cpm-banner-campaign-fields,--smart-campaign-fields,
--unified-campaign-fields,
--text-campaign-search-strategy-placement-types-fields,
--dynamic-text-campaign-search-strategy-placement-types-fields,
--unified-campaign-search-strategy-placement-types-fields, and
--unified-campaign-package-bidding-strategy-platforms-fields
are renamed to their kebab-case WSDL-canonical*-field-names
form (--text-campaign-field-names,
--mobile-app-campaign-field-names, ...), matching the parameter
names declared byCampaignsGetRequest. The old--*-fields
forms are no longer accepted — update scripts and automation
accordingly. Closes #409.
**Additional features:*...
0.3.13 — BiddingStrategy parity sweep
Breaking changes:
direct campaigns addanddirect campaigns updatenow require all
bidding-strategy money flags to be passed directly in micro-rubles,
matching the existing--budget,--average-cpa,--bid-ceiling, and
--filter-average-cpccontract. The CLI no longer accepts decimal currency
values or performs unit conversion for campaign money
inputs. Closes #399.direct ads addanddirect ads updatenow apply the same API-native
micro-ruble contract to--price-extension-priceand
--price-extension-old-price; price-extension values are no longer parsed
as decimal currency amounts.
Закрытый майлстоун 0.3.13 — BiddingStrategy parity sweep + optional WSDL field parity (#240–#397).
0.3.12 — Optional WSDL field parity completion
55 commits, ~50 closed issues — but this is essentially one cohesive patch:
all optional WSDL fields that were deferred from 0.3.8–0.3.10 are now wired
through as typed CLI flags. No new API endpoints, no architecture changes.
Added
Campaigns — typed add/update flags for all campaign subtypes:
- TextCampaign, DynamicTextCampaign, SmartCampaign, UnifiedCampaign,
MobileAppCampaign, CpmBannerCampaign optional settings and strategy controls. - Campaign-level
--tracking-params,--time-targeting-json,--notification-json.
Closes #291–#296.
Ad groups — typed add/update flags for all group subtypes:
DYNAMIC_TEXT_AD_GROUPadvanced fields,DYNAMIC_TEXT_FEED_AD_GROUP,
MOBILE_APP_AD_GROUP,CPM_*rare subtypes,UNIFIED_AD_GROUP,
SMART_AD_GROUP,TextAdGroupFeedParams, negative keyword typed flags.
Closes #279–#284.
Ads add — typed flags for every ad subtype:
TEXT_ADextension fields,RESPONSIVE_AD,SHOPPING_AD,LISTING_AD,
AdBuilderfamily,DYNAMIC_TEXT_AD, mobile app,SMART_AD_BUILDER_AD.
Closes #273–#278.
Ads update — full subtype coverage:
DYNAMIC_TEXT_AD,RESPONSIVE_AD,SHOPPING_AD,LISTING_AD,
AdBuilderfamily,SMART_AD_BUILDER_AD,MOBILE_APP_IMAGE_AD,
residual field classification. Closes #267–#272.TEXT_ADupdate:VideoExtension,PriceExtension, callout operations.
Closes #238, #245.
Keywords — autotargeting typed projection:
- Scalar flags,
AutotargetingCategories,AutotargetingBrandOptions,
AutotargetingSettings, batch input handling.
Closes #285–#289.
Strategies — remaining optional fields:
CustomPeriodBudget,ExplorationBudget, remaining subtype optional fields
for bothaddandupdate. Closes #297–#300.
Bids — selector/context/priority optional fields for bids set
and keywordbids set. Closes #301.
Other resources:
audiencetargets add:ContextBid,StrategyPriority. Closes #302.dynamicfeedadtargets add: condition arguments parity. Closes #303.smartadtargets add/update: condition arguments parity. Closes #304.clients update:EmailSubscriptions,Settings, full
ErirAttributes(Organization, Contract, Contragent). Closes #305–#308.feeds add/update:FileFeedupload,UrlFeedparity. Closes #253, #264.sitelinks add:TurboPageId. Closes #257.retargeting add/update:Description. Closes #256.bidmodifiers add: optional adjustment parity. Closes #254.vcards add:InstantMessenger,PointOnMap. Closes #246.adextensions get:CalloutFieldNamesflag.
Fixed
v0.3.11
Added:
direct campaigns addanddirect campaigns updatenow expose
--tracking-paramsfor the campaign-level tracking query string
(TextCampaign/DynamicTextCampaign/SmartCampaign.TrackingParams).
campaigns updategained an optional--typediscriminator —
required when--tracking-paramsis set, validated against
the three subtypes supported by the CLI. Backward compatible:
existingcampaigns update --id N --name Xcalls without--type
keep working unchanged. Closes #230.direct v4account account-managementnow supports--action Get,
Deposit,Invoice, andTransferMoneyin addition toUpdate,
matching the official v4 Live docs
(https://yandex.ru/dev/direct/doc/dg-v4/reference/AccountManagement-docpage/).
Getis read-only and accepts optional--logins/--account-ids
filters.Deposit,Invoice, andTransferMoneyare financial
mutations: they need--finance-token(or--master-token+
--operation-num+--finance-login) and respect the existing
dry-run-unless-sandbox rule. A Click-side allow-list rejects flags
that do not belong to the chosen action before any body is built.
Refs #125.
Fixed:
direct v4 *command wrappers now letclick.ClickException
(includingUsageErrorfromcall_v4shape validation) propagate to
Click instead of swallowing it in the genericexcept Exception.
Shape-validation errors keep their usage hint and exit with code 2,
matching Click's contract; non-Click runtime errors still surface
throughprint_error+Abort(exit 1). Closes #227.
Breaking changes:
direct v4finance get-credit-limitsno longer accepts--logins; the
request body now omitsparamper the official v4 Live docs
(https://yandex.ru/dev/direct/doc/dg-v4/reference/GetCreditLimits.html),
which define the body asmethod,finance_token, andoperation_num
only. Refs #125.