СправочникОбновлено: 2026-11-03

Справочник Site API (seoasist-site-api/1)

Полная спецификация SEOAsist Site API: аутентификация и HMAC-подпись, четыре эндпоинта, типы правил и обзор готовых примеров для Next.js и PHP.

Открыть этот экран в панели

На этой странице описан контракт SEOAsist Site API (спецификация seoasist-site-api/1), который реализует ваш сайт. Вкладка Руководство разработчика → Спецификация в панели и Подсказка по настройке содержат тот же контракт. Пошаговое руководство по подключению см. в статье Подключение самописного сайта с помощью SEOAsist Site API.

Общие правила

  • Все эндпоинты находятся по одному базовому пути, например, https://example.com/api/seoasist.
  • Всегда возвращайте ответ в формате JSON. Ответ не в формате JSON считается ошибкой.
  • Никогда не перенаправляйте запросы (без кодов 30x). SEOAsist не следует по перенаправлениям, поэтому сохраняйте в панели итоговый URL API.
  • В случае ошибки возвращайте 4xx/5xx с {"error":"<короткое сообщение>"}. Это сообщение отображается в панели.
  • Проверяйте входные данные, ограничивайте размер тела запроса (~2 МБ) и логируйте вызовы.
  • SEOAsist отменяет запрос по таймауту через 25 секунд. Запросы используют User-Agent SEOAsist-SiteAPI/1.0 (+https://seoasist.com).
  • URL должен быть публично доступен; SEOAsist никогда не вызывает localhost или адреса private-сетей.

Аутентификация

Каждый запрос содержит три заголовка:

ЗаголовокЗначение
AuthorizationBearer <SEOASIST_SITE_TOKEN>
X-SEOAsist-TimestampUnix timestamp (в секундах)
X-SEOAsist-Signaturesha256=<hex>, где hex = HMAC-SHA256(ключ = токен, сообщение = <timestamp>.<raw body>)
  • Храните токен в переменной окружения SEOASIST_SITE_TOKEN; никогда не прописывайте его жестко в коде. Он генерируется в панели при нажатии Подключить и начинается с sa_.
  • Сравнивайте токен и подпись за постоянное время (constant time).
  • Для GET-запросов сырое тело (raw body) представляет собой пустую строку, поэтому подписываемое сообщение выглядит как <timestamp>..
  • Возвращайте 401 {"error":"unauthorized"}, если подпись неверна или timestamp старше 300 секунд.
const expected = "sha256=" + createHmac("sha256", token).update(`${ts}.${body}`).digest("hex");

GET /manifest

Этот эндпоинт вызывается при проверке подключения. Указывайте только те возможности, которые вы реализовали.

{"spec":"seoasist-site-api/1","platform":"nextjs","name":"My site","capabilities":["rules","content","files"]}

spec должен начинаться с seoasist-site-api/. Распознаваемые возможности (capabilities): rules, content и files; всё остальное игнорируется. В панели они отображаются как SEO-правила, Публикация контента и llms.txt / robots.

Есть еще два необязательных поля:

  • locales: языки, на которых вы можете публиковать контент (ISO 639-1), например, ["az","ru","en","tr"]. SEOAsist отправляет статью на языке, отличном от основного языка сайта, только если этот язык указан здесь. Перед отклонением статьи из-за несоответствия языка манифест считывается еще раз.
  • ruleKinds: объявляет поддержку опциональных типов правил. Единственный опциональный тип на сегодняшний день — link; при "ruleKinds":["link"] SEOAsist отправляет внутренние ссылки в ваш Site API вместо Pixel.
{"spec":"seoasist-site-api/1","platform":"nextjs","name":"My site","capabilities":["rules","content","files"],"locales":["tr","en"],"ruleKinds":["link"]}

PUT /rules (возможность: rules)

Тело запроса: {"rules": Rule[]}. Это полный текущий набор правил; замените всё, что было сохранено ранее. Пустой массив очищает все правила. Сохраняйте правила (в таблице БД или JSON-файле) и применяйте их на стороне сервера при рендеринге, чтобы поисковые роботы видели результат в HTML, а не в клиентском JavaScript.

type Rule = { id: string; kind: string; matchType: "exact" | "prefix" | "regex" | "all"; matchPath: string; payload: object };

Сопоставление использует путь запроса (pathname) без завершающего слэша (/ для главной страницы):

  • exact: путь полностью совпадает
  • prefix: путь начинается с matchPath
  • regex: проверка с помощью JavaScript RegExp
  • all: каждая страница

Если совпадают несколько правил одного типа, побеждает наиболее специфичное: exact > prefix > regex > all.

kindpayloadКак применять
title{"value"}<title>
meta_description{"value"}<meta name="description">
canonical{"href"}<link rel="canonical"> (абсолютный URL)
robots{"content"}<meta name="robots"> (например, index,follow, noindex,follow)
h1{"value","selector"?}Заменить текст главного H1 страницы
og{"title"?,"description"?,"image"?,"type"?}Метатеги og:*
json_ld{"json"}<script type="application/ld+json"> (json — это объект или массив)
hreflang{"items":[{"lang","href"}]}<link rel="alternate" hreflang>
redirect{"to","status"?}HTTP-перенаправление перед рендерингом (по умолчанию 301)
img_alt{"items":[{"match","alt"}]}Установить alt для элементов <img>, чьей src содержит match
lang{"value"}<html lang>
link{"anchor","href"}Внутренняя ссылка: обернуть первое вхождение anchor в основном тексте страницы (не внутри ссылки, заголовка, кода, nav/header/footer) в <a href="href">; ничего не делать, если страница уже ссылается на href. Применяется каждое совпадающее правило link, а не только самое специфичное. Отправляется только если ruleKinds в манифесте содержит link
meta{"name","content"}<meta name="{name}" content="{content}"> в <head>. name используется только как тег подтверждения владения сайтом: msvalidate.01 (Bing), google-site-verification, yandex-verification (обычно matchPath /)

Сохраняйте неизвестные типы и игнорируйте их. Ответ: {"ok":true,"count":<количество сохраненных>}.

SEOAsist отправляет все включенные правила сайта: добавленные на вкладке Pixel, примененные мета-предложения, правила, созданные задачами тарифных планов Autopilot (Otopilot), утвержденные внутренние ссылки и правила, сгенерированные функциями Авто-исправление / Исправить с помощью правил. Подключенный Site API с возможностью rules используется в качестве канала правил сайта.

POST /content (возможность: content)

Тело запроса:

{"externalId":null,"type":"post","title":"…","slug":"…","html":"<h2>…</h2>","excerpt":"…","metaTitle":"…","metaDescription":"…","status":"draft","featuredImageUrl":"https://…","tags":["…"],"updateUrl":null,"locale":"tr","translationOf":null}
  • Указан externalId: обновить этот элемент.
  • Указан updateUrl (type: "page"): обновить существующую страницу по этому URL (ее основной контент, заголовок и метаданные).
  • В противном случае: создать новую статью в блоге, используя существующую систему контента сайта (DB/CMS/MDX) и ее стандартный шаблон URL.
  • status: "draft" не должен быть публично виден.
  • html — это доверенный, уже отформатированный HTML статьи (заголовки, списки, таблицы, FAQ). Сохраняйте дизайн и верстку сайта.
  • tags содержит не более 5 тегов.
  • locale: язык текста (ISO 639-1, например, az, tr). На мультиязычном сайте публикуйте статью под собственным URL этого языка (языковой префикс / маршрут), никогда не под другим языком.
  • translationOf: если статья является переводом, это id, который вы вернули ранее для оригинальной статьи. Сохраните её как языковую версию этой статьи (переключатель языков должен открывать её, а не ошибку 404) и свяжите версии с помощью <link rel="alternate" hreflang> на каждой из них. Оригинал всегда отправляется первым; когда владелец повторно публикует материал, каждая версия отправляется снова со своим собственным externalId.
  • featuredImageUrl: абсолютный URL изображения статьи, одинаковый для каждой языковой версии. При создании и при каждом обновлении, если он отличается от сохраненного, скачайте его и замените изображение статьи (URL может не иметь расширения файла; используйте Content-Type из ответа).
  • Для статей в блоге html может содержать структурированные данные статьи (например, BlogPosting и FAQPage) в конце в виде <script type="application/ld+json">. Не удаляйте их; публикуйте на странице как есть.

Ответ: {"id":"<постоянный id>","url":"<абсолютный публичный URL>","status":"draft"|"publish"}. SEOAsist сохраняет id и отправляет его обратно в качестве externalId при повторной отправке того же элемента. Если статья блога без externalId совпадает со статьей, опубликованной ранее на том же сайте с тем же slug и языком, SEOAsist использует id этой статьи, чтобы на сайте не открывалась вторая копия.

PUT /files (возможность: files)

Тело запроса: {"path":"llms.txt"|"robots-ai.txt","content":string}

  • llms.txt: отдавайте его по адресу /llms.txt как text/plain (заменяя предыдущий).
  • robots-ai.txt: блок правил для ИИ-краулеров. Отдавайте /robots.txt с собственными правилами сайта плюс добавленный этот блок (заменяя предыдущий блок).

Ответ: {"ok":true,"url":"<публичный url>"}.

Готовые примеры

Диалоговое окно Руководство разработчика содержит код для копирования и вставки:

ВкладкаСодержимое
Next.jslib/seoasist.ts (хранилище на базе JSON-файла и seoRules(pathname), выбирающая наиболее специфичное правило для каждого типа), app/api/seoasist/[...path]/route.ts (четыре эндпоинта с проверкой HMAC) и пример использования, который применяет правила в generateMetadata и отдаёт /llms.txt.
PHPseoasist-api.php: правило перенаправления .htaccess для /api/seoasist/*, хранилище data/seoasist.json и проверки подписи с помощью hash_hmac.
ТестПодписанная команда curl для /manifest.

Эндпоинт /content в примерах представляет собой заглушку (TODO); вам необходимо сохранить статью в свой собственный блог/CMS и вернуть ее реальный URL.

Тестовая команда:

TOKEN="<SEOASIST_SITE_TOKEN>"
TS=$(date +%s)
SIG=$(printf "%s." "$TS" | openssl dgst -sha256 -hmac "$TOKEN" | sed 's/^.* //')
curl -s "https://example.com/api/seoasist/manifest" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-SEOAsist-Timestamp: $TS" \
  -H "X-SEOAsist-Signature: sha256=$SIG"
tip

Apache может не передавать заголовок Authorization в PHP. В таком случае добавьте SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 в .htaccess.

Сообщения об ошибках, отображаемые в панели

СообщениеЗначение
token rejectedСайт ответил 401/403 без поля error в теле ответа.
endpoint not found (is the Site API installed at this URL?)404; неверный URL или API не установлен.
redirect to … (use the final API URL)Сайт вернул перенаправление.
non-JSON responseОтвет был не в формате JSON.
timeout / unreachable: …Нет ответа в течение 25 секунд или сбой подключения.
unexpected manifest (spec "…")/manifest не вернул валидный spec.

Если ваш сайт возвращает {"error":"…"} в теле ответа, панель отображает это сообщение как есть. Решения проблем см. в статье Проблемы с подключением Site API.

Была ли эта статья полезной?
Не нашли нужное?
Опишите проблему, и наша команда ответит по e-mail.
Связаться с нами