Connect an MCP client
Connect the official Telegram Ads API key through the extension, then add https://api.tlmtr.dev/mcp/ads (dev) or https://api.tlmtr.io/mcp/ads (production configuration) to your AI client. Telemetrio opens a separate consent page for that client. The provider key stays encrypted on the server; the AI client receives scoped access, never the key. Existing Telemetrio analytics authorization does not grant Ads access.
Three permission groups
| Permission | Scope | Allows |
|---|---|---|
| Read-only | telemetrio:ads:read | Read explicitly selected accounts, ads, statistics, transactions, reports, audiences, Pixel and targeting dictionaries. Required for every selected account. |
| Manage advertising | telemetrio:ads:manage | Account information, creative and delivery changes, start/pause/delete, review submission, uploads, audiences and Pixel. Resuming funded ads can spend existing funds. |
| Manage budgets | telemetrio:ads:budget | Allocate/withdraw funds, CPM and daily budget limits. Ad creation requires both management groups. |
Rights belong to each concrete connection/account pair. A scope union does not give every account every right. Related accounts can have different permissions, including access without the root. New accounts/connections never join existing grants automatically. Revocation blocks subsequent work and withheld results; disconnecting removes the provider credential for every client. Neither action revokes Telegram's own key.
Interactive Ads workspace
Clients supporting MCP Apps can render Ads explorer and Review changes inside the conversation. Clients without a renderer receive the same structured and textual data. These tools use the existing Ads authorization; no provider key is passed to the widget. The UI is English and follows the host's light/dark theme.
| Tool | Purpose |
|---|---|
ads_explore_ads | Browse one granted account, 50 ads per page, with lifetime metrics and account capabilities. Select, filter, sort, inspect details and compare ads. |
ads_review_changes | Prepare up to 20 changes in one account and show fresh before/after values. No Telegram mutation is sent. |
ads_apply_review | Apply the sealed review after explicit user confirmation. Each operation reports its own result. |
ads_inspect_review | Inspect operation results after an interruption without repeating provider writes. |
Ask your AI client: “Open the Ads explorer for my personal account.” Select the
account from ads_list_connections when several are available. Search and sorting
operate on loaded ads; use Load more for additional pages. Metrics are lifetime,
not a selected-period report. Missing clicks/metrics are shown as unavailable;
actions are labeled by their provider type.
Select ads and choose pause/resume, title/text/CPM/daily-budget edits or budget allocation/withdrawal. Controls reflect each account's granted rights. The review shows separate allocation and withdrawal totals in the account currency. Resuming a funded ad can spend its existing budget. Preparing or editing a review never applies it; Confirm applies only the reviewed intent.
Reviews expire after 15 minutes and are bound to the original authorization and connection generation. If relevant ad values change, prepare a new review. A batch is not atomic: earlier changes may succeed even if a later one fails. A successful edit is read back; Not confirmed means Telegram accepted it but current values differ or could not be verified. Do not repeat blindly.
After an interrupted confirmation, use Inspect status. An unknown outcome is not automatically retried; reconcile the existing operation ID before creating another intent. Review status can be inspected for 24 hours. Revoked or replaced credentials block the old review. Standard canonical tools remain available for other API operations.
The single bundled resource is ui://telemetrio-ads/workspace-v1.html. It loads no
external scripts, images or fonts; data and actions go through the host's existing
MCP connection. The public OAuth bridge exposes only this exact UI resource.
Account capabilities before creating ads
Read the selected account before planning a campaign:
- Root:
ads_api_get_current_account. - Related account:
ads_api_get_accounts_by_id, with its exact granted ID. ads_list_connectionsshows cached root currency and capabilities. Older connections can showunknown; refresh the connection or read the account.
Account results include capabilities, separately from your granted permissions:
| Account | Permitted destination family |
|---|---|
| TON | Telegram channels/posts, bots and Mini Apps; no external websites |
| EUR | Telegram destinations or external websites, subject to account and placement restrictions |
| Stars (XTR) | Only the channel or bot that earned the Stars |
These are versioned Telemetrio policies derived from currency. They do not
represent a provider guarantee. Targeting, media, Pixel, retargeting and geographic
delivery remain unknown until independently verified.
For Stars, the Ads API does not currently expose the earning-peer binding.
Capabilities show bound_peer: null and bound_peer_status: unknown. This version
blocks creation and destination changes with DESTINATION_BINDING_UNKNOWN and
validation: requires_verification; use Telegram to verify and manage that
source-specific destination. Reconnecting does not resolve the missing binding.
Other permitted operations on existing ads remain available.
Create and destination-edit requests validate the actual selected account's
currency before a provider write. TON/Stars website requests return
DESTINATION_NOT_SUPPORTED with an English explanation and field: promote_url.
The original Telegram error and requestId are retained if the provider rejects a
request later. Use ads_get_operation to inspect the outcome; do not automatically
retry, change the destination or switch accounts. The server performs no such
substitutions.
Canonical tools and native parameters
All 45 methods below are implemented as canonical tools. Tool visibility reflects usable rights; calls independently check exact rights and live credential generation. Each has strict input {connectionId, accountId?, params, operationId?}. Native fields stay inside params; required native fields below are marked *. Either accountId or native params.account_id selects the concrete account; if both are supplied, they must agree. Omitting both selects the provider root, so a related-only grant must name its account. Root-specific methods (current account, create account, related lists, batch account lookup and transaction status) retain their root context; requested or returned account data still requires explicit rights. Transfer methods use native account_id for the related endpoint and the connection root for the other endpoint. Batch IDs must all be granted. Use tools/list for complete types, constraints and method-specific descriptions.
| Native method | MCP tool | Required group beyond Read-only | Native parameters |
|---|---|---|---|
createAccount | ads_api_create_account | Manage advertising | title *, full_name *, email *, phone_number *, country *, city *, legal_name, idempotency_key |
editAccountInfo | ads_api_edit_account_info | Manage advertising | account_id, title, full_name, email, phone_number, country, city, legal_name |
getAccountInfo | ads_api_get_account_info | — | account_id |
getRelatedAccountsList | ads_api_get_related_accounts_list | — | offset, limit |
increaseAccountBudget | ads_api_increase_account_budget | Manage budgets | account_id *, amount *, idempotency_key |
decreaseAccountBudget | ads_api_decrease_account_budget | Manage budgets | account_id *, amount *, idempotency_key |
getTransactionStatus | ads_api_get_transaction_status | — | transaction_id * |
getCurrentAccount | ads_api_get_current_account | — | none |
getAccountsById | ads_api_get_accounts_by_id | — | account_ids * |
getAccountTransactionsList | ads_api_get_account_transactions_list | — | account_id, offset, limit |
getAccountStats | ads_api_get_account_stats | — | account_id, from_time *, to_time *, interval * |
getAccountReport | ads_api_get_account_report | — | account_id, year *, month * |
uploadAdPhoto | ads_api_upload_ad_photo | Manage advertising | account_id, file * |
uploadAdVideo | ads_api_upload_ad_video | Manage advertising | account_id, file * |
uploadWebsitePhoto | ads_api_upload_website_photo | Manage advertising | account_id, file * |
createAd | ads_api_create_ad | Both management groups | account_id, title *, text, photo_id, video_id, promote_url *, cpm *, placement *, target *, impression_frequency, website_name, website_photo_id, button, conversion_event_id, additional_info, show_userpic, initial_budget, daily_budget_limit, is_paused, activate_date, deactivate_date, schedule, return_target, idempotency_key |
editAd | ads_api_edit_ad | By field: advertising and/or budgets | account_id, ad_id *, title, text, photo_id, video_id, promote_url, cpm, impression_frequency, website_name, website_photo_id, button, conversion_event_id, additional_info, show_userpic, daily_budget_limit, is_paused, activate_date, deactivate_date, schedule, return_target |
editAdStatus (deprecated alias → editAd) | ads_api_edit_ad_status | Manage advertising | account_id, ad_id *, is_paused *, return_target |
increaseAdBudget | ads_api_increase_ad_budget | Manage budgets | account_id, ad_id *, amount *, return_target, idempotency_key |
decreaseAdBudget | ads_api_decrease_ad_budget | Manage budgets | account_id, ad_id *, amount *, return_target, idempotency_key |
submitAdForReview | ads_api_submit_ad_for_review | Manage advertising | account_id, ad_id *, return_target |
deleteAd | ads_api_delete_ad | Manage advertising | account_id, ad_id * |
getAdsById | ads_api_get_ads_by_id | — | account_id, ad_ids *, return_target |
getAdsList | ads_api_get_ads_list | — | account_id, offset, limit, return_target |
getAdTransactionsList | ads_api_get_ad_transactions_list | — | account_id, ad_id *, offset, limit |
getAdStats | ads_api_get_ad_stats | — | account_id, ad_id *, from_time *, to_time *, interval * |
createAudience | ads_api_create_audience | Manage advertising | account_id, title *, add_phones, idempotency_key |
editAudience | ads_api_edit_audience | Manage advertising | account_id, audience_id *, title, add_phones, remove_phones, reset_phones |
deleteAudience | ads_api_delete_audience | Manage advertising | account_id, audience_id * |
getAudiencesById | ads_api_get_audiences_by_id | — | account_id, audience_ids * |
getAudiencesList | ads_api_get_audiences_list | — | account_id, offset, limit |
createPixel | ads_api_create_pixel | Manage advertising | account_id, idempotency_key |
getPixel | ads_api_get_pixel | — | account_id |
createPixelEvent | ads_api_create_pixel_event | Manage advertising | account_id, title *, type *, idempotency_key |
editPixelEvent | ads_api_edit_pixel_event | Manage advertising | account_id, event_id *, title * |
deletePixelEvent | ads_api_delete_pixel_event | Manage advertising | account_id, event_id * |
getPixelEventsById | ads_api_get_pixel_events_by_id | — | account_id, event_ids * |
getPixelEventsList | ads_api_get_pixel_events_list | — | account_id, offset, limit |
getTargetLanguagesList | ads_api_get_target_languages_list | — | none |
getTargetTopicsList | ads_api_get_target_topics_list | — | none |
getTargetCountriesList | ads_api_get_target_countries_list | — | none |
getTargetLocationsById | ads_api_get_target_locations_by_id | — | location_ids * |
getTargetLocationsList | ads_api_get_target_locations_list | — | country_code *, query *, offset, limit |
getTargetChannel | ads_api_get_target_channel | — | channel_id *, for_excluding |
getTargetBot | ads_api_get_target_bot | — | bot_id * |
editAdStatus is retained only as a compatibility alias to editAd with is_paused; prefer ads_api_edit_ad. There are also nine convenience read tools: ads_list_connections, ads_list_ads, ads_get_ad, ads_get_account_stats, ads_get_ad_stats, ads_get_transactions, ads_get_account_report, ads_get_targeting_options and ads_lookup_target. Convenience data tools use the root account and cannot expose an ungranted root. ads_list_connections includes actual authorized accountAccess rows; related-only grants omit root metadata.
Money and CPM use the selected account currency (EUR, TON or XTR), not cents or a currency conversion. initial_budget allocates funds; is_paused and scheduling control delivery. Account transfers need Manage budgets on both endpoints, and transaction status needs Read-only on both returned endpoints. succeeded for the request does not mean the transfer settled: explicitly poll ads_api_get_transaction_status using transaction_id until native status is completed or failed.
Timestamps use Unix seconds. Statistics have an exclusive end and at most 1000 intervals of 300 or 86400 seconds. A native schedule uses seven 24-bit week_hours_mask values, one hour per bit, and a fixed UTC timezone offset in seconds, or use_viewer_timezone for users targeting. Pass schedule:false to clear scheduling. Preserve native provider day/hour ordering and allowed timezone values; no IANA timezone conversion is performed. Other native targeting/media rules remain provider validations.
Explicit mutation and recovery
Reads reject operationId. Before each mutation, generate a high-entropy UUIDv4 (or 16–128 ASCII letters/digits/underscore/hyphen ID) for that one intent. If supplying native idempotency_key, use exactly the same value. Results contain {result,operationId,status:"succeeded",replayed}. Never change the ID just because a request times out.
There is no automatic retry. Use ads_get_operation({connectionId,operationId}) to inspect safe status and retry guidance without sending a provider mutation. An explicit identical retry with the same grant, credential generation, account, payload and staged bytes is allowed only within the original 24 hours. Cached results can be replayed; IDs cannot be recycled after the window. OPERATION_PENDING means another call owns the intent; IDEMPOTENCY_MISMATCH means its payload changed; OPERATION_EXPIRED requires reconciliation. Transport/protocol/post-dispatch failures may return OPERATION_OUTCOME_UNKNOWN with the original operation ID. Reconcile the original outcome; a rejected retry does not prove that the first call failed. Revoked/rotated credentials cannot recover hidden cached results under a different binding.
Staged binary uploads
- Compute the unchanged file's byte count and lowercase SHA-256. Call
ads_prepare_file_uploadwithconnectionId, optionalaccountId,purpose(uploadAdPhoto,uploadAdVideooruploadWebsitePhoto),mimeType,byteCount, andsha256. - PUT exact bytes to the returned fixed-origin
url, withAuthorization: Bearer <uploadToken>and returnedcontentType. The opaque credential authorizes only this upload, with no GET, list or MCP access. Do not send the provider key. - After a successful PUT, call the corresponding canonical upload tool with
params.file:{uploadId}and one stableoperationId. Its native result supplies the photo/video ID for subsequent ad edits.
Ad photos allow JPEG/PNG up to 5 MiB, ad videos MP4 up to 20 MiB, and website photos JPEG/PNG up to 1 MiB. Preparation expires in 15 minutes; streams have 10-second idle and 30-second total deadlines. URLs, local paths, base64 and binary bodies in MCP JSON are rejected. An upload belongs to one operation ID; unknown outcomes retain its original bytes through recovery, while successful uploads release bytes and retain replay metadata. A second operation cannot consume the same upload.
Bounds and verification
Ads MCP JSON is bounded to 2 MiB; native provider responses to 8 MiB; complete MCP responses to 32 MiB. Account discovery and owner grant management are paged. GET /v1/mcp-grants/page?offset=0&limit=20 returns {grants,nextOffset}; each complete page is at most 4 MiB and may contain fewer rows than requested. Follow advancing offsets until null. Extension automatic processing is capped at eight pages and 8 MiB of retained safe metadata; incomplete or malformed access displays unavailable rather than an inferred denial. Manage the complete grant list in Telemetrio.
The internal /v1/mcp credential stays between the issuer and Ads service. It is never a browser input or chatbot secret. Ordinary verification uses synthetic provider fixtures/read-only live checks. All 45 methods are covered synthetically; this is not evidence of live writes, hosted rollout, or provider acceptance of every creative. Live provider mutations require explicit authorization for concrete test accounts/actions.