SEOньоритаДокументация API
API v1Позиции и конкуренты
Public API v1

Позиции и конкуренты

Один estimate/run-контур собирает позиции либо обычную Топ-10 выдачу конкурентов.

GET/projects/{projectId}/keywords/position-summarysemantics:readGET/projects/{projectId}/keywords/position-historysemantics:readGET/projects/{projectId}/tracking-contextspositions:readPOST/projects/{projectId}/tracking-contextspositions:runPATCH/projects/{projectId}/tracking-contexts/{contextId}positions:runPOST/projects/{projectId}/tracking-contexts/{contextId}/materializepositions:runPUT/projects/{projectId}/tracking-contexts/{contextId}/keywordspositions:runPOST/projects/{projectId}/rank-estimatespositions:runGET/projects/{projectId}/rank-runspositions:readPOST/projects/{projectId}/rank-runspositions:runGET/projects/{projectId}/jobs/{jobId}positions:readGET/projects/{projectId}/jobs/{jobId}/resultpositions:readPOST/projects/{projectId}/jobs/{jobId}/cancelpositions:runGET/projects/{projectId}/jobs/{jobId}/runtime-diagnosticspositions:readPOST/projects/{projectId}/jobs/{jobId}/retry-missingpositions:runGET/projects/{projectId}/rank-historypositions:readGET/projects/{projectId}/rank-workbench/dimension-mergespositions:readPOST/projects/{projectId}/rank-workbench/dimension-mergespositions:runPOST/projects/{projectId}/rank-workbench/dimension-merges/{mergeId}/removepositions:runPOST/projects/{projectId}/rank-workbench/positionspositions:readPOST/projects/{projectId}/rank-workbench/serppositions:readPOST/projects/{projectId}/rank-workbench/delete-dimension-historypositions:runGET/projects/{projectId}/keyword-ranks/dimensionspositions:readPOST/projects/{projectId}/keyword-ranks/comparisonpositions:readGET/projects/{projectId}/tracking-contexts/{contextId}positions:readPOST/projects/{projectId}/tracking-contexts/{contextId}/archivepositions:runPOST/projects/{projectId}/tracking-contexts/{contextId}/restorepositions:runGET/projects/{projectId}/tracking-contexts/{contextId}/keywordspositions:readPUT/projects/{projectId}/tracking-contexts/{contextId}/keywords/{keywordId}positions:runDELETE/projects/{projectId}/tracking-contexts/{contextId}/keywords/{keywordId}positions:run

Read-only API для внешнего клиентского кабинета

Для витрины наподобие таблицы позиций создайте отдельный API-ключ только со scopes projects:read, semantics:read и positions:read. Ограничьте ключ нужными проектами. Такой ключ может читать семантику, папки, целевые URL, частотности, города, устройства и историю позиций, но не может запускать сборы или изменять данные.

Базовые данные витриныbash
# 1. Найти доступный проект
curl "https://api.seonorita.ru/api/v1/access" \
  -H "Authorization: Bearer $SEO_API_TOKEN"

# 2. Получить дерево папок и семантику с целевыми URL
curl "https://api.seonorita.ru/api/v1/projects/<projectId>/keyword-groups" \
  -H "Authorization: Bearer $SEO_API_TOKEN"
curl "https://api.seonorita.ru/api/v1/projects/<projectId>/keywords?limit=200" \
  -H "Authorization: Bearer $SEO_API_TOKEN"

# 3. Получить точные срезы поисковик · город · устройство
curl "https://api.seonorita.ru/api/v1/projects/<projectId>/keyword-ranks/dimensions" \
  -H "Authorization: Bearer $SEO_API_TOKEN"
Матрица для таблицы клиентаbash
curl -X POST "https://api.seonorita.ru/api/v1/projects/<projectId>/rank-workbench/positions" \
  -H "Authorization: Bearer $SEO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "SEO",
    "dimensionKey": "<key из keyword-ranks/dimensions>",
    "observedFrom": "2026-06-01T00:00:00.000Z",
    "observedBefore": "2026-09-17T00:00:00.000Z",
    "dateLimit": 14,
    "limit": 100,
    "sort": "POSITION_ASC"
  }'
  1. 1Контекст
  2. 2Оценка
  3. 3Запуск
  4. 4Результат

Сводка позиций проекта

Главный экран читает текущие значения и отдельную append-only историю. История возвращает до 100 последних срезов; клиент может выбрать период и показать не более 30 точек без пересчёта данных.

Текущая сводка и история ТОПовbash
curl "https://api.seonorita.ru/api/v1/projects/<projectId>/keywords/position-summary" \
  -H "Authorization: Bearer $SEO_API_TOKEN"

curl "https://api.seonorita.ru/api/v1/projects/<projectId>/keywords/position-history" \
  -H "Authorization: Bearer $SEO_API_TOKEN"

# Включить в исторические TOP-счётчики активные неотслеживаемые запросы
curl "https://api.seonorita.ru/api/v1/projects/<projectId>/keywords/position-history?includeUntracked=true" \
  -H "Authorization: Bearer $SEO_API_TOKEN"

1. Создать контекст

POST/projects/{projectId}/tracking-contextspositions:run
JSON · Тело запросаjson
{
  "name": "Москва · Десктоп",
  "isReusable": true,
  "configuration": {
    "searchEngine": "YANDEX",
    "countryCode": "RU",
    "regionCode": "213",
    "regionLabel": "Москва",
    "language": "ru",
    "device": "DESKTOP",
    "depth": 50,
    "domainMatchRule": { "mode": "EXACT_HOST" },
    "safeSearch": false
  },
  "launchProfile": {
    "searchSource": "LIVE",
    "includeUntracked": false,
    "scope": { "mode": "ALL", "groupIds": [], "includeDescendants": false }
  }
}

Для создания обязателен уникальный Idempotency-Key. Для одноразового ручного запуска передайте isReusable=false: контекст сохранит неизменяемую историю, но не появится в каталоге профилей и расписаниях. GET-список возвращает только активные сохранённые профили. Для изменения передавайте ETag контекста через If-Match.

Пересчитать охват контекста

POST/projects/{projectId}/tracking-contexts/{contextId}/materializepositions:run

Передайте пустой JSON. Сервер прочитает сохранённый охват, заново раскроет выбранные папки и их потомков, исключит удалённые и неотслеживаемые запросы согласно includeUntracked и вернёт актуальное количество. Keyword ID от клиента не принимаются. Регулярные и ручные запуски расписания выполняют этот пересчёт автоматически перед оценкой.

Запросbash
curl -X POST "https://api.seonorita.ru/api/v1/projects/<projectId>/tracking-contexts/<contextId>/materialize" \
  -H "Authorization: Bearer $SEO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
200 · Ответjson
{
  "data": {
    "contextId": "<contextId>",
    "assignedKeywordCount": 894,
    "addedKeywordCount": 12,
    "removedKeywordCount": 3,
    "unchangedKeywordCount": 882,
    "keywordSetHash": { "algorithm": "SHA_256", "value": "..." },
    "version": 5,
    "changedAt": "2026-09-13T19:30:00.000Z"
  },
  "meta": { "requestId": "01J...", "version": 5 }
}

2. Получить оценку

POST/projects/{projectId}/rank-estimatespositions:run
Запросbash
curl -X POST "https://api.seonorita.ru/api/v1/projects/<projectId>/rank-estimates" \
  -H "Authorization: Bearer $SEO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: rank-estimate:agent:2026-09-01T16:00" \
  -d '{
    "trackingContextId": "<contextId>",
    "purpose": "POSITION_TRACKING",
    "provider": "XMLSTOCK",
    "searchSource": "LIVE"
  }'
201 · Сокращённый ответjson
{
  "data": {
    "id": "<estimateId>",
    "trackingContextId": "<contextId>",
    "status": "READY",
    "provider": "XMLSTOCK",
    "purpose": "POSITION_TRACKING",
    "credentialMode": "PLATFORM_PAID",
    "scope": {
      "keywordCount": "2130",
      "contextCount": "1",
      "pairCount": "2130",
      "contextVersion": 3,
      "configurationVersion": 2,
      "scopeHash": { "availability": "AVAILABLE", "algorithm": "SHA_256", "value": "..." }
    },
    "platformChargeMicro": "4260000",
    "billingCurrency": "RUB",
    "blockers": [],
    "executionAllowed": true,
    "expiresAt": "2026-09-01T16:15:00.000Z"
  },
  "meta": { "requestId": "01J..." }
}

3. Подтвердить запуск

POST/projects/{projectId}/rank-runspositions:run
JSON · Тело запросаjson
{
  "estimateId": "<estimateId>",
  "confirmedPlatformChargeMicro": "4260000"
}

Подтверждайте ровно platformChargeMicro из оценки. Для BYOK запуска значение равно "0". Ответ 202 содержит задание, а не готовые позиции.

202 · Ответjson
{
  "data": {
    "id": "<jobId>",
    "type": "MANUAL_RANK_CHECK",
    "provider": "XMLSTOCK",
    "status": "PREPARING",
    "stage": "PREPARING_SCOPE",
    "progress": { "current": "0", "total": "2130", "unit": "KEYWORD" },
    "platformChargeMicro": "4260000",
    "billingCurrency": "RUB",
    "createdAt": "2026-09-01T16:01:00.000Z"
  },
  "meta": { "requestId": "01J..." }
}

4. Получить результат

Запросbash
curl "https://api.seonorita.ru/api/v1/projects/<projectId>/jobs/<jobId>/result?limit=200" \
  -H "Authorization: Bearer $SEO_API_TOKEN"
200 · Сокращённый ответjson
{
  "data": {
    "job": { "id": "<jobId>", "status": "COMPLETED", "stage": "FINISHED" },
    "rows": [
      {
        "sequence": 1,
        "keywordId": "019...",
        "keyword": "купить холодильник",
        "found": true,
        "position": 7,
        "rankingUrl": "https://example.ru/catalog",
        "pollAttempts": 3
      }
    ],
    "page": { "hasNext": true, "nextCursor": "opaque-cursor" }
  },
  "meta": { "requestId": "01J..." }
}

5. Собрать обычную выдачу конкурентов

Используйте тот же контекст, estimate и подтверждение, но передайте purpose: "COMPETITOR_SERP". Провайдер собирает выбранную глубину Топ-10/20/30/50/100: Arsenkin запускает инструмент check-top, XMLStock — соответствующую Yandex/Google SERP-выдачу.

Оценка сбора конкурентовbash
curl -X POST "https://api.seonorita.ru/api/v1/projects/<projectId>/rank-estimates" \
  -H "Authorization: Bearer $SEO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: competitors:estimate:batch-42" \
  -d '{
    "trackingContextId": "<contextId>",
    "purpose": "COMPETITOR_SERP",
    "saveProjectPosition": true,
    "provider": "ARSENKIN",
    "searchSource": "LIVE"
  }'
200 · Отдельный результат выдачи Топ-10json
{
  "data": {
    "execution": { "purpose": "COMPETITOR_SERP", "depth": 30 },
    "rows": [{
      "keyword": "купить холодильник",
      "state": "NOT_FOUND",
      "serpResults": [
        {
          "position": 1,
          "rankingUrl": "https://competitor.example/catalog",
          "title": "Каталог холодильников",
          "snippet": "Описание результата"
        }
      ]
    }]
  }
}