Adsly.pro
Documentation pages All documentation

Create campaigns

POST /v1/campaigns — create one or up to 100 Telegram ads in a call, targeting channels, bots, search queries or audiences by country, language and topic; upload images and video with POST /v1/media.

View as Markdown

POST /v1/campaigns creates campaigns in one cabinet. It needs a key with Manage campaigns, an Idempotency-Key, and returns 202 with a task — the campaigns appear when the task completes.

A first example

curl -s -X POST https://app.adsly.pro/api/v1/campaigns \
  -H "X-API-Key: $ADSLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "account_id": 53,
    "title": "Crypto channels — notes",
    "text": "Daily market notes in 3 minutes. No noise.",
    "promote_url": "https://t.me/yourchannel",
    "cpm": 1.5,
    "budget": 20,
    "target_type": "channels",
    "channels": ["@durov", "t.me/telegram"]
  }'
{ "success": true, "data": { "id": 81234, "type": "create", "status": "pending", "account_id": 53, "total": 1, "ad_ids": [] } }

Many at once

Put the campaigns in campaigns (up to 100). account_id and the group fields stay at the top level and apply to all of them.

{
  "account_id": 53,
  "new_group_name": "October test",
  "campaigns": [
    { "title": "A", "text": "Variant A", "promote_url": "https://t.me/yourchannel", "cpm": 1.5, "budget": 10,
      "target_type": "channels", "channels": ["@durov"] },
    { "title": "B", "text": "Variant B", "promote_url": "https://t.me/yourchannel", "cpm": 1.5, "budget": 10,
      "target_type": "channels", "channels": ["@telegram"] }
  ]
}

Campaigns are created one after another. If the first one fails, the task stops — fix the input rather than repeat the same error 100 times. Each failure is listed in the task’s errors with its index in your array.

Fields

FieldRequiredMeaning
titleyesInternal name, shown in the panel.
textyesAd text people see. Telegram’s own length and content rules apply — a refusal comes back in the task’s errors.
promote_urlyesWhat the ad opens: https://t.me/channel, t.me/bot?start=ref, @channel or a website URL.
cpmyesBid per 1,000 views in the cabinet’s currency, greater than 0. Too low for the targeting → Telegram’s minimum comes back in the error.
budgetyesMoney moved from the cabinet balance to the campaign: 0, or at least the cabinet’s min_budget (Cabinets). With 0 the ad is created but can’t run until you add budget.
target_typeyeschannels, bots, search or users — see below.
activenofalse creates it switched off. Default true.
daily_budgetnoDaily spending cap.
views_per_usernoHow many times one person can see the ad, 1–4.
medianoImage or video token from POST /v1/media.
picturenotrue shows the promoted channel’s avatar in the ad.
buttonnoButton under the ad: subscribe, view, read, learn_more, download, open, sign_up, buy, order, play, try, leave_request. Only where the cabinet’s features.ad_button is true.
website_namenoBrand name shown above a website ad.
schedulenoShow the ad only on chosen weekdays and hours, e.g. weekdays 9:00–18:00. Format: Schedule. Without it the ad runs around the clock.

Top level only: account_id (needed when the key reaches several cabinets), group_id (an existing group) or new_group_name (creates the group, or reuses one with that name).

Unknown fields are refused with 400 VALIDATION_ERROR and the field name in param — a typo never silently drops a setting.

Targeting

channels — show the ad in specific channels

{ "target_type": "channels", "channels": ["@durov", "t.me/telegram"],
  "languages": ["en"], "topics": [7, 26], "exclude_topics": [2], "add_similar_channels": true }
FieldMeaning
channels1–100 public channels: @name, name or t.me/name. Required.
languages, topics, exclude_topicsNarrow by channel language and topic (codes).
add_similar_channelsAlso add channels similar to these.

bots — show the ad in bots

{ "target_type": "bots", "bots": ["@somebot"] }

bots: 1–100 public bots. Required.

search — show the ad for Telegram search queries

{ "target_type": "search", "search_keywords": ["crypto wallet", "bitcoin"] }

search_keywords: 1–100 phrases, up to 64 characters each. Required.

users — show the ad to an audience

{ "target_type": "users", "countries": ["DE", "AT"], "languages": ["de"],
  "topics": [26], "exclude_topics": [2], "audience_channels": ["@somechannel"] }
FieldMeaning
countriesISO country codes.
languagesLanguage codes.
topics, exclude_topicsInterests by topic id.
audience_channelsPeople who read these channels.

At least one of these is required. Codes: Targeting codes.

Channels, bots and keywords are resolved to Telegram’s own ids when the task runs. Ones Telegram can’t find are skipped; if none are found, that campaign fails — No targets found: … for channels and bots, No valid search queries found for keywords — and the task’s errors says so.

After creating

  1. Poll GET /v1/tasks/{id} until completed. ad_ids holds the new campaigns.
  2. Telegram reviews each new ad: it starts In Review, then becomes Active (or Declined). A webhook tells you when.
  3. Change, fund or pause them with Manage campaigns.

Upload media

POST /v1/media uploads an image or video into a cabinet and returns a media token for POST /v1/campaigns, PATCH and copy. The token belongs to that cabinet — upload into the cabinet you’ll create in.

curl -s -X POST "https://app.adsly.pro/api/v1/media?account_id=53" \
  -H "X-API-Key: $ADSLY_API_KEY" \
  -F "file=@banner.jpg"
{ "success": true, "data": { "media": "BQACAgIAAx0…", "account_id": 53 } }
  • JPG, PNG, GIF, WEBP or MP4, up to 10 MB, sent as multipart/form-data in the field file.
  • Some cabinets accept only 16:9 images at least 640 px wide; if a file doesn’t fit, Telegram’s reason comes back in error.

Errors

CodeWhen
VALIDATION_ERRORA field is missing, unknown, of the wrong type, or doesn’t belong to this target_type — param says which.
IDEMPOTENCY_KEY_REQUIREDNo Idempotency-Key.
ACCOUNT_ID_REQUIRED / ACCOUNT_NOT_FOUNDSay which cabinet / that cabinet isn’t reachable.
VIEW_ONLY_ACCESSYou have Viewer access to this cabinet.
QUEUE_FULL5 creates already queued in this cabinet.
CABINET_LOCKED, SUBSCRIPTION_REQUIREDThe cabinet can’t take manual changes right now.

Individual campaign failures (Telegram refused a text, a bid, a link) don’t fail the request — they appear in the task’s errors.

Updated 2026-10-08

Discuss your project