KLO Public APIKLO Public API
REST-интерфейс для управления, анализа и мониторинга вашей клоаки из собственных инструментов - дашбордов, скриптов, ботов - без входа в кабинет. A REST interface to manage, analyze and monitor your cloaking setup from your own tools - dashboards, scripts, bots - without logging into the cabinet.
ОбзорOverview
Чтение: список кампаний и их настройки, счётчики трафика (белая страница / оффер), графики по дням и часам, история кликов, живая лента решений, домены. Запись: создание, изменение, включение/отключение и удаление кампаний, а также готовый файл интеграции. Всё в пределах вашей подписки и тарифа - от лица вашего аккаунта, без входа в кабинет. Read: list campaigns and their settings, traffic counters (white page / offer), day/hour charts, click history, a live decision feed, and domains. Write: create, update, enable/disable and delete campaigns, plus the ready-to-deploy integration file. Everything within your subscription and plan - on behalf of your account, without logging into the cabinet.
{"data": …, "meta": …}, где meta может отсутствовать. Ошибка: {"error": {"code": …, "message": …}}. Скачивание интеграции возвращает файл. Пагинация есть у кампаний и истории; домены возвращаются одним списком. Новые совместимые поля не меняют адрес API.
Response format. Success: {"data": …, "meta": …}, with optional meta. Error: {"error": {"code": …, "message": …}}. Integration downloads return a file. Campaigns and history are paginated; domains return one list. Compatible new fields do not change the API URL.
Первый запрос за три шагаYour first request in three steps
- В кабинете, раздел «API», создайте токен с правом чтения. Для управления кампаниями дополнительно включите запись.Create a read token in Cabinet → API. Enable write access only if your tool needs to manage campaigns.
- На своём сервере сохраните токен в переменную окружения
KLO_API_TOKENи выполните пример ниже. Во всех остальных примерах заменяйтеklo_live_…на свой токен.On your server, store the token in theKLO_API_TOKENenvironment variable and run the example below. Replaceklo_live_…in other examples with your own token. - Проверьте HTTP
200, свой тариф иdata.limits. Далее запросите/campaignsили/stats. Примеры cURL рассчитаны на Bash; в PowerShell используйтеcurl.exeи синтаксис своей оболочки.Check for HTTP200, your plan anddata.limits. Then request/campaignsor/stats. cURL examples use Bash syntax; in PowerShell usecurl.exeand your shell's quoting syntax.
curl --silent --show-error --fail-with-body --max-time 30 \
-H "Authorization: Bearer $KLO_API_TOKEN" \
https://cabinet.klo-boostclicks.online/api/v1/account/check относятся к другому протоколу; Bearer-токен его не заменяет.This is the account management and analytics API. To check visitors, install an integration from the cabinet. Loader secrets, HMAC signatures and the /check route use a separate protocol; a Bearer token does not replace them.АутентификацияAuthentication
API использует отдельные Bearer-токены вида klo_live_…. Это не тот же секрет, что вшит в лоадер, - токены выпускаются и отзываются отдельно, специально для API.
The API uses dedicated Bearer tokens shaped like klo_live_…. These are not the loader secret - API tokens are issued and revoked separately, exclusively for the API.
Как получить токенGetting a token
- Откройте кабинет → вкладка «API».Open the cabinet → the “API” tab.
- Нажмите «Создать токен», задайте название.Click “Create token” and give it a name.
- Скопируйте токен в настройки своего приложения. Новые токены хранятся зашифрованными; в кабинете их можно повторно показать и скопировать. У старого токена может быть доступен только префикс; тогда создайте новый.Copy the token to your application settings. New tokens are stored encrypted and can be revealed and copied again in the cabinet. A legacy token may only expose its prefix; create a replacement in that case.
- Отзывайте ненужные токены там же. После отзыва запросы API с этим токеном отклоняются. Существующие файлы фильтрации используют отдельный секрет и продолжают работу.Revoke unused tokens there. Revoked tokens can no longer authenticate API requests. Existing filtering files use a separate secret and continue working.
Передавайте токен в заголовке каждого запроса:Send the token in the header of every request:
Authorization: Bearer klo_live_1a2b3c4d5e6f7890abcd1234ef567890abcd1234Права токена (scopes)Token scopes
У токена есть уровень доступа. При создании в кабинете выберите «Доступ на запись», если токену нужны операции изменения; иначе токен будет только для чтения. A token carries an access level. When creating one in the cabinet, tick “write access” if the token needs to modify data; otherwise it is read-only.
| Scope | Что разрешеноAllows |
|---|---|
read | Все GET-эндпоинты (аккаунт, кампании, статистика, история, лента)All GET endpoints (account, campaigns, stats, history, feed) |
read + write | Дополнительно - создание, изменение, вкл/выкл и удаление кампаний (v1.1)Additionally - create, update, enable/disable and delete campaigns (v1.1) |
403 insufficient_scope.A write request with a read-only token returns 403 insufficient_scope.Максимум 15 активных токенов на аккаунт. Вместо Authorization поддерживается X-Api-Key, но передавайте только один способ авторизации. Токен в URL не принимается. Для каждого приложения удобно создать отдельный токен с минимальными правами.Up to 15 active tokens per account. X-Api-Key is supported as an alternative to Authorization; use one authentication method per request. URL tokens are not accepted. Use a separate least-privilege token for each application.
Базовый URL и версииBase URL & versioning
https://cabinet.klo-boostclicks.online/api/v1
Все пути в этой документации относительны базового URL. Версия зафиксирована в пути (/api/v1). Ломающие изменения выйдут под новой версией; текущая продолжит работать в переходный период.
All paths in this documentation are relative to the base URL. The version is pinned in the path (/api/v1). Breaking changes will ship under a new version; the current one keeps working during the transition.
v1 в адресе - основная версия API. 1.4.0 - версия выпуска внутри v1: в нём добавлены новые возможности. Поэтому запрос аккаунта остаётся GET /api/v1/account; адреса /api/v1.4 и /api/v1.4.0 не используются. Текущая версия выпуска указана в info.version OpenAPI-спецификации.Why /api/v1 when the release is 1.4.0? v1 in the URL is the major API version. 1.4.0 is a release within v1 that adds capabilities. Account requests therefore remain GET /api/v1/account; /api/v1.4 and /api/v1.4.0 are not used. The current release is available as info.version in the OpenAPI specification.Лимиты запросовRate limits
Лимит зависит от тарифа и виден в limits.rate_limit_per_min ответа /account:The limit depends on your plan and is exposed as limits.rate_limit_per_min in /account:
| ТарифPlan | Запросов в минутуRequests per minute |
|---|---|
| START | 60 |
| PROFIT / TRIAL | 120 |
| DOMINATION | 300 |
Лимит считается отдельно для каждого токена на обслуживающем узле в минутном окне. Ответ после проверки токена содержит заголовки:The limit applies per token on each serving node in a minute window. Responses after token validation include:
| Header | ЗначениеMeaning |
|---|---|
X-RateLimit-Limit | Лимит в текущем окнеLimit for the current window |
X-RateLimit-Remaining | Сколько запросов осталосьRequests remaining |
X-RateLimit-Reset | Unix-время сброса окнаUnix time when the window resets |
При превышении вернётся 429 Too Many Requests с заголовком Retry-After (секунды до сброса). Реализуйте экспоненциальную паузу и повтор.Exceeding it returns 429 Too Many Requests with a Retry-After header (seconds until reset). Implement exponential backoff and retry.
Показатель использования токена в кабинете приблизительный: счётчики находятся в памяти узла, сбрасываются при его перезапуске, сутки считаются по UTC. Он не предназначен для сверки оплаченного трафика.Token usage shown in the cabinet is approximate: counters are node-local, reset after a restart and use UTC days. They are not a billing or traffic reconciliation ledger.
ОшибкиErrors
Ошибки возвращаются с соответствующим кодом HTTP и телом в едином формате:Errors are returned with the appropriate HTTP status and a consistent body:
{
"error": {
"code": "invalid_token",
"message": "API token is invalid or has been revoked."
}
}| code | HTTP | ПричинаReason |
|---|---|---|
missing_token | 401 | Нет заголовка AuthorizationNo Authorization header |
invalid_token | 401 | Токен неверный или отозванToken invalid or revoked |
subscription_inactive | 403 | Подписка не активнаSubscription not active |
subscription_expired | 403 | Подписка истеклаSubscription expired |
insufficient_scope | 403 | Токен без права записи (v1.1)Token lacks write scope (v1.1) |
plan_upgrade_required | 403 | Тип интеграции недоступен на тарифеIntegration type not allowed on your plan |
validation_error | 422 | Ошибка в полях запроса (см. details)Invalid request fields (see details) |
unsupported_integration | 422 | Для этого типа интеграции нет скачиваемого файла (Cloudflare)This integration has no downloadable file (Cloudflare) |
idempotency_conflict | 409 | Тот же Idempotency-Key использован с другим телом запросаThe same Idempotency-Key was reused with a different request body |
not_found | 404 | Ресурс не найденResource not found |
rate_limit_exceeded | 429 | Превышен лимит запросовRate limit exceeded |
upstream_error | 502 | Не удалось связаться с узлом записиThe write node could not be reached |
write_unavailable | 503 | Запись временно недоступна; учитывайте Retry-AfterWrites are temporarily unavailable; honor Retry-After |
service_unavailable | 503 | Хранилище авторизации недоступно; повторите позжеAuthorization storage is unavailable; retry later |
write_failed | 503 | Не удалось подтвердить сохранение; проверьте результат перед повторомPersistence could not be confirmed; check the result before retrying |
payload_too_large | 413 | Тело запроса больше 64 КиБThe request body exceeds 64 KiB |
unsupported_media_type | 415 | Указан неподдерживаемый Content-TypeThe supplied Content-Type is unsupported |
401 проверьте токен, при 403 подписку и права, при 422 поля из error.details. Повторяйте 429, временные 5xx и сетевые сбои с паузой. Для создания кампании при повторе сохраняйте исходные тело и Idempotency-Key. При сбое прокси тело ответа может оказаться HTML; сначала проверяйте HTTP-статус и Content-Type.For 401 check the token; for 403 check subscription and scopes; for 422 inspect error.details. Retry 429, temporary 5xx and network failures with backoff. For campaign creation retain the original body and Idempotency-Key on retries. A proxy failure may return HTML; inspect the HTTP status and Content-Type before parsing JSON.ПагинацияPagination
Списки листаются курсором. Параметр limit задаёт размер страницы; в блоке meta приходит next_cursor - передайте его в параметр cursor следующего запроса. Если has_next=false, страниц больше нет.
Collections use cursor pagination. The limit parameter sets the page size; the meta block returns next_cursor - pass it as the cursor parameter of the next request. When has_next=false, there are no more pages.
Курсор непрозрачный: не собирайте и не изменяйте его вручную. Для следующей страницы сохраняйте прежние фильтры и limit. При смене фильтра начинайте без курсора. Изменения данных во время обхода могут сдвигать страницы; сверку проводите за завершённый период, устраняя повторы по event_id.Treat cursors as opaque: do not construct or edit them. Keep the same filters and limit for subsequent pages; restart without a cursor after changing filters. Concurrent data changes may shift pages. Reconcile a completed period and deduplicate by event_id.
{
"data": [ /* … */ ],
"meta": {
"count": 20,
"total": 57,
"has_next": true,
"next_cursor": "eyJvIjoyMH0"
}
}Время и полнота данныхTime and data completeness
ts содержит Unix-время в секундах, time, created_at, updated_at и expires_at используют ISO-8601 в UTC. Неизвестная дата может быть null. Даты фильтров и группировка по суткам относятся к часовому поясу статистики кабинета. В графиках используйте meta.timezone, а не часовой пояс браузера.ts is Unix time in seconds; time, created_at, updated_at and expires_at use ISO-8601 UTC. An unknown date may be null. Date filters and daily aggregates use the cabinet statistics timezone. For charts use meta.timezone, not the browser timezone.
История доступна за 7 дней на START и за 45 дней на остальных планах. Точные ограничения возвращает /account. Даты передавайте как YYYY-MM-DD; обе границы включены. Проверяйте фактические meta.from и meta.to: доступный период может быть уже запрошенного.History is available for 7 days on START and 45 days on other plans; /account returns the limits. Use YYYY-MM-DD dates; both boundaries are inclusive. Check effective meta.from and meta.to, as the available period may be narrower than requested.
Аналитика обновляется с задержкой. Проверяйте meta.source и meta.partial, а у счётчиков в объектах кампаний stats_meta. source=clickhouse означает основную аналитику, local_jsonl локальный резерв; partial=true предупреждает о неполной выборке. Не заменяйте последний полный отчёт нулями из неполного ответа: повторите запрос позже.Analytics updates are delayed. Check meta.source and meta.partial, or stats_meta for counters inside campaign objects. source=clickhouse identifies primary analytics; local_jsonl is a local fallback; partial=true warns of incomplete data. Keep the last complete report instead of replacing it with zeros from a partial response, and retry later.
offer и white описывают принятое решение и выданную страницу. Это не подтверждение покупки, просмотра страницы или окончательная оценка человека/бота. unique_ips считает разные IP, а не людей: за одним IP могут быть тысячи посетителей.offer and white describe a decision and the selected page. They do not confirm a purchase, page view or definitive human/bot classification. unique_ips counts IP addresses, not people: one IP may represent thousands of visitors.АккаунтAccount
curl https://cabinet.klo-boostclicks.online/api/v1/account \
-H "Authorization: Bearer klo_live_…"ОтветResponse
{
"data": {
"key_id": "key-20260101120000-a1b2c3d4",
"label": "My account",
"plan": "profit",
"plan_restricted": false,
"active": true,
"expires_at": "2026-09-13T10:00:00+00:00",
"created_at": "2026-07-13T14:40:28+00:00",
"domains": ["example.com"],
"limits": {
"rate_limit_per_min": 120,
"history_window_days": 45
}
}
}Сводная статистикаAccount statistics
today относится к текущим суткам в часовом поясе кабинета. total охватывает сохранённую историю аналитики, а не неограниченный срок жизни аккаунта. Итоги включают трафик без кампании и удалённых кампаний, поэтому могут превышать сумму текущего списка кампаний. Локальный резерв ограничен 45 днями и отмечается partial=true.today uses the cabinet's current calendar day. total covers retained analytics history, not an unlimited account lifetime. Totals include traffic without a campaign and traffic from deleted campaigns, so they may exceed the sum of current campaigns. Local fallback covers up to 45 days and is marked partial=true.
curl https://cabinet.klo-boostclicks.online/api/v1/stats \
-H "Authorization: Bearer klo_live_…"ОтветResponse
{
"data": {
"totals": {
"today": { "offer": 340, "white": 1290 },
"total": { "offer": 15803, "white": 64200 }
},
"campaigns_count": 3,
"campaigns": [
{
"id": "camp-1a2b3c4d5e6f",
"name": "Demo LP",
"is_active": true,
"today": { "offer": 120, "white": 410 },
"total": { "offer": 5100, "white": 22010 }
}
]
}
}Список кампанийList campaigns
Параметры запросаQuery parameters
| Param | Type | ОписаниеDescription |
|---|---|---|
limitopt | int | Размер страницы, 1–100 (по умолчанию 20)Page size, 1–100 (default 20) |
cursoropt | string | Курсор следующей страницы из meta.next_cursorNext-page cursor from meta.next_cursor |
curl "https://cabinet.klo-boostclicks.online/api/v1/campaigns?limit=20" \
-H "Authorization: Bearer klo_live_…"ОтветResponse
{
"data": [
{
"id": "camp-1a2b3c4d5e6f",
"name": "Demo LP",
"is_active": true,
"integration_type": "php_direct",
"white_url": "main.html",
"offer_url": "d/index.php",
"redirect_method": "include",
"created_at": "2026-07-13T14:40:28+00:00",
"updated_at": "2026-08-01T09:12:00+00:00",
"stats": {
"today": { "offer": 120, "white": 410 },
"total": { "offer": 5100, "white": 22010 }
}
}
],
"meta": { "count": 1, "total": 1, "has_next": false }
}Одна кампанияGet a campaign
curl https://cabinet.klo-boostclicks.online/api/v1/campaigns/camp-1a2b3c4d5e6f \
-H "Authorization: Bearer klo_live_…"ОтветResponse
{
"data": {
"id": "camp-1a2b3c4d5e6f",
"name": "Demo LP",
"is_active": true,
"integration_type": "php_direct",
"white_url": "main.html",
"offer_url": "d/index.php",
"targeting": {
"countries": ["LT"],
"devices": ["mobile"],
"operating_systems": [],
"browsers": [],
"browser_languages": ["lt"],
"block_empty_language": true
},
"allowed_ips_count": 0,
"blocked_ips_count": 4,
"delayed_start_clicks": 5,
"stats": { "today": { "offer": 120, "white": 410 }, "total": { "offer": 5100, "white": 22010 } }
}
}404 not_found.If the campaign does not belong to your token - 404 not_found.Статистика кампанииCampaign statistics
{
"data": {
"campaign_id": "camp-1a2b3c4d5e6f",
"today": { "offer": 120, "white": 410 },
"total": { "offer": 5100, "white": 22010 }
}
}История кликовClick history
Параметры запросаQuery parameters
| Param | Type | ОписаниеDescription |
|---|---|---|
fromopt | date | С даты, YYYY-MM-DDFrom date, YYYY-MM-DD |
toopt | date | По дату, YYYY-MM-DDTo date, YYYY-MM-DD |
actionopt | string | offer · white |
siteopt | string | ДоменDomain |
campaign_idopt | string | Идентификатор своей кампанииYour campaign identifier |
reasonopt | string | Фильтр по причине решенияFilter by decision reason |
qopt | string | Полнотекстовый поиск (IP, гео, причина…)Full-text search (IP, geo, reason…) |
limitopt | int | 10–200 (по умолчанию 50)10–200 (default 50) |
cursoropt | string | Курсор следующей страницыNext-page cursor |
curl "https://cabinet.klo-boostclicks.online/api/v1/history?action=offer&limit=50" \
-H "Authorization: Bearer klo_live_…"ОтветResponse
{
"data": [
{
"event_id": "0123456789abcdef0123456789abcdef",
"ts": 1787401200,
"time": "2026-08-22T12:20:00+00:00",
"action": "offer",
"reason": "targeting_match",
"ip": "5.20.10.4",
"geo": "LT",
"site": "example.com",
"campaign_id": "camp-1a2b3c4d5e6f",
"browser": "Chrome",
"device": "mobile",
"query": "gclid=abc&buyer=demo"
}
],
"meta": { "count": 50, "total": 1240, "page": 1, "pages": 25, "has_next": true, "next_cursor": "eyJwIjoyfQ" }
}Живая лентаRealtime feed
after = meta.cursor_ts предыдущего ответа.The latest decisions for real-time monitoring. Poll at an interval, passing after = the previous response’s meta.cursor_ts.Параметры запросаQuery parameters
| Param | Type | ОписаниеDescription |
|---|---|---|
afteropt | int | Unix-время в секундах; передайте предыдущий meta.cursor_ts. Сервер повторно читает 180 секунд перед этой отметкой.Unix time in seconds; pass the previous meta.cursor_ts. The server rereads 180 seconds before this timestamp. |
limitopt | int | 1–200 (по умолчанию 50)1–200 (default 50) |
curl "https://cabinet.klo-boostclicks.online/api/v1/realtime?after=1787401100" \
-H "Authorization: Bearer klo_live_…"ОтветResponse
{
"data": [ /* строки как в /history */ ],
"meta": { "count": 7, "cursor_ts": 1787401242 }
}event_id и пропускайте уже полученные. В новых событиях это 32 шестнадцатеричных символа; для старых записей в ленте возможен непрозрачный совместимый идентификатор, а в истории пустая строка. Не разбирайте формат ID. Сочетание ts + ip + campaign_id не уникально и может склеить разных посетителей.Polling every 5-10 seconds is usually sufficient. Repeats are expected: remember recent nonempty event_id values and skip those already received. New events use 32 hexadecimal characters; legacy feed events may have an opaque compatibility ID, while history may return an empty string. Do not parse IDs. ts + ip + campaign_id is not unique and may merge different visitors.meta.limit_hit=true означает, что ответ достиг лимита; это сигнал возможного усечения, а не точное число оставшихся событий.meta.limit_hit=true means the response reached its limit: it warns of possible truncation without counting remaining events.
limit, длительном перерыве или большой задержке аналитики часть событий может не попасть в ленту. Не рассчитывайте по ней итоговую статистику и оплату; для сверки используйте историю, агрегаты и экспорт кабинета за завершённый период.This is a monitoring feed, not guaranteed delivery of every event. Bursts above limit, long polling gaps or substantial analytics delays may omit events. Do not calculate final statistics or billing from this feed; reconcile history, aggregates and cabinet exports for a completed period.v1.2 Клики во времениClicks over time
/campaigns/{id}/timeseries с теми же параметрами.Chart-ready series: clicks bucketed by day or hour. For a single campaign use /campaigns/{id}/timeseries with the same parameters.Параметры запросаQuery parameters
| Param | Type | ОписаниеDescription |
|---|---|---|
granularityopt | string | day (по умолчанию)(default) · hour |
from, toopt | date | Период YYYY-MM-DD. По умолчанию: 30 дней (day) или текущие сутки (hour)Range YYYY-MM-DD. Defaults: last 30 days (day) or today (hour) |
siteopt | string | Только по одному доменуRestrict to a single domain |
day ограничено тарифом: 7 дней на START, 45 на остальных. hour возвращает до 7 дней. Слишком широкий период сужается; фактические границы находятся в meta. Некорректная дата или период целиком вне доступного окна возвращает 422.day is limited by plan: 7 days on START, 45 on other plans. hour covers up to 7 days. Wider requests are narrowed; meta contains the effective boundaries. Invalid dates or a period entirely outside the available window return 422.curl "https://cabinet.klo-boostclicks.online/api/v1/stats/timeseries?granularity=day&from=2026-08-01&to=2026-08-24" \
-H "Authorization: Bearer klo_live_…"ОтветResponse
{
"data": [
{ "bucket": "2026-08-22", "offer": 3, "white": 1543, "total": 1546, "unique_ips": 150 },
{ "bucket": "2026-08-23", "offer": 0, "white": 529, "total": 529, "unique_ips": 235 }
],
"meta": {
"granularity": "day", "from": "2026-08-01", "to": "2026-08-24",
"points": 2, "timezone": "Europe/Moscow",
"totals": { "offer": 3, "white": 2072, "total": 2075 },
"source": "clickhouse", "partial": false
}
}meta.timezone. Пустые интервалы не возвращаются - если нужен сплошной ряд, дополните нулями на стороне клиента.Buckets use the timezone from meta.timezone. Empty buckets are omitted - pad the series client-side if you need a continuous line.v1.2 ДоменыDomains
Оба метода доменов принимают необязательные from и to в формате YYYY-MM-DD, с теми же ограничениями, что дневные графики. Список включает привязанные домены, в том числе без трафика; пагинации нет. pass_rate находится в диапазоне 0-1; например, 0.4923 означает 49.23%.Both domain endpoints accept optional from and to dates in YYYY-MM-DD format, with the same limits as daily charts. The unpaginated list includes assigned domains even if they have no traffic. pass_rate ranges from 0 to 1; for example, 0.4923 means 49.23%.
{
"data": [
{ "host": "example.com",
"stats": { "total": 7211, "offer": 3550, "white": 3661, "unique_ips": 1204, "pass_rate": 0.4923 } }
],
"meta": { "count": 8, "from": "2026-07-26", "to": "2026-08-24" }
}{
"data": {
"host": "example.com",
"stats": { "total": 7211, "offer": 3550, "white": 3661, "unique_ips": 1204, "pass_rate": 0.4923 },
"days": [ { "date": "2026-08-23", "total": 812, "offer": 401, "white": 411 } ],
"top_white_reasons": [ { "reason": "hosting", "count": 2085 }, { "reason": "bot_ua", "count": 679 } ]
}
}404 not_found. По доменам доступна статистика - ровно то же, что показывает вкладка «Домены» в кабинете.A domain outside your account returns 404 not_found. Domains are analytics-only here - exactly what the cabinet Domains tab shows.v1.2 Файл интеграцииIntegration file
sdk успешный ответ является JSON, а не файлом: data={integration_type:"sdk",package:"@boostclicks/klo",token,campaign_id,endpoint}. Здесь token - публичный токен SDK, не management Bearer и не секрет PHP-лоадера.For sdk, success returns JSON instead of a file: data={integration_type:"sdk",package:"@boostclicks/klo",token,campaign_id,endpoint}. This token is the SDK public token, not a management Bearer token or PHP loader secret.Content-Disposition: attachment задаёт имя; Content-Type зависит от интеграции: HTML для JS-фильтра, обычно application/octet-stream для PHP. При ошибке возвращается JSON. Сначала проверяйте HTTP-статус. Файл содержит секрет ключа: храните его как пароль.A successful response contains a file. Content-Disposition: attachment provides the filename; Content-Type depends on the integration: HTML for the JS filter, usually application/octet-stream for PHP. Errors return JSON. Check the HTTP status first. The file embeds your key secret; protect it like a password.curl --fail --show-error -OJ https://cabinet.klo-boostclicks.online/api/v1/campaigns/camp-1a2b3c4d5e6f/integration \
-H "Authorization: Bearer klo_live_…"422 unsupported_integration.Cloudflare campaigns have no integration file: use the deployment API. Downloading returns 422 unsupported_integration.v1.1 Управление кампаниями (запись)Managing campaigns (write)
Операции записи требуют токен с правом write (см. Права токена). Ограничения по тарифу - те же, что в кабинете.
Write operations require a token with the write scope (see Token scopes). Plan limits are the same as in the cabinet.
php_direct,php_reverseиsdkдоступны на всех тарифах, включая START.php_direct,php_reverseandsdkare available on all plans, including START.javascript,keitaro,wordpress- тариф PROFIT и выше (иначе403 plan_upgrade_required).javascript,keitaro,wordpress- PROFIT plan or higher (else403 plan_upgrade_required).cloudflareтребует DOMINATION для создания, редактирования, включения, сохранения доступа и развёртывания. Отключение и удаление доступны на любом активном тарифе. API поддерживает создание, изменение, включение, отключение и удаление Cloudflare-кампаний. Чтение статуса своей кампании доступно и на младшем тарифе, чтобы увидетьdisabled_plan.cloudflarerequires DOMINATION for creation, editing, enabling, saving access and deployment. Disable and delete remain available with any active subscription. The API supports creating, updating, enabling, disabling and deleting Cloudflare campaigns. You can read your campaign status on a lower plan, includingdisabled_plan.
Допустимые значения таргетингаAllowed targeting values
Значения сверяются точно (регистр нормализуется); неизвестное → 422 validation_error. Пустой список = без ограничения.Values are matched exactly (case is normalized); unknown → 422 validation_error. Empty list = no restriction.
devices | Desktop, Mobile, Tablet |
operating_systems | Windows, macOS, Linux, iOS, Android, Chrome OS, Ubuntu, Fedora |
browsers | Chrome, Chromium, Firefox, Safari, Edge, Opera, Samsung Internet, UC Browser, Yandex Browser |
countries | ISO-3166 alpha-2, напр. LT, USISO-3166 alpha-2, e.g. LT, US |
browser_languages | код языка, напр. lt, enlanguage code, e.g. lt, en |
5xx сначала выясните результат операции через чтение; создание повторяйте с тем же Idempotency-Key.Use the documented base URL. After a successful write, another node may reflect the change with a delay. On 5xx, check the operation result by reading; retry creation with the same Idempotency-Key.Передавайте JSON-объект с Content-Type: application/json, не массив. Размер тела до 64 КиБ. Boolean-поля передавайте как true/false, списки как массивы строк. Вложенный объект unique_visit описан ниже. Доступны только перечисленные поля; dns_channel доступен только для чтения, собственные DNS-резолверы через API не задаются.Send a JSON object, not an array, with Content-Type: application/json. Maximum body size: 64 KiB. Send booleans as true/false and lists as string arrays. The nested unique_visit object is described below. Only listed fields are writable; dns_channel is read-only, and the API does not accept custom DNS resolvers.
Создать кампаниюCreate a campaign
name, white_url, offer_url.Creates a campaign. name, white_url, offer_url are required.Тело запроса (JSON)Request body (JSON)
| Field | Type | ОписаниеDescription |
|---|---|---|
namerequired | string | Непустое название, до 120 символовNonempty name, up to 120 characters |
white_urlrequired | string | Белая страница (URL или локальный путь)White page (URL or local path) |
offer_urlrequired | string | Оффер (URL или локальный путь)Offer (URL or local path) |
white_target_mode, offer_target_modeopt | string | url (по умолчанию) или local. Для локального файла (напр. main.html) укажите local явно - иначе безсхемное значение считается URL.url (default) or local. For a local file (e.g. main.html) pass local explicitly - otherwise a scheme-less value is treated as a URL. |
integration_typeopt | string | php_direct (default) · php_reverse · sdk · javascript · keitaro · wordpress · cloudflare |
redirect_methodopt | string | 302·301·proxy·meta_refresh·js_redirect·iframe·include |
white_methodopt | string | Метод показа white: значения как у redirect_method. include применяется к локальному файлу; для URL используется 302. Метод оффера по умолчанию 302.White page method: same values as redirect_method. include applies to local files; URLs use 302. The offer method defaults to 302. |
countries, devices, operating_systems, browsers, browser_languagesopt | string[] | Таргетинг (пустой = без ограничения)Targeting (empty = no restriction) |
block_empty_languageopt | bool | Блокировать пустой языкBlock empty language |
allowed_ips, blocked_ipsopt | string[] | Списки IPIP lists |
delayed_start_clicksopt | int | Прогрев: первые N кликов → whiteWarm-up: first N clicks → white |
utm_modeopt | string | "" без проверки, allow пропускать совпадение с шаблоном, deny отклонять совпадение"" disables matching; allow permits a pattern match; deny rejects a match |
utm_patternopt | string | Шаблон параметров запроса, до 500 символов; например ?buyer=demo&gclid={gclid}. Макрос соответствует любому значению.Query parameter pattern, up to 500 characters; for example ?buyer=demo&gclid={gclid}. A macro matches any value. |
is_activeopt | bool | Включена (по умолчанию true)Enabled (default true) |
unique_visitopt | object | enabled: bool; scope: domain / campaign / account; ttl_hours: 24 / 168 / 360 / 720; skip_mobile: bool. При PATCH включённой настройки пропущенные вложенные поля сохраняются. Отключение очищает настройку: ответ []. Последующее включение использует значения по умолчанию, если не передать новые: domain, 168, skip_mobile=true.enabled: bool; scope: domain / campaign / account; ttl_hours: 24 / 168 / 360 / 720; skip_mobile: bool. While enabled, PATCH preserves omitted nested fields. Disabling clears the setting and returns []. Re-enabling uses defaults unless supplied: domain, 168, skip_mobile=true. |
Для совместимости black_url и black_target_mode принимаются как имена offer_url и offer_target_mode, js как javascript. В новых запросах используйте основные имена. Пустой список таргетинга снимает соответствующее ограничение. Локальный файл относится к серверу клиента, где установлена интеграция.Compatibility aliases: black_url and black_target_mode mean offer_url and offer_target_mode; js means javascript. Prefer canonical names in new requests. An empty targeting list removes that restriction. Local files belong to the client server running the integration.
curl -X POST https://cabinet.klo-boostclicks.online/api/v1/campaigns \
-H "Authorization: Bearer klo_live_…" \
-H "Content-Type: application/json" \
-d '{
"name": "Demo LP",
"integration_type": "php_direct",
"white_url": "main.html",
"white_target_mode": "local",
"offer_url": "https://offer.example.com/lp",
"countries": ["LT"],
"devices": ["Mobile"]
}'v1.2 Защита от дублейDuplicate protection
При создании передавайте Idempotency-Key: уникальную строку из 8-128 символов A-Z a-z 0-9 . _ : -. Сохраните ключ и исходное тело для повторов после сбоя. В пределах 24 часов повтор в том же аккаунте вернёт ту же кампанию, HTTP 200 и meta.idempotent_replay=true. Первый успех возвращает 201. Другое тело с прежним ключом возвращает 409 idempotency_conflict. Для новой кампании создавайте новый ключ. Без заголовка защита от дублей отсутствует. Некорректный ключ возвращает 422.For creation send Idempotency-Key: a unique 8-128 character string using A-Z a-z 0-9 . _ : -. Retain it and the original body for retries after a failure. Within 24 hours, a retry in the same account returns the same campaign, HTTP 200 and meta.idempotent_replay=true. Initial success returns 201. A changed body with the same key returns 409 idempotency_conflict. Use a new key for a new campaign. Without the header duplicate protection is unavailable. An invalid key returns 422.
curl -X POST https://cabinet.klo-boostclicks.online/api/v1/campaigns \
-H "Authorization: Bearer klo_live_…" \
-H "Idempotency-Key: my-unique-key-42" \
-H "Content-Type: application/json" \
-d '{"name":"Demo LP","white_url":"https://example.com/white","offer_url":"https://example.com/offer","is_active":false}'ОтветResponse
{ "data": { "id": "camp-9f1c…", "name": "Demo LP", "is_active": true, /* … полный объект кампании … */ } }Изменить кампаниюUpdate a campaign
Это правило распространяется на вложенный unique_visit: {"unique_visit":{"ttl_hours":168}} меняет только срок, сохраняя enabled, scope и skip_mobile. Для Cloudflare изменение целей ставит асинхронное обновление в очередь и сохраняет cookies миграции. Явно переданный метод 302 сохраняется. Статус развёртывания проверяйте отдельно.This also applies to nested unique_visit: {"unique_visit":{"ttl_hours":168}} changes only the TTL, preserving enabled, scope and skip_mobile. For Cloudflare, target changes queue an asynchronous update and preserve migration cookies. An explicitly supplied 302 method is retained. Check deployment status separately.
409. Для смены типа создайте отдельную кампанию.PATCH cannot change a Cloudflare campaign to another integration type: it returns 409. Create a separate campaign to change the integration type.curl -X PATCH https://cabinet.klo-boostclicks.online/api/v1/campaigns/camp-9f1c… \
-H "Authorization: Bearer klo_live_…" \
-H "Content-Type: application/json" \
-d '{ "name": "Demo LP v2", "countries": ["LT","LV"] }'{ "data": { "id": "camp-9f1c…", "name": "Demo LP v2", /* … */ } }Включить / отключитьEnable / disable
/disable. Тело не нужно.Enables the campaign. Use /disable to turn it off. No body needed.curl -X POST https://cabinet.klo-boostclicks.online/api/v1/campaigns/camp-9f1c…/disable \
-H "Authorization: Bearer klo_live_…"{ "data": { "id": "camp-9f1c…", "is_active": false, /* … */ } }PATCH с телом {"is_active": false}.The same can be done via PATCH with body {"is_active": false}.Удалить кампаниюDelete a campaign
curl -X DELETE https://cabinet.klo-boostclicks.online/api/v1/campaigns/camp-9f1c… \
-H "Authorization: Bearer klo_live_…"{ "data": { "id": "camp-9f1c…", "deleted": true } }v1.4.0 Сохранённый доступ CloudflareSaved Cloudflare access
Эти маршруты управляют сохранённым доступом к существующему аккаунту Cloudflare. Они не создают аккаунт у Cloudflare. Доступ и кампании принадлежат текущему владельцу Bearer-токена; чужой идентификатор не даёт доступа.These routes manage saved access to an existing Cloudflare account. They do not create an account at Cloudflare. Saved access and campaigns belong to the Bearer token owner; another owner's identifier does not grant access.
read.Lists saved connections; requires the read scope.Каждая запись содержит только id, label, email, account_id и added_at. API не возвращает ключ Cloudflare.Each record contains only id, label, email, account_id and added_at. The API never returns the Cloudflare key.
write и тариф DOMINATION.Saves access. Requires the write scope and DOMINATION.| Field | Type | ОписаниеDescription |
|---|---|---|
emailrequired | string | Email аккаунта CloudflareCloudflare account email |
api_keyrequired | string | Cloudflare Global API Key. Передаётся только в теле запроса по HTTPS; API Token вместо Global API Key не подходит.Cloudflare Global API Key. Send it only in the HTTPS request body; an API Token cannot replace the Global API Key. |
account_idrequired | string | Идентификатор аккаунта Cloudflare: 32 hex-символаCloudflare account ID: 32 hexadecimal characters |
labelopt | string | Удобное название подключенияA label for the connection |
Ответ содержит те же безопасные метаданные, что GET. Используйте возвращённый id как credential_id при развёртывании.The response contains the same safe metadata as GET. Use its returned id as credential_id when deploying.
Зоны CloudflareCloudflare zones
read. {id} - ID сохранённого доступа, а не Cloudflare Account ID.Returns zones owned by the Cloudflare account behind the saved connection. Requires read. {id} is the saved access ID, not the Cloudflare Account ID.| Query | ОписаниеDescription |
|---|---|
domain | Необязательный фильтр домена, например example.comOptional domain filter, for example example.com |
page, per_page | Номер и размер страницы: page=1..10000, per_page=5..50 (по умолчанию 20). Это постраничная пагинация; не используйте cursor. Фактические параметры и итог страницы возвращаются в meta.Page number and size: page=1..10000, per_page=5..50 (default 20). This route uses page pagination, not cursor. Effective pagination parameters and totals are returned in meta. |
Каждая зона в data содержит id, domain, status и name_servers. При передаче zone_id в развёртывание API повторно проверяет принадлежность зоны сохранённому аккаунту и соответствие домена.Each zone in data contains id, domain, status and name_servers. Deployment rechecks that the supplied zone_id belongs to the saved account and matches the domain.
Статус Cloudflare-кампанииCloudflare campaign status
read и своя кампания. Чтение доступно после перехода на младший тариф, в том числе для статуса disabled_plan.Returns deployment status, configuration and queue information. Requires read and an owned campaign. Status remains readable after a plan downgrade, including disabled_plan.Поля data: campaign_id, status, is_active, domain, credential_id, zone_id, worker_name, route_id, deployed_at, queued, queue, error_code. queue равен null или содержит created_at, next_check_at, check_count. Завершение подтверждает status="deployed". При повторе с Idempotency-Key возвращается исходный ответ приёма; актуальное состояние всегда читайте через GET.The data fields are campaign_id, status, is_active, domain, credential_id, zone_id, worker_name, route_id, deployed_at, queued, queue, and error_code. queue is null or contains created_at, next_check_at, and check_count. Only status="deployed" confirms completion. Idempotency-Key replay returns the original acceptance; always GET the current state.
Все Cloudflare GET-запросы направляются на основной узел, чтобы состояние очереди и сохранённого доступа не зависело от задержки репликации. Ответы не содержат API-ключей или исходных диагностик Cloudflare.All Cloudflare GET routes use the primary node, so queue and saved-access state do not depend on replica lag. Responses contain no API keys or raw Cloudflare diagnostics.
202 опрашивайте этот маршрут с паузой; не отправляйте deploy на каждый опрос.A saved campaign and a completed deployment are separate events. After 202, poll this route with backoff; do not send deploy on every poll.domain - точное имя зоны Cloudflare (обычно корневой домен). Произвольный поддомен, URL с путём и wildcard не подходят. Отключение/удаление сначала сохраняет локальное состояние. Если удаление ресурсов на Cloudflare не подтверждено, API возвращает 503 cf_cleanup_failed; повторите тот же disable/delete. Для DELETE сохранена запись восстановления, поэтому повтор возможен после локального удаления кампании.domain must be the exact Cloudflare zone name, normally an apex domain. Arbitrary subdomains, URLs with paths, and wildcards are not accepted. Disable/delete first persists local state. If Cloudflare resource removal is unconfirmed, the API returns 503 cf_cleanup_failed; retry the same disable/delete. DELETE keeps a recovery record so it can be retried after local campaign removal.Развёртывание, повтор и проверка NSDeploy, retry and check nameservers
Все три POST-маршрута требуют scope write и DOMINATION. Существующий фоновый обработчик выполняет развёртывание асинхронно. Запрос API не ждёт установки Worker.All three POST routes require write and DOMINATION. The existing background processor deploys asynchronously. The API request does not wait for Worker installation.
| Field | Type | ОписаниеDescription |
|---|---|---|
credential_idrequired | string | ID своего сохранённого доступа из /cloudflare/accountsYour saved access ID from /cloudflare/accounts |
domainrequired | string | Домен развёртывания, например example.comDeployment domain, for example example.com |
zone_idopt | string | ID зоны из списка зон; API проверяет владельца и домен. Если не передан, зона определяется по домену.A zone ID from the zone list; the API verifies ownership and domain. If omitted, the zone is resolved from the domain. |
HTTP 202 означает, что задача принята в очередь. Для уже развёрнутой кампании с той же конфигурацией ответ 200 не запускает повторную установку. Повторный запрос для уже ожидающей задачи сохраняет существующую запись очереди и её состояние.HTTP 202 means the job was accepted into the queue. For an already deployed campaign with identical configuration, 200 does not reinstall it. Repeating a request for a pending job preserves the existing queue entry and state.
Поддерживается Idempotency-Key на 24 часа. Ключ ограничен текущим аккаунтом, операцией и кампанией. Повторяйте запрос с тем же ключом и телом; другое тело в этой области возвращает 409 idempotency_conflict. Новый запрос для другой кампании или другой операции имеет отдельную область ключей.Idempotency-Key is supported for 24 hours, scoped to the current owner, operation and campaign. Retry with the same key and body; a different body within that scope returns 409 idempotency_conflict. A different campaign or operation has a separate key scope.
409. Для другого домена создайте отдельную кампанию.Rebinding an already active or deployed domain returns 409. Create a separate campaign for another domain.{}. Ответ 202 означает очередь; существующая ожидающая задача сохраняется.Retries deployment using saved configuration. Send the JSON object {}. A 202 response means queued; an existing pending job is preserved.{}. Если делегирование ещё ожидается, ответ 200 сообщает результат проверки. Если можно продолжить развёртывание, ответ 202 ставит задачу в очередь.Checks nameserver delegation for the saved domain. Send the JSON object {}. While delegation is pending, 200 returns the check result. When deployment can proceed, 202 queues the job.API использует тот же жизненный цикл кампании, что кабинет: изменение целей вызывает обновление, включение - восстановление, отключение и удаление - очистку интеграции. Установка обновления API сама по себе не меняет Worker у клиентов.The API uses the same campaign lifecycle as the cabinet: target changes trigger an update, enabling restores deployment, and disabling or deleting cleans up the integration. Installing the API update alone does not change customer Workers.
Cloudflare: полный пример cURLCloudflare: complete cURL example
Пример для Bash. Все значения ниже - заглушки. Подставьте свой токен с read и write, существующий аккаунт Cloudflare и собственный домен. После каждого шага проверьте HTTP-статус; замените ID на возвращённые API. Требуется DOMINATION.Bash example. All values below are placeholders. Supply your own token with read and write, an existing Cloudflare account and your domain. Check the HTTP status after each step and replace IDs with returned values. Requires DOMINATION.
export KLO_API_TOKEN='KLO_BEARER_TOKEN_PLACEHOLDER'
BASE='https://cabinet.klo-boostclicks.online/api/v1'
# 1. Save access to your existing Cloudflare account.
curl --silent --show-error --fail-with-body --max-time 30 -X POST "$BASE/cloudflare/accounts" \
-H "Authorization: Bearer $KLO_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"label":"Example account","email":"owner@example.com","api_key":"GLOBAL_API_KEY_PLACEHOLDER","account_id":"00000000000000000000000000000000"}'
# 2. Use data.id returned above; list zones and note the selected zone ID.
CREDENTIAL_ID='SAVED_ACCESS_ID_PLACEHOLDER'
curl --silent --show-error --fail-with-body --max-time 30 --get "$BASE/cloudflare/accounts/$CREDENTIAL_ID/zones" \
-H "Authorization: Bearer $KLO_API_TOKEN" \
--data-urlencode 'domain=example.com' --data-urlencode 'page=1' --data-urlencode 'per_page=20'
# 3. Create a Cloudflare campaign. No Worker is deployed by this request.
curl --silent --show-error --fail-with-body --max-time 30 -X POST "$BASE/campaigns" \
-H "Authorization: Bearer $KLO_API_TOKEN" -H 'Content-Type: application/json' \
-H 'Idempotency-Key: example-cf-campaign-001' \
-d '{"name":"Example Cloudflare","integration_type":"cloudflare","white_url":"https://white.example.com/","offer_url":"https://offer.example.com/","white_target_mode":"url","offer_target_mode":"url","white_method":"302","redirect_method":"302","unique_visit":{"enabled":true,"scope":"campaign","ttl_hours":24,"skip_mobile":false}}'
# 4. Use data.id returned by campaign creation and the zone ID from step 2.
CAMPAIGN_ID='CAMPAIGN_ID_PLACEHOLDER'
curl --silent --show-error --fail-with-body --max-time 30 -X POST "$BASE/campaigns/$CAMPAIGN_ID/cloudflare/deploy" \
-H "Authorization: Bearer $KLO_API_TOKEN" -H 'Content-Type: application/json' \
-H 'Idempotency-Key: example-cf-deploy-001' \
-d "{\"credential_id\":\"$CREDENTIAL_ID\",\"domain\":\"example.com\",\"zone_id\":\"ZONE_ID_PLACEHOLDER\"}"
# 5. Poll status with backoff; 202 means queued, not deployed.
curl --silent --show-error --fail-with-body --max-time 30 "$BASE/campaigns/$CAMPAIGN_ID/cloudflare" \
-H "Authorization: Bearer $KLO_API_TOKEN"
# 6. After setting the required nameservers at your registrar, check delegation.
curl --silent --show-error --fail-with-body --max-time 30 -X POST "$BASE/campaigns/$CAMPAIGN_ID/cloudflare/check-ns" \
-H "Authorization: Bearer $KLO_API_TOKEN" -H 'Content-Type: application/json' -d '{}'
# 7. Update one nested setting; other unique_visit fields stay unchanged.
curl --silent --show-error --fail-with-body --max-time 30 -X PATCH "$BASE/campaigns/$CAMPAIGN_ID" \
-H "Authorization: Bearer $KLO_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"unique_visit":{"ttl_hours":168}}'
# 8. If deployment needs a retry, use the saved configuration.
curl --silent --show-error --fail-with-body --max-time 30 -X POST "$BASE/campaigns/$CAMPAIGN_ID/cloudflare/retry" \
-H "Authorization: Bearer $KLO_API_TOKEN" -H 'Content-Type: application/json' -d '{}'Если домен ещё не делегирован, используйте name_servers из ответа списка зон и повторите проверку после обновления DNS. Для повторного deploy после сетевого сбоя сохраните исходное тело и ключ; для состояния используйте GET.If the domain is not delegated yet, use name_servers from the zone list and check again after DNS updates. Retain the original body and key when retrying deploy after a network failure; use GET to inspect state.
v1.2 OpenAPI-спецификацияOpenAPI specification
Машиночитаемый контракт (OpenAPI 3.1) - по нему генерируются клиенты и импортируется коллекция в Postman/Insomnia:A machine-readable contract (OpenAPI 3.1) - generate clients from it or import it into Postman/Insomnia:
https://cabinet.klo-boostclicks.online/api/openapi.jsonСпецификация доступна без токена, описывает маршруты, параметры и схемы ответа. Перед генерацией клиента скачайте актуальную версию. Клиент должен допускать новые поля и учитывать ограничения, описанные выше.The specification is public and describes routes, parameters and response schemas. Download the current version before generating a client. Clients should tolerate new response fields and honor the limits documented above.
# OpenAPI Generator
npx @openapitools/openapi-generator-cli generate \
-i https://cabinet.klo-boostclicks.online/api/openapi.json \
-g python -o ./klo-clientОбъектыObjects
КампанияCampaign
| ПолеField | Type | ОписаниеDescription |
|---|---|---|
id | string | Идентификатор кампанииCampaign identifier |
name | string | НазваниеName |
is_active | bool | Включена ли кампанияWhether the campaign is enabled |
integration_type | string | php_direct, php_reverse, sdk, javascript, keitaro, wordpress, cloudflare |
white_url | string | Белая страницаWhite page target |
offer_url | string | Оффер (целевая страница)Offer (target page) |
white_target_mode, offer_target_mode | string | В подробном ответе: url или localIn detailed responses: url or local |
white_method, redirect_method | string | Метод показа white и оффераWhite and offer delivery methods |
targeting | object | Гео, устройства, ОС, браузеры, языкиGeo, devices, OS, browsers, languages |
allowed_ips, blocked_ips | string[] | В подробном ответе: списки IP. Поля с суффиксом _count содержат их размеры.In detailed responses: IP lists. Fields ending in _count contain their sizes. |
utm_mode, utm_pattern | string | В подробном ответе: режим и шаблон метокIn detailed responses: query matching mode and pattern |
delayed_start_clicks | int | В подробном ответе: количество кликов прогреваIn detailed responses: warm-up click count |
unique_visit | object | [] | В подробном ответе: enabled, scope, ttl_hours, skip_mobile; значения и частичный PATCH описаны в создании.In detailed responses: enabled, scope, ttl_hours, skip_mobile; see creation for values and partial PATCH behavior. |
dns_channel | object | Текущий DNS-канал: enabled, а при включении zone и server. Только чтение; собственные резолверы не поддерживаются.Current DNS channel: enabled, and zone/server when enabled. Read-only; custom resolvers are unsupported. |
created_at, updated_at | string | null | Даты в ISO-8601 UTC; могут отсутствовать у старых записейISO-8601 UTC dates; legacy records may have unknown dates |
stats | object | today / total → {offer, white} |
stats_meta | object | Источник и полнота счётчиков: source, partialCounter source and completeness: source, partial |
Событие историиHistory event
| ПолеField | Type | ОписаниеDescription |
|---|---|---|
event_id | string | Непрозрачный ID для устранения повторов. Новый ID содержит 32 hex-символа; старые записи истории могут иметь пустую строку.Opaque ID for deduplication. New IDs have 32 hexadecimal characters; legacy history records may have an empty string. |
ts | int | Unix-время событияUnix time of the event |
time | string | То же в ISO-8601 (UTC)Same in ISO-8601 (UTC) |
action | string | offer · white |
reason | string | Причина решенияDecision reason |
ip, geo | string | IP и страна посетителяVisitor IP and country |
browser, device | string | Браузер и тип устройстваBrowser and device type |
site, campaign_id, query | string | Домен, ID кампании и строка параметров запроса; неизвестное значение пустоеDomain, campaign ID and query string; unknown values are empty |
История измененийChangelog
| ВерсияVersion | ИзмененияChanges |
|---|---|
v1.4.0 | Cloudflare: сохранённый доступ, зоны аккаунта, асинхронное развёртывание, статус, повтор и проверка NS; жизненный цикл кампании через API. SDK на START, Fedora, unique_visit с частичным вложенным PATCH, поля dns_channel для чтения.Cloudflare saved access, owned zones, asynchronous deployment, status, retry and nameserver checks; campaign lifecycle through the API. SDK on START, Fedora, unique_visit with partial nested PATCH, and read-only dns_channel. |
v1.2 | Тайм-серии (день/час), домены, фильтр campaign_id в истории, скачивание файла интеграции, Idempotency-Key, лимиты по тарифу, OpenAPI-спека.Time-series (day/hour), domains, campaign_id filter in history, integration file download, Idempotency-Key, plan-based rate limits, OpenAPI spec. |
v1.1 | Запись: создание, изменение, вкл/выкл и удаление кампаний (scope write; ограничения по тарифу).Write access: create, update, enable/disable and delete campaigns (write scope; plan limits). |
v1.0 | Первый выпуск: аккаунт, кампании, статистика, история, живая лента (только чтение).Initial release: account, campaigns, statistics, history, realtime feed (read-only). |
GET /campaigns/{id}/timeseries. /domains возвращает аналитику доменов; привязка домена Cloudflare выполняется через развёртывание.Per-campaign charts are available through GET /campaigns/{id}/timeseries. /domains returns domain analytics; bind a Cloudflare domain through deployment.