1. Главная
  2. Документация
  3. API Keys: описание методов

API Keys: описание методов

Ключи, лимиты, ошибки и все методы API v1 с примерами запросов и ответов.

API нужен, чтобы забирать фразы с частотами и позициями в свои отчёты и инструменты, добавлять фразы из своих систем и запускать сбор данных без интерфейса. Ниже всё о ключах, лимитах и ошибках и описание каждого метода с примерами.

Доступ и ключи

  • Тариф. API работает на тарифе «Агентство». Если тариф закончился, запросы получают ошибку plan, а ключи остаются и снова заработают после оплаты.
  • Ключи создают владелец и администратор пространства на странице «Команда» в разделе «Ключи API». Ключ показывается один раз, сохраните его сразу. До 20 действующих ключей на пространство, отзыв кнопкой «Отозвать» действует мгновенно.
  • Права ключа такие же, как у человека, который его создал, и только в проектах этого пространства. Когда человека убирают из команды, его ключи отзываются автоматически.

Подробнее о ключах: Команда: ключи API.

Как отправлять запросы

  • Адрес: https://keys.linkodium.com/api/v1/, к нему добавляется путь метода без слэша в конце, например https://keys.linkodium.com/api/v1/projects.
  • Ключ передаётся заголовком Authorization: Bearer kk_…. Ключ начинается с kk_, за ним 48 символов.
  • Формат: параметры GET-методов передаются в строке запроса, тело POST-методов передаётся в JSON (заголовок Content-Type: application/json, кодировка UTF-8, без сжатия). Тело запроса не больше 40 МБ.
  • Ответ всегда JSON. Успешный ответ содержит "ok": true и данные.
  • Деньги во всех полях указаны в копейках: balance_kop, price_kop, reserved_kop, cost_kop. 150000 означает 1 500 ₽.
  • Время в формате ISO 8601 по UTC, например 2026-10-24T09:12:40Z.

Лимиты

ЧтоСколько
Запросов на один ключ120 в минуту
Фраз в одном ответе GET …/phrasesдо 10 000
Фраз в одном запросе POST …/phrasesдо 200 000 строк, фраза до 400 символов
Фраз в одном заданиидо 500 000
Масок в одном сборедо 1 000, маска до 200 символов
Заданий в очереди и работе на один проектдо 5
Фраз в проектедо 500 000

Задания пространства на тарифе «Агентство» стоят в общей очереди сервиса выше остальных.

Ошибки

При ошибке приходит HTTP-статус из таблицы и JSON с полями ok, error (текст на русском, его можно показать человеку) и code (короткий код для программы).

{"ok": false, "error": "Не больше 120 запросов в минуту", "code": "rate_limited"}
HTTPcodeКогда
401unauthorizedНет заголовка Authorization, ключ неверный или отозван.
403planУ пространства не тариф «Агентство» или он закончился.
403forbiddenЧеловек, создавший ключ, больше не в команде.
404not_foundПроект или задание не найдены в пространстве ключа, либо такого метода нет.
409staleПроект изменился в момент добавления фраз. Повторите запрос.
422invalidОшибка в параметрах или задание нельзя запустить: не хватает денег на балансе, уже идут 5 заданий, нет фраз, превышен лимит фраз и так далее. Причина в error.
423lockedДобавить фразы нельзя: проект сейчас правит другой человек в интерфейсе. Повторите через пару минут.
423importingВ проект идёт перенос из KeyCollector, правки откроются после него.
429rate_limitedБольше 120 запросов в минуту с одного ключа. Подождите и повторите.
500storageНе удалось сохранить изменение из-за временного сбоя. Повторите запрос.

Список методов

МетодЧто делает
GET /balanceТариф, срок, баланс и скидка
GET /regionsНомера регионов Яндекса и Google по названию
GET /projectsПроекты пространства
POST /projectsСоздать проект
GET /projects/{id}Проект, формулы KEI и группы
GET /projects/{id}/phrasesФразы с частотами, выдачей и позициями
POST /projects/{id}/phrasesДобавить фразы в группу
POST /projects/{id}/importЗагрузить частоты, позиции и другие данные в фразы проекта
POST /projects/{id}/jobsУзнать цену или запустить задание
GET /jobs/{id}Состояние и итог задания

GET /balance: баланс и тариф

Параметров нет.

curl -s -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" https://keys.linkodium.com/api/v1/balance
{
  "ok": true,
  "workspace": "Личное пространство",
  "plan": "agency",
  "plan_until": "2026-11-23T10:15:00Z",
  "balance_kop": 1250000,
  "discount": 25
}
ПолеЧто это
workspaceНазвание пространства
planДействующий тариф: start, specialist, team или agency
plan_untilДата окончания тарифа
balance_kopБаланс в копейках
discountСкидка тарифа на данные, в процентах

GET /regions: номера регионов

Поиск региона по названию для параметров region и regions заданий. Регионы Яндекса и Google нумеруются по-разному, поэтому поисковик указывается явно.

ПараметрЧто значит
engineyandex (по умолчанию) или google
qЧасть названия, например «пермь». Для Яндекса без q вернутся основные регионы, для Google q обязателен
curl -s -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" "https://keys.linkodium.com/api/v1/regions?engine=google&q=пермь"
{
  "ok": true,
  "engine": "google",
  "regions": [
    {"id": 1011969, "name": "Perm", "path": "Perm, Perm Krai, Russia"}
  ]
}

В задание передавайте id. Если сервис регионов временно недоступен, ответ будет 503 с кодом unavailable.

GET /projects: список проектов

Все проекты пространства, кроме архивных, по порядку создания. Параметров нет.

curl -s -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" https://keys.linkodium.com/api/v1/projects
{
  "ok": true,
  "projects": [
    {"id": 12, "name": "Стоматология", "site": "example.ru", "phrases": 18450, "updated_at": "2026-10-24T09:12:40Z"}
  ]
}

phrases: число фраз в проекте, updated_at: время последней правки.

POST /projects: создать проект

ПараметрТипОписание
nameстрокаОбязательно. Название, до 255 символов.
siteстрокаСайт проекта, например example.ru. Нужен для позиций, можно не передавать.
curl -s -X POST -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" -H "Content-Type: application/json" \
  -d '{"name": "Кальяны", "site": "example.ru"}' https://keys.linkodium.com/api/v1/projects
{"ok": true, "id": 13}

В новом проекте сразу есть группа «Новая группа 1» и формулы KEI по умолчанию.

GET /projects/{id}: проект и группы

curl -s -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" https://keys.linkodium.com/api/v1/projects/12
{
  "ok": true,
  "project": {
    "id": 12, "name": "Стоматология", "site": "example.ru", "phrases": 18450,
    "kei": [
      {"id": "kei1", "name": "KEI 1 Эффективность (фразовая)", "expr": "((base + phrase) / (base + 0.01) - 1) * 100"}
    ]
  },
  "groups": [
    {"id": 101, "parent_id": null, "name": "Имплантация", "path": "Имплантация", "unused": false},
    {"id": 102, "parent_id": 101, "name": "Цены", "path": "Имплантация / Цены", "unused": false}
  ]
}
  • kei: формулы KEI проекта. Значения KEI API не отдаёт: они считаются по формулам из частот и данных выдачи, посчитайте их у себя. Переменные формул описаны в разделе Формулы KEI.
  • groups: все группы проекта, отсортированные по пути. parent_id равен null у групп верхнего уровня, path содержит полный путь через « / ». unused равен true у неиспользуемых групп: их фразы не входят в "scope": "all".

GET /projects/{id}/phrases: фразы

Фразы проекта по порядку добавления. Удалённые фразы не возвращаются.

ПараметрПо умолчаниюОписание
group_idвсе группыТолько фразы этой группы, без подгрупп
limit1000Сколько фраз вернуть, от 1 до 10 000
offset0Сколько фраз пропустить
curl -s -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" "https://keys.linkodium.com/api/v1/projects/12/phrases?limit=1000&offset=0"
{
  "ok": true,
  "phrases": [
    {
      "id": 5501, "text": "имплантация зубов цена", "group_id": 102, "marker": 0, "checked": 0,
      "f_base": 12840, "f_phrase": 3120, "f_exact": 2410, "f_region": 225, "f_period": "year",
      "s_docs": 41000000, "s_main": 2, "s_titles": 7,
      "ya_pos": 4, "ya_prev": 6, "ya_url": "https://example.ru/implant/",
      "g_pos": null, "g_prev": null, "g_url": null,
      "added_at": "2026-10-20T14:03:11Z"
    }
  ],
  "limit": 1000,
  "offset": 0,
  "total": 18450
}
ПолеЧто это
id, text, group_idНомер фразы, текст и группа
markerЦвет строки: 0 без цвета, от 1 до 10 цвета от красного до розового
checkedГалочка: 1 стоит, 0 нет
f_base, f_phrase, f_exactЧастота базовая, "фразовая" и "!точная"
f_region, f_periodРегион и период частоты: year, quarter, month, week для прогноза Директа, ws для Wordstat
s_docs, s_main, s_titlesВыдача Яндекса: документов найдено, главных страниц в топ-10, заголовков с фразой в топ-10
ya_pos, ya_prev, ya_urlПозиция сайта в Яндексе, прежняя позиция и найденный адрес
g_pos, g_prev, g_urlТо же для Google
added_atКогда фраза добавлена

Если данные не собирались, в поле null. total показывает число фраз во всём проекте, даже если задан group_id. Чтобы забрать все фразы, увеличивайте offset на limit, пока не придёт пустой список.

POST /projects/{id}/phrases: добавить фразы

ПараметрТипОписание
phrasesмассив строкОбязательно. До 200 000 строк.
group_idчислоГруппа, куда положить фразы.
group_nameстрокаЕсли group_id не передан: создать новую группу верхнего уровня с этим названием. Каждый такой запрос создаёт новую группу, даже если группа с таким названием уже есть.
curl -s -X POST -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" -H "Content-Type: application/json" \
  -d '{"group_id": 102, "phrases": ["имплантация зубов цена", "импланты под ключ"]}' \
  https://keys.linkodium.com/api/v1/projects/12/phrases
{"ok": true, "group_id": 102, "added": 1, "existing": 1, "duplicates_in_input": 0}
  • added: сколько фраз добавлено. existing: сколько уже было в проекте (в любой группе), они не добавляются и не переносятся. duplicates_in_input: повторы внутри переданного списка.
  • Дубли сравниваются без учёта регистра, «ё» и «е» считаются одной буквой. Лишние пробелы убираются, фраза длиннее 400 символов обрезается.
  • В колонке «Источник» у таких фраз будет «Файл». Добавление можно отменить в проекте через Ctrl+Z, как обычную правку.
  • Если новые фразы не помещаются в лимит тарифа, ничего не добавляется и приходит ошибка invalid.
  • Добавление считается правкой проекта от имени владельца ключа. Если в интерфейсе проект правит другой человек, придёт ошибка locked. Право правки запись через API не забирает: люди в интерфейсе продолжают работать как обычно.

POST /projects/{id}/import: загрузить данные фраз

То же, что «Данные → Импорт данных из CSV / Excel» в проекте: данные, снятые в другом месте, записываются в фразы проекта. Бесплатно. Фразы сопоставляются с проектом так же, как при добавлении.

ПараметрТипОписание
phrasesмассив строкОбязательно. Фразы, до 50 000 строк за запрос (больше: несколькими запросами). Повтор фразы пропускается, берётся первая строка.
valuesобъектДанные по колонкам: ключ колонки и массив значений той же длины, что phrases. Колонки: f_base, f_phrase, f_exact (частоты), s_docs, s_main, s_titles (выдача), ya_pos, ya_url, g_pos, g_url (позиции и адреса). null или пустая строка: значения нет, данные фразы не меняются.
newстрокаЧто делать с фразами, которых в проекте нет: group (по умолчанию) добавить в group_id; column разложить по группам из groups; skip не добавлять.
group_idчислоГруппа для новых фраз. При new = column: группа для строк с пустым названием группы.
groupsмассив строкДля new = column: название группы по каждой строке. Путь «Родитель / Группа» ищется от корня дерева, просто название ищется по всему дереву. Чего нет, то создаётся.
overwriteлогическоеfalse (по умолчанию): заполнить только пустые значения. true: перезаписать собранные значения значениями из запроса.
curl -s -X POST -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" -H "Content-Type: application/json" \
  -d '{"phrases": ["имплантация зубов цена", "импланты под ключ"], "values": {"f_base": [12840, 960], "f_exact": [2410, null]}, "new": "skip"}' \
  https://keys.linkodium.com/api/v1/projects/12/import
{
  "ok": true,
  "import": {"rows": 2, "matched": 2, "added": 0, "skipped_new": 0, "updated": 2, "filled": 3, "replaced": 0, "kept": 0, "bad": 0, "dup_input": 0, "empty": 0, "groups_created": 0, "op_id": 8812, "label": "Импорт «API»: данные у 2"},
  "added_ids": [],
  "updated_ids": [5501, 5502]
}
  • Числа передавайте числами или строками: «12 840» и «12,5» тоже понимаются. Частота от 0 до 4 294 967 295, главных страниц и заголовков до 255, позиция от 1 до 1000. Позиция 0, прочерк, «>100» или «100+» значит «сайта нет в выдаче». Адрес должен начинаться с http:// или https://.
  • bad: сколько значений не удалось понять, они пропущены. kept: сколько значений не записано, потому что у фразы уже было другое значение, а overwrite выключен.
  • Импорт можно отменить в проекте через Ctrl+Z: добавленные фразы удалятся, данные фраз вернутся, какими были.
  • Если новые фразы не помещаются в лимит тарифа, ничего не меняется и приходит ошибка invalid. Если проект правит другой человек, приходит locked, как при добавлении фраз.

POST /projects/{id}/jobs: цена и запуск задания

Один метод для четырёх видов заданий. Вид задаётся полем kind, остальные поля зависят от вида и повторяют настройки окон меню «Данные».

kindЧто делаетОкно в интерфейсе
collectСбор фраз по маскамСбор фраз по маскам
freqЧастотностьЧастотность
serpВыдача и позицииВыдача и позиции
clusterКластеризацияКластеризация

Сначала узнайте цену

Добавьте к любому заданию "estimate": true: задание не запустится, деньги не зарезервируются, придёт расчёт цены.

curl -s -X POST -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" -H "Content-Type: application/json" \
  -d '{"kind": "freq", "source": "direct", "scope": "all", "estimate": true}' \
  https://keys.linkodium.com/api/v1/projects/12/jobs
{
  "ok": true,
  "estimate": {
    "label": "Частота из Директа: 1520 фраз без частоты",
    "units": {"freq_direct": 1520},
    "price_kop": 1710,
    "full_kop": 1710,
    "discount": 25,
    "exempt": false,
    "balance_kop": 1250000,
    "enough": true
  }
}
ПолеЧто это
labelОписание задания
unitsСколько единиц будет оплачено: масок, фраз или страниц выдачи
price_kopНаибольшая цена задания со скидкой тарифа. Эта сумма зарезервируется при запуске
full_kopЦена со скидкой тарифа. Отличается от price_kop, только если данные для пространства бесплатны
discountСкидка тарифа, в процентах
exempttrue, если данные для пространства бесплатны
balance_kop, enoughБаланс сейчас и хватает ли его на задание

Запуск

Тот же запрос без estimate ставит задание в очередь и резервирует price_kop на балансе. По итогу списывается только сделанное, остаток резерва возвращается на баланс. Если денег не хватает, задание не запускается, приходит ошибка invalid.

curl -s -X POST -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" -H "Content-Type: application/json" \
  -d '{"kind": "freq", "source": "direct", "scope": "all"}' \
  https://keys.linkodium.com/api/v1/projects/12/jobs
{"ok": true, "job": 3471, "reserved_kop": 1710}

job: номер задания для GET /jobs/{id}. Задание видно и в проекте, во вкладке «Процессы». Список фраз фиксируется в момент запуска: фразы, добавленные позже, в задание не попадут. Как считается цена: Задания: цена, резерв и списание.

Какие фразы обработать

Для freq, serp и cluster нужен один из параметров:

ПараметрОписание
"scope": "all"Все фразы проекта, кроме групп с "unused": true (неиспользуемые группы)
"ids": [5501, 5502]Номера фраз из GET …/phrases. Удалённые и чужие номера пропускаются

Регионы задаются номерами регионов Яндекса: 225 Россия, 213 Москва, 2 Санкт-Петербург. По умолчанию везде 225. Найти номер по названию: GET /regions.

collect: сбор фраз по маскам

Фразы для сбора не нужны: задание работает по маскам. Цена: 1 ₽ за маску, подсказки 0,1 ₽ за маску и поисковик, до скидки тарифа.

ПараметрПо умолчаниюОписание
masksобязательноСтрока, маски через перевод строки \n. До 1 000 масок
region225Регион Wordstat
elkafalse«Ёлочка»: та же маска до 7 слов, редкие хвосты. В интерфейсе включено по умолчанию, в API передайте true явно
assocfalseДобавить «похожие запросы» Wordstat в группу «Похожие запросы»
suggest_y, suggest_gfalseПодсказки Яндекса, подсказки Google
min_freq0Не добавлять фразы с базовой частотой ниже порога
group_id«Собранные фразы»Куда положить фразы. Без него фразы лягут в группу «Собранные фразы» верхнего уровня, она создаётся, если её нет
per_maskfalseОтдельная группа на каждую маску: внутри group_id, а без него на верхнем уровне. Группа с таким же названием на том же месте используется повторно
minustrueФразы с минус-словами проекта положить в группу «Отсеяно минус-словами»
{"kind": "collect", "masks": "имплантация зубов\nимплант зуба", "region": 213, "elka": true, "suggest_y": true, "group_id": 101, "per_mask": true}

freq: частотность

Цена: прогноз Директа 15 ₽ за 1000 фраз за все три вида сразу, Wordstat 20 ₽ за 1000 фраз за каждый вид, до скидки тарифа.

ПараметрПо умолчаниюЗначения
sourcedirectdirect: прогноз Директа за период; wordstat: Wordstat за последние 30 дней
formsвсе триМассив из base, phrase, exact
region225Регион Яндекса
periodyearТолько для Директа: year, quarter, month, week
period_num0Для квартала: 0 ближайший, от 1 до 4 номер квартала. Для месяца: 0 ближайшие 30 дней, от 1 до 12 месяц с января по декабрь
only_emptytruetrue: только фразы без частоты; false: перезаписать
{"kind": "freq", "source": "direct", "forms": ["base", "phrase", "exact"], "region": 225, "period": "month", "period_num": 0, "scope": "all"}

serp: выдача и позиции

Цена: сразу 2 ₽ за 100 страниц выдачи (страница это 10 результатов), ночью 45 ₽ за 1000 фраз, до скидки тарифа. Сразу резервируется цена полной глубины, а списываются только снятые страницы: сбор останавливается, когда найден сайт.

ПараметрПо умолчаниюЗначения
modenownow: сразу, Яндекс и Google; night: ночью, только Яндекс, топ-100, готово к утру
engines["yandex"]Массив из yandex, google. Ночью всегда только Яндекс
regions{"yandex": 225}Объект с регионами: yandex и google. Для Google регион обязателен
depth100Глубина от 10 до 100 с шагом 10. Ночью всегда 100
devicedesktopdesktop или mobile. Ночью не выбирается
siteсайт проектаСайт, позиции которого искать. Поддомены считаются сайтом, www не важен
only_emptytruetrue: только фразы без позиций; false: обновить, прежняя позиция станет «было»
{"kind": "serp", "mode": "now", "engines": ["yandex"], "regions": {"yandex": 213}, "depth": 30, "device": "desktop", "scope": "all"}
Номер региона Google найдите методом GET /regions?engine=google&q=…: у Google своя нумерация, номера Яндекса для него не подходят.

cluster: кластеризация

Нужно минимум две фразы. Цена: по выдаче 25 ₽ за 1000 фраз, с ИИ 90 ₽ за 1000 фраз, по словам бесплатно. Недостающая выдача Яндекса (топ-10, компьютер) снимается сама и входит в цену. Фразы, по которым выдачу получить не удалось, в кластеризации не участвуют и не оплачиваются.

ПараметрПо умолчаниюЗначения
methodserpserp: по общим адресам в топ-10; ai: выдача и модель, понимает интент и называет группы; words: по словам
threshold3Для serp: сколько общих адресов в топ-10 нужно, от 1 до 10
hardfalseДля serp: общие адреса со всеми фразами кластера, а не только с главной
graincoarseДля ai: coarse крупно, normal обычно, fine мелко
region225Регион выдачи для фраз, у которых её ещё нет
{"kind": "cluster", "method": "ai", "grain": "coarse", "region": 213, "scope": "all"}

Кластеризация через API группы не меняет. Готовые кластеры приходят в result задания, а применить их можно в проекте: окно результата открывается кнопкой «Открыть» во вкладке «Процессы», там же «Создать группы».

GET /jobs/{id}: состояние задания

Возвращает любое задание пространства, в том числе запущенное из интерфейса.

curl -s -H "Authorization: Bearer kk_ВАШ_КЛЮЧ" https://keys.linkodium.com/api/v1/jobs/3471
{
  "ok": true,
  "job": {
    "id": 3471, "kind": "freq", "status": "done",
    "progress": null,
    "result": {"updated": 1520, "nodata": 0},
    "message": "Частота из Директа (за год, регион 225): 1520 фраз",
    "cost_kop": 1710, "reserved_kop": 0,
    "run_after": null, "cancel": false,
    "created_at": "2026-10-24T09:20:05Z", "started_at": "2026-10-24T09:20:06Z", "finished_at": "2026-10-24T09:21:40Z",
    "project_id": 12
  }
}
ПолеЧто это
kindcollect, freq, serp, cluster, import_kc (перенос из KeyCollector), ai_minus или ai_site (ИИ-помощник, beta; запускаются только из интерфейса)
statusqueued в очереди, running идёт, done готово, error ошибка, cancelled отменено
progressПока задание идёт: этап stage, сделано done из total
messageИтог задания или текст ошибки, как во вкладке «Процессы»
resultПодробный итог, зависит от вида задания (ниже)
reserved_kopРезерв, пока задание идёт. После окончания 0
cost_kopСколько списано по итогу
run_afterЕсли задание ждёт: когда оно продолжится
canceltrue, если в интерфейсе нажали «Отменить»

Что лежит в result

  • collect: added добавлено, existing уже были в проекте, minus отсеяно минус-словами, below реже порога, cut не поместилось по тарифу, groups номера групп с фразами.
  • freq из Директа: updated фраз с частотой, nodata фраз, по которым Директ не дал данных (за них не списывается). У Wordstat итог только в message.
  • serp: итог в message, сами позиции читайте через GET …/phrases.
  • cluster: method, noserp номера фраз без выдачи и clusters: список кластеров с полями name (название), center (главная фраза), ids (номера фраз, самые частотные первыми), freq (сумма частот), у ИИ ещё intent.

Как дождаться результата

  1. Запустите задание и сохраните номер job.
  2. Запрашивайте GET /jobs/{id} раз в 5-10 секунд, пока status не станет done, error или cancelled. Ночные задания ждут ночного окна Яндекса и готовы к утру: для них хватит запроса раз в несколько минут. Пока задание ждёт, оно может снова показывать queued с run_after.
  3. После done заберите данные через GET …/phrases или из result.

Чего API не умеет

  • отменять задания: это делается во вкладке «Процессы» проекта;
  • создавать, переименовывать и удалять группы, кроме создания через group_name;
  • удалять, переносить, красить фразы и ставить галочки;
  • работать с минус-словами и формулами KEI;
  • применять кластеры к группам;
  • переносить проекты из KeyCollector, выгружать Excel и файл семядра;
  • архивировать и удалять проекты, открывать доступ, управлять командой и оплатой.

Всё это доступно в интерфейсе. Вопросы по API: info@linkodium.com.