VK Ads For All is a portable Codex plugin bundle for working with the VK Ads API from an agent workspace.
It is not a client archive and it is not a browser automation. It gives a Codex agent a clean, reusable operating layer for:
- read-only VK Ads account inspection;
- reproducible account snapshots saved to files;
- safe campaign, ad group, banner, audience, goal, and statistics work;
- audience preparation from phones or email;
- structure checks after changes;
- public-safety scanning before the bundle is published or copied.
The repository intentionally contains only placeholder examples. It must never contain real tokens, customer names, account snapshots, reports, media, private domains, CRM exports, audience lists, or local operator paths.
This README is written for another Codex agent entering the repository cold.
The agent should be able to answer:
- What is this bundle for?
- Which file should be read first?
- How do I authenticate to VK Ads without exposing secrets?
- How do I run a safe read-only check?
- How do I prepare a write without accidentally changing the ad account?
- Which checks must pass before I report success?
- What must never be committed?
plugins/vk-ads-for-all/.codex-plugin/plugin.json- Codex plugin manifest..agents/plugins/marketplace.json- repo-local marketplace entry that points Codex to the plugin folder.plugins/vk-ads-for-all/skills/vk-ads-for-all/SKILL.md- the main operating skill. Read this before using the API.plugins/vk-ads-for-all/skills/vk-ads-for-all/references/- safety, API-surface, and write-workflow references.plugins/vk-ads-for-all/scripts/vk_ads_api_cli.py- deterministic VK Ads API caller with saved request and response files.plugins/vk-ads-for-all/scripts/vk_ads_auth.py- OAuth helper that exchangesclient_id/client_secretfor a private token file and verifiesuser.json.plugins/vk-ads-for-all/scripts/vk_ads_account_snapshot.py- read-only account snapshot.plugins/vk-ads-for-all/scripts/vk_ads_audience_upload.py- local audience normalization and optional upload.plugins/vk-ads-for-all/scripts/vk_ads_integrity_check.py- JSON-rule structure verification from readback files.plugins/vk-ads-for-all/scripts/scan_public_safety.py- scanner for secrets and customer-data leakage.plugins/vk-ads-for-all/scripts/validate_bundle.sh- one-command local validation.plugins/vk-ads-for-all/mcp/vk-ads/server.py- optional MCP server for common read tools and guarded raw API calls.plugins/vk-ads-for-all/examples/- placeholder-only environment, request, readback, and report examples.plugins/vk-ads-for-all/docs/authentication.md- step-by-step path for gettingclient_id/client_secretin the VK Ads UI and exchanging them locally.
Start from the repository root:
find . -maxdepth 8 -type f | sort
python3 -m json.tool plugins/vk-ads-for-all/.codex-plugin/plugin.json >/dev/null
python3 -m json.tool .agents/plugins/marketplace.json >/dev/null
sed -n '1,220p' plugins/vk-ads-for-all/skills/vk-ads-for-all/SKILL.mdThen switch to the plugin root for all script examples:
cd plugins/vk-ads-for-allRead these files in order:
sed -n '1,220p' skills/vk-ads-for-all/SKILL.md
sed -n '1,220p' skills/vk-ads-for-all/references/safety-checklist.md
sed -n '1,220p' skills/vk-ads-for-all/references/api-surface.md
sed -n '1,260p' skills/vk-ads-for-all/references/write-workflows.mdDo not call VK Ads and do not edit an ad account until the safety checklist and write workflow are understood.
Use Python 3.11 or newer.
From the plugin root:
python3 -m pip install -r requirements.txtMinimum package for scripts: httpx.
Optional MCP server package: mcp.
There is no browser login flow in this repository. VK Ads API access uses an OAuth access token, passed to scripts and MCP tools through the VK_ADS_TOKEN environment variable.
Official VK Ads API docs:
- API entrypoint:
https://ads.vk.com/doc/api - Authorization page:
https://ads.vk.com/ru/doc/api/info/Авторизация%20в%20API - VK Ads help article for API access:
https://ads.vk.com/help/articles/help_api
The official authorization page describes OAuth2 flows. For own-account API work, use Client Credentials Grant. For agency or manager client work, use Agency Client Credentials Grant. In both cases, the API returns an access_token; every API request must be signed with Authorization: Bearer <access_token>.
The plugin cannot create client_id and client_secret by API. Those values are issued inside the VK Ads account UI.
Open the exact VK Ads account, then use:
- Settings.
- API Access.
- Request API Access.
- Fill the full name and contacts of the employee responsible for API use.
- Submit the request.
- After access is granted, copy
client_id. - Click the button to get
client_secret. - Save
client_secretimmediately into a private local file.
Official VK Ads help says the secret is available only for 10 minutes and must be saved immediately. Do not paste it into chat, README files, reports, examples, issue text, or committed request files.
If the button is not available, first check account details:
- agencies and legal-entity advertisers: details in the Budget section must be filled and moderated;
- individual advertisers: details in Settings must be filled.
For the fuller agent checklist, read:
sed -n '1,260p' docs/authentication.mdCreate a private local file that contains API client credentials, not an access token yet:
cp examples/vk_ads.env.example .env.oauth
chmod 600 .env.oauthEdit .env.oauth locally:
VK_ADS_CLIENT_ID=REPLACE_WITH_PRIVATE_CLIENT_ID
VK_ADS_CLIENT_SECRET=REPLACE_WITH_PRIVATE_CLIENT_SECRETFor an agency or manager client token, add one of:
VK_ADS_AGENCY_CLIENT_NAME=REPLACE_WITH_PRIVATE_AGENCY_CLIENT_NAME
VK_ADS_AGENCY_CLIENT_ID=REPLACE_WITH_PRIVATE_AGENCY_CLIENT_IDNever commit .env.oauth.
For your own VK Ads account:
python3 scripts/vk_ads_auth.py \
--grant client_credentials \
--env-file .env.oauth \
--output-env .env \
--verify-user-output /tmp/vk_ads_user.jsonFor an agency or manager client account:
python3 scripts/vk_ads_auth.py \
--grant agency_client_credentials \
--env-file .env.oauth \
--output-env .env \
--verify-user-output /tmp/vk_ads_user.jsonTo refresh an existing token later:
python3 scripts/vk_ads_auth.py \
--grant refresh_token \
--env-file .env \
--output-env .env \
--verify-user-output /tmp/vk_ads_user.jsonThe helper:
- sends the OAuth request to
https://ads.vk.com/api/v2/oauth2/token.json; - writes
VK_ADS_TOKENinto the private.envfile; - writes
VK_ADS_REFRESH_TOKENwhen VK Ads returns one; - sets file permissions to owner-only;
- optionally verifies access by reading
user.json; - never prints the token value to the terminal.
Open /tmp/vk_ads_user.json and confirm it is the expected account before doing anything else.
Leave VK_ADS_ALLOW_WRITE unset by default. Set it only for a specific approved MCP write after the payload and readback path are prepared.
From the plugin root:
python3 scripts/vk_ads_api_cli.py GET user.json \
--output /tmp/vk_ads_user.json \
--env-file .envThen check that the saved file describes the expected account context before reading campaigns:
python3 scripts/vk_ads_api_cli.py GET ad_plans.json \
--params '{"limit": 10, "offset": 0, "sorting": "-id"}' \
--output /tmp/vk_ads_campaigns.json \
--env-file .envIf token or account context is wrong, stop. Do not continue to snapshots or writes.
Use this when the user asks to inspect the account or before planning a change:
python3 scripts/vk_ads_account_snapshot.py \
--output-dir output/snapshot_$(date +%Y%m%d_%H%M%S) \
--active-only \
--env-file .envThe snapshot writes JSON files under output/, which is ignored and must not be committed.
Use --campaign-ids only with explicit campaign IDs from a trusted readback file. An empty --campaign-ids "" is treated as an error so the script cannot accidentally expand to the whole account.
Local normalization can run without a VK Ads token:
python3 scripts/vk_ads_audience_upload.py \
--name "Example audience 2026-05-21" \
--type phones \
--input-file /tmp/vk_ads_source.csv \
--field phone \
--output-dir /tmp/vk_ads_audience_prepare \
--min-records 100 \
--summary-onlyUse --summary-only for safe tests because it writes only a manifest, not the prepared contact list.
For real audience uploads:
- keep source files outside the repository;
- write prepared files only to ignored private folders;
- get explicit user approval for upload;
- add
--upload --env-file .env; - verify the saved upload readback before reporting success.
Every live write must follow this order:
- Read current state.
- Save the exact intended payload to a file.
- Run the write command once without confirmation. This saves the request and does not call VK Ads.
- Get explicit user approval for the specific write.
- Run with
--confirm-writeand--readback-path. - Read back the changed object and affected children.
- Run an integrity check when structure matters.
- Report success only if readback and checks match the intended result.
Dry-run write preparation:
python3 scripts/vk_ads_api_cli.py POST ad_plans.json \
--payload-file output/payloads/create_campaign.json \
--request-output /tmp/vk_ads_create_campaign.request.jsonConfirmed write after approval:
python3 scripts/vk_ads_api_cli.py POST ad_plans.json \
--payload-file output/payloads/create_campaign.json \
--confirm-write \
--readback-path ad_plans.json \
--readback-params '{"_id__in": "REPLACE_WITH_CREATED_ID"}' \
--env-file .envDo not use inline --data for writes. The script blocks that because the payload must exist as a saved file before execution.
Prepare a JSON rule file from the example:
cp examples/integrity_rules.example.json output/integrity_rules.jsonUpdate it to point at real readback files and expected names, statuses, budgets, targetings, URLs, and banner counts.
Run:
python3 scripts/vk_ads_integrity_check.py \
--spec output/integrity_rules.json \
--output output/integrity_report.jsonIf ok is false, the task is not complete.
The plugin includes .mcp.json and a sanitized MCP server.
The server reads only environment variables:
VK_ADS_TOKENVK_ADS_OUTPUT_DIRVK_ADS_API_BASE_V2VK_ADS_API_BASE_V3VK_ADS_ALLOW_WRITE
Raw MCP writes are disabled unless VK_ADS_ALLOW_WRITE=true. Even then, write calls require a file-backed payload and a readback path.
Use MCP for typed reads when available. Use scripts when you need an exact saved request and response trail.
Before pushing or making this repository public:
bash plugins/vk-ads-for-all/scripts/validate_bundle.sh
python3 plugins/vk-ads-for-all/scripts/scan_public_safety.py .
python3 plugins/vk-ads-for-all/scripts/scan_public_safety.py . --denylist /path/to/private-denylist.txtThe private denylist should include customer names, domains, account markers, local operator markers, and anything else that must never appear in a public artifact. Keep that denylist outside the repository.
The scanner must find zero issues.
.env,.env.*,.envrc- API tokens, client secrets, refresh tokens, bearer tokens
- raw account snapshots or API responses
- write responses
- customer reports
- CRM exports
- audience source files or prepared uploads
- customer names, domains, landing pages, campaign IDs, account markers
- screenshots or media from a client account
- local absolute paths from an operator machine
reports/,private/,output/, ortmp/
From repository root:
bash plugins/vk-ads-for-all/scripts/validate_bundle.sh
python3 plugins/vk-ads-for-all/scripts/scan_public_safety.py .From plugin root:
cd plugins/vk-ads-for-all
python3 scripts/vk_ads_api_cli.py GET user.json --output /tmp/vk_ads_user.json --env-file .env
python3 scripts/vk_ads_account_snapshot.py --output-dir output/snapshot_$(date +%Y%m%d_%H%M%S) --active-only --env-file .env
python3 scripts/vk_ads_audience_upload.py --name "Example audience" --type phones --input-file /tmp/vk_ads_source.csv --field phone --output-dir /tmp/vk_ads_audience_prepare --summary-only
python3 scripts/vk_ads_integrity_check.py --spec examples/integrity_rules.example.json --output /tmp/vk_ads_integrity_report.jsonDo not say a VK Ads task is complete because an API write returned success.
Completion requires:
- saved request payload;
- saved API response;
- readback of the changed object and relevant children;
- integrity check when structure matters;
- name-first human report;
- no secrets or customer data in committed files.