🌐 Lead Intake API

Публичный HTTPS-эндпоинт, через который любая HTML-форма, лендинг, n8n / Zapier / Make-сценарий или AI-агент кладёт нового лида прямо в твой Planning CRM. Документ читается человеком и AI-агентом — можно скормить его Claude / GPT, они построят форму сами.

⏬ Скачать готовую инструкцию для подключения формы

Markdown-файл с твоим API-токеном (выпустится автоматически, если ещё нет), готовой HTML-формой, рецептами для n8n / Zapier и промптом для AI-агента. Внутри ссылка на эту же страницу — чтобы агент при необходимости подтянул самую свежую документацию.

⏬ Скачать leads-api-guide.md

🔑 Получить / показать API-токен ⚡ Готовый пример HTML-формы 📦 JSON-схема (с реальными ID воронок)

В этом документе

Как это работает

  1. Получаешь свой API-токен в /agent-settings.html (блок «API-токен Planning»). Один токен на одного пользователя; перевыпуск отзывает старый.
  2. Дёргаешь GET /api/leads/schema — узнаёшь свои воронки, их стадии и список доступных полей.
  3. Каждая отправка формы шлёт POST /api/leads с JSON-телом. Сервер санитизирует все строки, ищет дубликаты по контактам (email / phone / соц-хэндлы) и кладёт новый контакт в указанную воронку и стадию. История изменений с пометкой [form] доступна и обратима из /admin.html.

Авторизация

Все эндпоинты требуют заголовок:

Authorization: Bearer <твой apiToken>

Токен лежит на странице /agent-settings.html → «API-токен Planning» (кнопка «Показать»). Это тот же токен, что использует браузерное расширение, n8n, Zapier и любые твои скрипты. Перевыпуск немедленно отзывает старый.

GET /api/leads/schema GET

Возвращает список воронок (с реальными id и стадиями), список принимаемых полей с типами и ограничениями, а также готовый пример запроса с baseUrl текущего инстанса. Используй этот эндпоинт перед каждой отправкой, если у тебя могут меняться воронки/стадии.

Пример ответа (сокращённо):

{
  "ok": true,
  "version": 1,
  "baseUrl": "https://plan.akm-technologies.org",
  "endpoint": "https://plan.akm-technologies.org/api/leads",
  "auth": { "type": "Bearer", "header": "Authorization: Bearer <apiToken>" },
  "pipelines": [
    {
      "id": "main",
      "name": "Основная",
      "stages": [
        { "id": "lead",      "label": "Lead" },
        { "id": "outreach",  "label": "Outreach" },
        { "id": "responded", "label": "Responded" }
      ],
      "firstStageId": "lead"
    }
  ],
  "fields": [ { "name": "fullName", "type": "string", "maxLen": 200, "required": true }, … ],
  "exampleRequest": { … }
}

POST /api/leads POST

Принимает JSON-тело с полями формы. Минимум — только fullName.

Ответ 201 / 200:

{
  "ok": true,
  "accepted": true,      // запрос принят
  "stored": true,        // лид сохранён (false — если honeypot сработал)
  "duplicate": false,    // true — нашли существующий контакт, не перетёрли
  "id": "c-1731776123-abc123",
  "contact": { … }       // итоговая запись
}

Если приходит контакт с тем же email / phone / соц-хэндлом, что и существующий — создаётся новое касание (interaction) с пометкой [form], а сам контакт не переписывается (это защита от перезаписи руками введённых данных). В ответе будет "duplicate": true и id уже существующего контакта.

Список полей

Сервер игнорирует любые поля, которых нет в этой таблице.

ПолеТипЛимитОписание
Загрузка…

Пример: HTML-форма (можно вставить на любой сайт)

Скопируй блок ниже, замени YOUR_API_TOKEN и https://plan.akm-technologies.org на свои значения. Форма отправляется без перезагрузки, показывает сообщение.

<form id="leadForm">
  <input name="fullName" placeholder="Имя"   required />
  <input name="email"    placeholder="E-mail" type="email" />
  <input name="phone"    placeholder="Телефон" />
  <textarea name="notes" placeholder="Сообщение"></textarea>
  <!-- honeypot: реальный пользователь его не увидит, бот заполнит -->
  <input name="honeypot" tabindex="-1" autocomplete="off"
         style="position:absolute;left:-9999px" />
  <button type="submit">Отправить</button>
  <div id="leadStatus"></div>
</form>

<script>
document.getElementById("leadForm").addEventListener("submit", async (e) => {
  e.preventDefault();
  const fd = new FormData(e.target);
  const body = Object.fromEntries(fd.entries());
  body.source     = "landing:" + location.pathname;
  body.sourceLink = location.href;
  body.tags       = ["landing"];

  const status = document.getElementById("leadStatus");
  status.textContent = "Отправляем…";

  try {
    const r = await fetch("https://plan.akm-technologies.org/api/leads", {
      method: "POST",
      headers: {
        "Content-Type":  "application/json",
        "Authorization": "Bearer YOUR_API_TOKEN"
      },
      body: JSON.stringify(body)
    });
    const data = await r.json();
    if (!r.ok) throw new Error(data.error || ("HTTP " + r.status));
    status.textContent = data.duplicate
      ? "Спасибо! Мы уже на связи — добавили ваше сообщение."
      : "Спасибо! Заявка принята.";
    e.target.reset();
  } catch (err) {
    status.textContent = "Ошибка: " + err.message;
  }
});
</script>

⚠️ Не клади токен в публичный HTML без прокси. На production-лендингах ставь свой маленький бэкенд (1 PHP-файл / Vercel function / Cloudflare worker) который принимает форму и сам ходит в /api/leads с токеном. Прямой вызов из браузера ок для внутренних форм или для теста.

curl / Python

curl

curl -sS -X POST "https://plan.akm-technologies.org/api/leads" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fullName": "Иван Петров",
    "email":    "ivan@example.com",
    "phone":    "+7 999 123-45-67",
    "company":  "Example LLC",
    "notes":    "Заполнил форму на лендинге /travel",
    "source":   "landing:/travel",
    "tags":     ["лендинг","travel"]
  }'

Python

import requests

requests.post(
    "https://plan.akm-technologies.org/api/leads",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"},
    json={
        "fullName": "Иван Петров",
        "email":    "ivan@example.com",
        "phone":    "+7 999 123-45-67",
        "source":   "landing:/travel",
        "tags":     ["лендинг", "travel"],
    },
    timeout=10,
).raise_for_status()

Промпт для AI-агента

Скопируй блок ниже и дай Claude / GPT / Cursor — он сам сделает форму под твою задачу.

Тебе нужно подключить HTML-форму на сайте к Planning CRM.

1. Перед тем как генерировать код, сделай GET-запрос на
   https://plan.akm-technologies.org/api/leads/schema
   с заголовком: Authorization: Bearer <APIKEY>
   В ответе будет:
     - pipelines[].id / pipelines[].stages[].id  → выбери подходящие
     - fields[]  → используй ТОЛЬКО эти имена полей, остальные сервер игнорирует

2. Сгенерируй HTML <form> с полями из задачи пользователя
   (стандартные: fullName email phone company notes; см. полный список в fields[]).
   ВСЕГДА добавляй скрытое поле name="honeypot" (защита от спама).

3. На submit отправь fetch POST на https://plan.akm-technologies.org/api/leads
   с тем же Bearer-токеном, Content-Type: application/json, телом из FormData.
   Добавь сам source и sourceLink (location.pathname / location.href).

4. По ответу:
   - r.ok && data.duplicate === true  → «Мы уже на связи — добавили ваше сообщение»
   - r.ok && data.duplicate === false → «Заявка принята»
   - !r.ok                            → показать data.error

Никаких других эндпоинтов выдумывать не нужно. Полная документация:
https://plan.akm-technologies.org/leads-api.html

Безопасность

Версия API: v1 · Эндпоинты: GET /api/leads/schema, POST /api/leads · CORS разрешён для всех Origin.