Adsly.pro
Documentation pages All documentation

Campaigns — list and read

The campaign object, its statuses, GET /v1/campaigns with filters by status, bot, website domain and ad type, GET /v1/campaigns/{ad_id} for one campaign with its targeting and schedule.

View as Markdown

A campaign is one Telegram ad. It is identified by (account_id, ad_id) — Telegram reuses ad_id across cabinets, so ad_id alone is not unique.

The campaign object

GET /v1/campaigns/{ad_id} returns:

{
  "ad_id": 90412,
  "account_id": 53,
  "title": "API test",
  "text": "Join the channel for daily market notes",
  "status": "Active",
  "active": true,
  "promote_url": "https://t.me/yourchannel",
  "tme_path": "yourchannel",
  "target_type": "channels",
  "targets": ["durov"],
  "cpm": "1.50",
  "budget": "3.54100",
  "spent": "1.45900",
  "daily_budget": null,
  "views": 1043,
  "opens": 0,
  "clicks": 12,
  "actions": 4,
  "ctr": "1.15",
  "cvr": "33.33",
  "cpc": "0.1215833333",
  "cpa": "0.3647500000",
  "views_per_user": 1,
  "schedule": {
    "days": { "mon": [9, 10, 11, 12, 13, 14, 15, 16, 17], "tue": [9, 10, 11, 12, 13, 14, 15, 16, 17],
              "wed": [9, 10, 11, 12, 13, 14, 15, 16, 17], "thu": [9, 10, 11, 12, 13, 14, 15, 16, 17],
              "fri": [9, 10, 11, 12, 13, 14, 15, 16, 17], "sat": [], "sun": [] },
    "timezone": "+03:00"
  },
  "has_media": false,
  "media_type": null,
  "button": null,
  "website_name": null,
  "group_id": 7,
  "auto_cpm_enabled": false,
  "date": "1791364800",
  "synced_at": "2026-10-08T10:29:41.000Z",
  "status_changed_at": "2026-10-08T10:31:07.112Z"
}
FieldMeaning
titleYour internal name for the ad.
textThe ad text people see.
statusWhat Telegram is doing with the ad — see Statuses.
activeWhat you asked for: true = should run. A campaign with active: true and status Stopped resumes as soon as it has budget again.
promote_url / tme_pathWhat the ad leads to: a website URL, or a t.me/<tme_path> link (channel, bot, mini-app, post).
target_typechannels, bots, search or users — see Create campaigns.
targetsUsernames the ad targets (channels or bots), when known.
cpmBid per 1,000 views, in the cabinet’s currency.
budgetMoney left on the campaign. budget + spent is everything it was given.
spentMoney spent so far.
daily_budgetDaily spending cap, if one is set.
views, clicks, actions, opensLifetime counters. actions are platform actions (joins, bot starts) — not your conversions; for those see Conversions.
ctr, cvrPercentages: "1.15" means 1.15 %.
cpc, cpaCost per click and per action.
views_per_userHow many times one person can see the ad (1–4).
scheduleWeekdays and hours the ad is shown, or null — it runs around the clock. See Schedule.
group_idThe campaign’s group in the panel, if any.
auto_cpm_enabledAdsly’s Auto CPM manages the bid.
dateWhen the ad was created: unix seconds, as a string.
status_changed_atLast status change. Not touched by stats updates — good for “what changed since”.
synced_atWhen the ad’s own settings — schedule, text, views_per_user, targeting — were last read from Telegram. See Freshness.

Money fields are decimal strings (cpm, budget, spent, ctr, cvr, cpc, cpa) so decimals stay exact. Counters (views, clicks, actions, opens) are numbers. All money is in the cabinet’s currency (see Cabinets).

Statuses

StatusMeaningWhat you can do
ActiveRunning.Pause, change bid, add budget.
In ReviewWaiting for Telegram’s review; not shown yet.Wait — a webhook tells you when it changes.
DeclinedTelegram rejected the ad.Edit the text or link (resubmits), or create a new one.
On HoldSwitched off — by you or an automation rule.Resume.
StoppedBudget used up.Add budget; it runs again if active is true.
PausedPaused by Telegram for the whole cabinet (rare).Contact @adsly_pro.
DeletedRemoved. Kept in history, hidden from lists.—

GET /v1/campaigns

Campaigns of every cabinet the key reaches.

curl -s "https://app.adsly.pro/api/v1/campaigns?account_id=53&status=Active,On%20Hold&limit=100&cursor=" \
  -H "X-API-Key: $ADSLY_API_KEY"
ParameterDefaultMeaning
account_id—Only this cabinet. (accountId also works.)
statusall but DeletedOne status or several, comma-separated.
title—Title contains this text.
bot_username—Ads of one bot or channel: matches the username in tme_path, case-insensitive, no @. foo does not match foobar.
promote_domain—Website ads whose link is on this host. Accepts example.com or a full URL; www., scheme, path and port are ignored.
promote_domain_modeexactsuffix also matches subdomains (x.example.com).
type—bot (bots and mini-apps), channel (channels, groups, posts) or site (external websites).
limit1001–500.
cursor—Pagination — see Pagination. Recommended.
offset, sortBy, sortOrder—Offset pagination (≤ 500 per cabinet).

Filters combine with AND. An unknown bot or domain returns an empty list, not an error.

{
  "success": true,
  "data": [
    { "ad_id": 90412, "account_id": 53, "title": "API test", "text": "…", "status": "Active",
      "tme_path": "yourchannel", "promote_url": null, "views": 1043, "opens": 0, "clicks": 12,
      "actions": 4, "spent": "1.45900", "budget": "3.54100", "cpm": "1.50", "cpc": "0.12",
      "cpa": "0.36", "ctr": "1.15", "cvr": "33.33", "date": "1791364800", "group_id": 7,
      "status_changed_at": "2026-10-08T10:31:07.112Z" }
  ],
  "meta": { "limit": 100, "cursor": null, "next_cursor": null, "hasMore": false }
}

Get one campaign

GET /v1/campaigns/{ad_id} — the full object above, including targeting, creative fields and schedule (the list endpoint leaves those out to stay fast). Deleted campaigns are returned too, with status: "Deleted".

curl -s "https://app.adsly.pro/api/v1/campaigns/90412?account_id=53" -H "X-API-Key: $ADSLY_API_KEY"

account_id is needed only when the same ad_id exists in several of your cabinets (400 ACCOUNT_ID_REQUIRED tells you).

Freshness

Counters and status are refreshed for every campaign every hour. The ad’s own settings — schedule, text, views_per_user, targeting — come from reading the ad itself, so:

  • GET /v1/campaigns/{ad_id} re-reads the ad from Telegram when our copy is older than 5 minutes, before answering. A change someone made directly in Telegram’s ad interface shows up here within that window.
  • Running campaigns (Active, In Review, On Hold) are also re-read in the background about every 3 hours.
  • Changes made through Adsly — the panel or this API — are in the copy at once.

If Telegram doesn’t answer in time, you get the stored copy; synced_at tells you how old it is.

GET /v1/campaigns/{ad_id}/history

One campaign’s totals over a period — a single aggregate, not hourly points.

curl -s "https://app.adsly.pro/api/v1/campaigns/90412/history?account_id=53&period=7d" -H "X-API-Key: $ADSLY_API_KEY"
{ "success": true,
  "data": { "views": 640, "clicks": 7, "spent": 0.96, "ctr": 1.09, "cpm": 1.5, "cpa": 0.32 },
  "meta": { "adId": 90412, "accountId": 53, "period": "7d" } }

period: 24h (default), 7d, 30d or custom with startDate / endDate (YYYY-MM-DD, UTC) and optional startHour / endHour (0–23). No data for the period → 404 NOT_FOUND.

Keeping a local copy in sync

  1. Page through GET /v1/campaigns?cursor= and upsert by (account_id, ad_id).
  2. Subscribe to webhooks for status changes and hourly stats instead of polling every minute.
  3. Re-sync fully once a day to catch anything a webhook missed.

Updated 2026-10-08

Discuss your project