Интеграция M1.TOP с Keitaro: API и постбэк
Как подключить M1.TOP (бывший M1-shop) к Keitaro: отправка лидов по API send_order, subid в метке W, глобальный постбэк, статусы new, approved, declined…

M1.TOP (раньше M1-shop) работает и в 2026 году: на сайте сеть описывает себя как CPA-сеть в нутре и прямого рекламодателя в ЛатАме и ЕС. Чтобы лить на её офферы со своего лендинга через Keitaro, нужны три вещи: обработчик формы, который отправляет заявку на https://m1.top/send_order/, метка с subid клика и глобальный постбэк из M1 в трекер.
Ниже рабочая схема на октябрь 2026 года: какие ID взять в кабинете, готовый api.php, ссылка постбэка, таблица статусов и разбор ошибок.
- Что даёт интеграция по API
- Что взять в кабинете M1
- Форма на лендинге
- Обработчик api.php для M1
- Постбэк M1 в Keitaro
- Шаг 1. Партнёрская сеть в Keitaro
- Шаг 2. Глобальный постбэк в кабинете M1
- Статусы M1 и типы конверсий Keitaro
- Ошибки и где их искать
- Частые вопросы
- M1.TOP и M1-shop это одна сеть?
- Какую метку выбрать под subid: s, w или t?
- Можно ли отправлять заказы со своего лендинга?
- Почему тестовый постбэк не создаёт конверсию в Keitaro?
- Где посмотреть, почему заказ отклонён?
Что даёт интеграция по API
- Лендинг лежит у вас или в Keitaro, заявка уходит в M1 напрямую. Формы, прелендинги и тексты можно менять без кабинета сети.
- Keitaro получает лид, апрув и отмену по каждому клику. ROI считается по креативу, площадке и ключу, а не по офферу в целом.
- Причину отмены видно в кабинете M1 на вкладке «Заказы», а сам факт отмены приходит в трекер тем же постбэком.
Что взять в кабинете M1
| Параметр API | Что это | Где найти |
|---|---|---|
ref | ID вебмастера | кабинет M1, данные профиля |
api_key | API-ключ вебмастера | кабинет M1, данные профиля |
product_id | ID товара (оффера) для API | карточка оффера |
s, w, t | метки для своих данных | заполняете сами, одна из них под subid |
Проще всего сверить ref и ключ по лендингу, скачанному из кабинета: в документации Keitaro по передаче конверсий в партнёрские сети по API сказано, что в таком архиве уже прописаны API key и ID вебмастера. Если поля не нашли, спросите поддержку @M1_Supp, её контакт указан в FAQ сети.
Сервер M1 сразу сообщает, какого параметра не хватает. При проверке 1 октября 2026 года запрос без product_id вернул {"result":"error","message":"No Product ID"}, а запрос с пустым ID вебмастера получил HTTP 400 и "No Webmaster ID".
Форма на лендинге
В форме нужны поля name и phone и скрытое поле с subid клика. Если лендинг загружен в Keitaro архивом, трекер сам подставит значение вместо {subid}, так работает локальный лендинг.
<form action="api.php" method="post">
<input type="text" name="name" placeholder="Nombre" required>
<input type="tel" name="phone" placeholder="Teléfono" required>
<input type="hidden" name="subid" value="{subid}">
<button type="submit">Pedir</button>
</form>Если лендинг лежит на своём хостинге, добавьте к его адресу в Keitaro ?subid={subid}, а в форме выведите значение так: value="<?= htmlspecialchars($_GET['subid'] ?? '', ENT_QUOTES) ?>". Тогда файл лендинга должен быть index.php.
Обработчик api.php для M1
Положите файл рядом с index.html или index.php и заполните три константы в начале.
<?php
// api.php: принимает заявку с лендинга и отправляет её в M1.TOP
const API_URL = 'https://m1.top/send_order/';
const REF = 'ВАШ_ID_ВЕБМАСТЕРА'; // ID вебмастера (ref) из профиля M1
const API_KEY = 'ВАШ_API_KEY'; // API-ключ из профиля M1
const PRODUCT_ID = 'ID_ТОВАРА_API'; // «ID товара (API)» из карточки оффера
const BEHIND_CF = false; // true, если домен лендинга за Cloudflare
const TIMEOUT = 3; // секунды: лимит Keitaro для локальных лендингов
const LOG_FILE = __DIR__ . '/m1-leads.log';
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
exit;
}
$name = trim((string)($_POST['name'] ?? ''));
$phone = preg_replace('/\D+/', '', (string)($_POST['phone'] ?? ''));
$subid = preg_replace('/[^A-Za-z0-9_-]/', '', (string)($_POST['subid'] ?? ''));
if ($name === '' || strlen($phone) < 7) {
header('Location: error.php');
exit;
}
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
if (BEHIND_CF && !empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
$order = [
'ref' => REF,
'api_key' => API_KEY,
'product_id' => PRODUCT_ID,
'name' => $name,
'phone' => $phone,
'ip' => $ip,
'w' => $subid, // метка W: subid клика Keitaro, как в шаблоне трекера
's' => (string)($_POST['s'] ?? ''), // метки S и T свободны
't' => (string)($_POST['t'] ?? ''),
];
$ch = curl_init(API_URL);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($order),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => TIMEOUT,
CURLOPT_TIMEOUT => TIMEOUT,
]);
$body = curl_exec($ch);
$code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
$resp = is_string($body) ? json_decode($body, true) : null;
// Ошибка у M1 приходит в виде {"result":"error","message":"..."}
$ok = $code === 200 && is_array($resp) && ($resp['result'] ?? '') !== 'error';
file_put_contents(LOG_FILE, date('c') . " http=$code subid=$subid "
. substr((string)$body, 0, 300) . "\n", FILE_APPEND | LOCK_EX);
header('Location: ' . ($ok ? 'success.php' : 'error.php'));
exit;Что важно в коде:
- subid клика уходит в метку
w. Её же использует встроенный шаблон M1 в Keitaro, поэтому в постбэке она вернётся как{w}. - Телефон очищается до цифр, пустое имя или короткий номер сразу ведут на
error.php, запрос в сеть не уходит. - IP берётся из
REMOTE_ADDR. ЗаголовкуCF-Connecting-IPскрипт верит только приBEHIND_CF = true: без Cloudflare перед сайтом этот заголовок может подделать кто угодно. - В исправленном примере нужны HTTP 200, корректный JSON-массив и отсутствие явной ошибки. Это упрощённая проверка: она ещё не подтверждает создание заказа по позитивному контракту API. Перед рабочим запуском сверяйте положительный ответ и идентификатор заказа с актуальным API сети. Код проверяет, что в ответе нет
"result":"error". Вm1-leads.logпишется фрагмент ответа сети. Имя и телефон не добавляются отдельными полями, но могут оказаться в самом ответе. Маскируйте персональные данные и секреты до записи. - Таймаут 3 секунды. Такой лимит Keitaro ставит PHP-лендингам, загруженным в трекер. На своём хостинге его можно поднять до 10 секунд.
Страницы success.php и error.php нужны обязательно. Готовые шаблоны есть в статьях про мультиязычную страницу «Спасибо за заказ» и мультиязычную страницу ошибки. Закройте доступ к файлу лога из браузера или вынесите его за пределы папки сайта.
Постбэк M1 в Keitaro
Шаг 1. Партнёрская сеть в Keitaro
- Откройте «Партнерские сети», нажмите «Создать» и выберите шаблон M1-shop.ru: в трекере он до сих пор назван по старому домену.
- В поле «Параметры для оффера» оставьте
w={subid}. Оно нужно, если оффер M1 стоит в потоке редиректом. При отправке по API subid передаётapi.php. - Скопируйте Postback URL. Адрес трекера и ключ берутся из раздела «Настройки» → «Postback URL».

Готовая ссылка с обучением статусов по документации Keitaro о postback:
https://ВАШ_ТРЕКЕР/POSTBACK_KEY/postback?subid={w}&status={status}&lead_status=new&sale_status=approved&rejected_status=declined&payout={web_total}¤cy={currency}&tid={order_id}&from=m1.topПараметр tid с номером заказа нужен на случай, если с одного клика пришло два заказа: без него вторая конверсия перезапишет первую.
Шаг 2. Глобальный постбэк в кабинете M1
- Откройте раздел «Глобальный Postback» (в кабинете он лежит в «Инструментах»).
- Вставьте ссылку из Keitaro в поле Postback URL. Лимит поля 2000 символов.
- Отметьте «Создание заказа», «Подтверждение заказа» и «Отмена заказа». Без первой галочки трекер не увидит лиды, без третьей не увидит отмены.
- Метод передачи: GET.
- Нажмите «Сохранить». Постбэк, заданный в потоке, главнее глобального: если в потоке стоит своя ссылка, глобальная для него не сработает.

Макросы, которые M1 подставляет в ссылку (список со страницы «Глобальный Postback»):
| Макрос | Что передаёт |
|---|---|
{s}, {w}, {t} | метки S, W, T из заказа |
{order_id} | номер заказа |
{status} | статус: new, approved, declined |
{trash} | флаг треша: 1 или 0 |
{web_total} | размер выплаты за заказ, передаётся в любом статусе |
{lead_profit} | прибыль вебмастера, если заказ подтверждён |
{currency} | валюта: rub или usd |
{uip}, {lead_time}, {lead_date} | IP пользователя, время заказа в unix и в формате Y-m-d H:i:s |
Статусы M1 и типы конверсий Keitaro
| Статус M1 | Что значит | Тип в Keitaro | Обучение в ссылке |
|---|---|---|---|
| new | заказ создан, колл-центр обзванивает клиента | Lead | lead_status=new |
| approved | заказ подтверждён | Sale | sale_status=approved |
| declined | отказ или треш | Rejected | rejected_status=declined |
Треш M1 тоже отдаёт статусом declined, отличить его можно по {trash}=1. Если хотите видеть треш отдельно, допишите в ссылку &sub_id_20={trash} и стройте отчёт по этому параметру. По FAQ M1 в треш уходят заказы с некорректными данными, с ГЕО вне условий оффера, с неработающим или городским номером и с ответом «не заказывал». В отклонённые попадают дубли, недозвоны после лимита звонков и отказы клиента.
Отсекать повторные заявки до отправки в сеть помогает фильтр из статьи про дубли лидов.
Ошибки и где их искать
| Где видно | Сообщение | Причина и решение |
|---|---|---|
| m1-leads.log | No Webmaster ID (HTTP 400) | пустой или неверный ref, проверьте константу REF |
| m1-leads.log | No Product ID | не передан product_id, возьмите его в карточке оффера |
| m1-leads.log | no ref | сеть не приняла пару ID вебмастера и ключа, сверьте оба значения |
| m1-leads.log | http=0 | запрос не дошёл или упёрся в таймаут, проверьте исходящие соединения хостинга |
| Keitaro: «Обслуживание» → «Логи» → «Postbacks» | Click for subid REPLACE not found | в постбэке не та метка или subid не дошёл до M1: сверьте w в api.php и subid={w} в ссылке |
| Keitaro, логи постбэков | Postback status is not set | в ссылке нет status={status} |
| Keitaro, логи постбэков | Conversion type not found | статус без обучения: добавьте lead_status, sale_status, rejected_status |
| Keitaro, логи постбэков | Incorrect postback code | в ссылке устаревший ключ, скопируйте его заново в «Настройки» → «Postback URL» |
Расшифровка ошибок трекера взята из раздела Keitaro про устранение проблем с postback. Если в логе Keitaro пусто, а в M1 заказы есть, проверьте галочку «Создание заказа» и нет ли в потоке своего постбэка.
Частые вопросы
M1.TOP и M1-shop это одна сеть?
Да. Старый домен m1-shop.ru сейчас отвечает ошибкой 403, кабинет и API работают на m1.top. В Keitaro шаблон по-прежнему называется M1-shop.ru.
Какую метку выбрать под subid: s, w или t?
Любую, но одну и ту же в обработчике и в ссылке постбэка. Мы используем w, потому что её ждёт шаблон Keitaro.
Можно ли отправлять заказы со своего лендинга?
Да. В FAQ M1 прямо сказано, что заказы со своих лендингов и сайтов принимаются через iframe-форму или API.
Почему тестовый постбэк не создаёт конверсию в Keitaro?
По документации Keitaro партнёрские сети в тестовых постбэках не передают реальный subid клика. Проверяйте связку реальной заявкой по ссылке кампании.
Где посмотреть, почему заказ отклонён?
В кабинете M1 на вкладке «Заказы». Там же можно прослушать записи разговоров по отклонённым лидам на колл-центре M1.



