Підключіть будь-який сайт до Seonix
Реалізуйте один REST-ендпоінт у своєму сайті — Seonix публікуватиме згенеровані статті напряму на нього: оновлення, завантаження медіа та опційне видалення з коробки. Працює з будь-яким стеком: Node, Python, PHP, Go, Rails чи генератор статичних сайтів.
Як це працює
Seonix — клієнт. Ваш сайт надає ендпоінт. Ви генеруєте, редагуєте й оцінюєте статті в Seonix, тиснете Publish — Seonix надсилає статтю на ваш ендпоінт із Bearer-токеном. Повторні публікації використовують той самий external_id, тому дублікатів не буде.
1. Реалізуйте ендпоінт
Приймайте JSON POST, перевіряйте Bearer-токен проти власного секрету та робіть upsert за external_id. Достатньо кількох рядків у будь-якому фреймворку — див. приклади клієнта нижче.
2. Підключіть канал у Seonix
У Channels проєкту додайте Custom API канал із URL ендпоінта і токеном. Seonix перевіряє з'єднання при збереженні, потім надсилає кожну статтю і зберігає id, який ви повернули.
3. Оновлення та видалення синхронні
Кожна повторна публікація — той самий POST із тим же external_id, upsert на вашому боці. Якщо налаштуєте delete URL template, видалення статті в Seonix викличе DELETE з id, який повернув ваш ендпоінт.
Налаштування підключення
Для підключення обов'язкові два поля — URL ендпоінта і токен. Додайте також media upload URL: саме він тримає ваші зображення на вашому хості, а не лишає опубліковані сторінки з посиланнями на Seonix (див. Медіа). Вставити й зберегти їх можна у вкладці Channels всередині Seonix, не виходячи з додатку.
- 1
Оберіть спільний секрет
Згенеруйте довгий випадковий рядок (32+ символи). Це Bearer-токен, який Seonix надсилає в кожному запиті. Тримайте його на сервері; не зашивайте у клієнтський код.
- 2
Реалізуйте POST /your-endpoint
Перевіряйте заголовок Authorization проти вашого секрету, робіть upsert статті за external_id та повертайте { "id": "…", "url": "…" }. У разі помилки відповідайте 4xx/5xx із JSON-тілом.
- 3
Реалізуйте ендпоінт завантаження медіа
Приймайте multipart POST із полем `file` і повертайте { "url": "…" }. Обов'язково для продакшену — саме це кладе зображення на ваш хост, а не лишає сторінки з посиланнями на Seonix. Хешуйте байти та зберігайте за контент-адресою, повертаючи вже наявний URL для відомих байтів: те саме зображення надсилається повторно під час правок і переопублікацій, і саме контент-адресація зупиняє дублікати.
- 4
(Опційно) Реалізуйте DELETE /your-endpoint/:id
Якщо хочете, щоб статті зникали з сайту при видаленні в Seonix, обробляйте DELETE з тим самим Bearer-токеном. Повертайте 200 у разі успіху; 404 ми трактуємо як вже видалений запис.
- 5
Додайте канал у Seonix
Відкрийте Channels у проєкті → Custom API → Connect. Вставте URL ендпоінта і токен, опційно — delete URL template, media upload URL, локаль та автора. Seonix перевіряє з'єднання одразу після збереження.
- 6
Публікуйте з редактора
Відкрийте статтю, натисніть Publish, оберіть свій Custom API канал у списку — і тисніть Publish now. Seonix збереже повернутий id, щоб усі подальші оновлення й видалення йшли в той самий запис.
Конфіг каналу
Канал Custom API зберігає URL ендпоінта, bearer-токен і опційні поля нижче. Секрети залишаються всередині проєкту Seonix — їх читають лише для побудови вихідних запитів. Мапа `headers` — розширена опція, що задається через API каналу; решту покриває форма в дашборді.
{
"api_url": "https://your-site.example/api/articles",
"api_token": "YOUR_SHARED_SECRET",
"delete_url_template": "https://your-site.example/api/articles/{id}",
"media_upload_url": "https://your-site.example/api/media",
"lang": "en",
"author": "Your team",
"headers": { "X-Custom": "advanced, via channel API" }
}Усі поля конфіга зберігаються всередині проєкту Seonix, доступні лише для серверної частини Seonix і ніколи не залишають движок. Змінити конфіг можна в будь-який момент через ту саму модалку Channels → Custom API → Manage.
Автентифікація
Оберіть будь-який bearer-токен — це спільний секрет між вашим сайтом і Seonix. Seonix надсилає його в заголовку Authorization кожного запиту: публікації, завантаження медіа, видалення та верифікаційні проби. Ротація — просто оновіть конфіг каналу, рестарт не потрібен жодній стороні.
- Authorization:Bearer <your shared secret>
- X-Seonix-Contract: 1
Порівнюйте токен за константний час (hash_equals / timingSafeEqual / hmac.compare_digest — див. приклади нижче) і тримайте його лише на сервері. X-Seonix-Contract — версія контракту: вона зміниться лише при breaking-змінах, нові опційні поля її не піднімають.
Перевірка з'єднання
При збереженні каналу Seonix надсилає пробний запит, щоб неправильний URL чи токен спливли одразу, а не на першій публікації. Проба — звичайний POST із порожнім JSON-об'єктом і заголовком X-Seonix-Verify: 1. Не створюйте для неї запис: відхилити порожній payload з 400 — очікувана відповідь.
/ваш-ендпоінтПроба з'єднання: порожній JSON + X-Seonix-Verify: 1.
POST https://your-site.example/api/articles
Authorization: Bearer YOUR_SHARED_SECRET
X-Seonix-Verify: 1
X-Seonix-Contract: 1
Content-Type: application/json
{}
# How Seonix reads your answer:
# 401 / 403 -> token rejected, channel save fails
# 404 -> endpoint not found, channel save fails
# non-JSON content -> wrong URL (a marketing page?), save fails
# 2xx or 4xx with JSON -> connection verifiedПублікація статті
Seonix надсилає JSON POST на ваш налаштований URL і для створення, і для оновлення. external_id — стабільний id статті всередині Seonix (UUID), він не змінюється між публікаціями. Робіть upsert за ним — повторне надсилання того ж id оновлює існуючий запис замість створення дубліката.
/ваш-ендпоінтСтворення або оновлення (upsert).
POST https://your-site.example/api/articles
Authorization: Bearer YOUR_SHARED_SECRET
X-Seonix-Contract: 1
Content-Type: application/json
{
"external_id": "9b2f6e0a-4b1d-4c3a-9a56-170b63f6d2c1",
"translation_key": "c1d2e3f4-…",
"slug": "how-to-automate-seo-content",
"lang": "en",
"title": "How to automate SEO content in 2026",
"excerpt": "Short summary shown on list pages and meta tags.",
"content_html": "<h2 id=\"intro\">Intro</h2><p>Body copy…</p>",
"category": "Automation",
"key_takeaways": ["Point one", "Point two"],
"key_takeaways_title": "Key takeaways",
"author": "Your team",
"cover_url": "https://your-site.example/media/abc.webp",
"cover_alt": "Dashboard with rising organic traffic",
"og_image": "https://your-site.example/media/abc.webp",
"seo_description": "Short meta description.",
"published_at": "2026-04-16T09:00:00Z",
"schema_jsonld": "{\"@context\":\"https://schema.org\",\"@graph\":[…]}"
}HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "42",
"url": "https://your-site.example/blog/how-to-automate-seo-content"
}Оновлення — це той самий POST з тим же external_id. Опційні поля, порожні в Seonix, у payload не потрапляють — збережені значення для них залишайте як є.
# Updates reuse the same POST with the same external_id —
# your endpoint should upsert on it. Optional fields that are
# empty in Seonix are omitted from the payload.
POST https://your-site.example/api/articles
Authorization: Bearer YOUR_SHARED_SECRET
{
"external_id": "9b2f6e0a-4b1d-4c3a-9a56-170b63f6d2c1",
"slug": "how-to-automate-seo-content",
"lang": "en",
"title": "How to automate SEO content in 2026 (refined)",
"excerpt": "Updated summary.",
"content_html": "<p>Updated body…</p>"
}Медіа: зберігайте зображення в себе
Кожне зображення має опинитися на вашій інфраструктурі. Seonix — не CDN: опублікована сторінка не повинна залишатися з посиланням на URL Seonix. Налаштуйте media upload URL — і Seonix надсилатиме кожне зображення одразу, щойно його додали в редакторі: multipart/form-data, поле `file`, той самий Bearer-токен. Поверніть URL, який ви призначили (root-relative теж підходить — він розгортається відносно origin вашого ендпоінта), і до моменту публікації кожен img src та обкладинка вже вказують на ваш хост. Дедуплікуйте за вмістом: захешуйте байти, зберігайте файл під цим хешем і повертайте вже наявний URL, коли хеш відомий — Seonix іменує файли за контент-хешем і надсилає те саме зображення повторно під час правок, рефайнменту та переопублікацій, тож саме контент-адресація лишає одну копію замість нового запису на кожну публікацію. Без media upload URL у content_html і cover_url будуть тимчасові URL доставки Seonix: завантажте їх і перехостіть у себе перед рендером. Це механізм передавання, а не гарантія хостингу.
/ваш-медіа-ендпоінтmultipart/form-data, поле `file`. Той самий Bearer-токен.
POST https://your-site.example/api/media
Authorization: Bearer YOUR_SHARED_SECRET
Content-Type: multipart/form-data; boundary=…
--…
Content-Disposition: form-data; name="file"; filename="cover.webp"
Content-Type: image/webp
<binary image bytes>
--…--
# Expected response — absolute or root-relative URL:
HTTP/1.1 200 OK
Content-Type: application/json
{ "url": "https://your-site.example/media/ab12cd.webp" }Приймайте зображення (jpeg/png/webp/gif) розміром щонайменше до 12 МБ. Дедуплікуйте за вмістом: візьміть SHA-256 від байтів, зберігайте файл під цим хешем і повертайте вже наявний URL, коли хеш відомий. Seonix надсилає те саме зображення повторно під час правок, рефайнменту та переопублікацій — саме контент-адресація лишає одну копію в медіатеці замість нового запису на кожну публікацію.
Видалення статті
Налаштуйте delete_url_template у каналі — Seonix підставить в {id} той id, який ваш ендпоінт повернув при публікації (або external_id статті, якщо ви його не повернули), і зробить DELETE із тим же Bearer-токеном. Пропустіть template, щоб ігнорувати видалення; 404 трактується як вже видалений запис.
/ваш-ендпоінт/:idВидалення статті. Використовується той самий Bearer-токен.
# {id} in delete_url_template is substituted with the id your
# endpoint returned at publish time ("42" in the example above);
# if you returned none, the article's external_id is used instead.
DELETE https://your-site.example/api/articles/42
Authorization: Bearer YOUR_SHARED_SECRETПоля payload
Саме таку форму надсилає Seonix — поля, позначені як опційні, пропускаються, коли порожні. Мапте їх на свою схему на сервері та ігноруйте непотрібне. Вважайте content_html недовіреним вводом і санітизуйте власним allowlist перед рендером.
| Поле | Тип | Опис |
|---|---|---|
| external_id | string | Стабільний UUID статті в Seonix — ключ upsert. Присутній завжди і не змінюється між публікаціями. |
| translation_key | string? | Спільний ключ мовних версій однієї статті. Надсилається, коли стаття має переклади, — використовуйте для крос-лінків між локалями. |
| slug | string | Малими літерами, через дефіс (^[a-z0-9]+(?:-[a-z0-9]+)*$). Seonix санітизує його перед надсиланням. Однаковий slug у різних локалях вирівнює URL-адреси. |
| lang | string | ISO-639-1 код мови статті: "en", "ua", "de", "fr", … Seonix підтримує 50+ мов, тож не обмежуйте валідацію двома значеннями. Українська нормалізується uk → ua. |
| title | string | Заголовок статті. Значення за замовчуванням для <h1> та <title>. |
| excerpt | string | Короткий опис для сторінок списків і запасний варіант meta description. Присутній завжди, але може бути порожнім рядком — майте власний фолбек. |
| content_html | string | HTML-тіло статті (заголовки h2/h3, абзаци, списки, таблиці, зображення, код). Вважайте недовіреним і санітизуйте на своєму боці — але лишіть у allowlist <img>, <figure>, <figcaption> та атрибути src, alt, width, height, loading: інакше зображення зникнуть, а сторінку смикатиме (CLS). |
| category | string? | Довільний рядок — категорія статті так, як вона названа у проєкті Seonix. Фіксованого словника немає; мапте на свою таксономію. |
| key_takeaways | string[]? | Маркований список для блоку-резюме вгорі сторінки статті. 4–6 самодостатніх речень, впорядкованих за корисністю (перше — пряма відповідь на запит). Див. примітку та розмітку під таблицею. |
| key_takeaways_title | string? | Заголовок блоку key takeaways мовою статті — рендерте разом зі списком, щоб не потрібен був власний переклад. |
| author | string | Автор. За замовчуванням 'Seonix' або значення з конфіга каналу. |
| cover_url | string? | Абсолютний URL обкладинки 16/9. З налаштованим media upload URL він уже вказує на ваш хост. Без нього це тимчасовий URL доставки Seonix — завантажте файл і перехостіть у себе, не рендерте його напряму. |
| cover_alt | string? | Alt-текст обкладинки — використовуйте для <img alt> та og:image:alt. |
| og_image | string? | Зображення Open Graph. Наразі збігається з cover_url. |
| seo_description | string? | Meta description статті. |
| published_at | ISO 8601? | Дата першої публікації (RFC 3339). Не змінюється при оновленнях — використовуйте як канонічну позначку часу і не «омолоджуйте» статтю. |
| schema_jsonld | string? | Серіалізований schema.org @graph статті (Article, WebPage, BreadcrumbList, FAQPage, HowTo, …), згенерований з контенту. Рендерте у <script type="application/ld+json"> — див. примітку під таблицею. |
Про key_takeaways: рендерте блок як звичайні заголовок + список НАД тілом статті — саме цю форму пошуковики підіймають у list-сніпети, а AI-асистенти цитують дослівно. key_takeaways_title використовуйте як заголовок без змін (він уже мовою статті); якщо він порожній — покажіть список без заголовка. Елементи — чистий текст без HTML: екрануйте їх і зберігайте порядок (він за корисністю, не за позицією в тексті). Якщо масив відсутній або порожній — сховайте блок повністю. Дублювання не буде: коли key_takeaways присутній, content_html не містить власної секції takeaways — Seonix прибирає її під час публікації, структуроване поле є єдиним джерелом.
<!-- Recommended markup — a plain heading + list ABOVE the body. -->
<!-- This exact shape is what search engines lift into list snippets -->
<!-- and what AI assistants (ChatGPT, Perplexity, AI Overviews) quote. -->
<section class="key-takeaways">
<h2>{key_takeaways_title}</h2> <!-- already in the article's language -->
<ul>
<li>{key_takeaways[0]}</li> <!-- plain text: HTML-escape each item -->
<li>{key_takeaways[1]}</li>
…
</ul>
</section>
{content_html}Про schema_jsonld: @graph генерується до того, як стане відомий фінальний URL сторінки, тому URL-залежні вузли (Article, WebPage, BreadcrumbList) розраховані від домену проєкту. Якщо шлях ваших статей інший (наприклад /blog/…), рендерте з графа лише доповнювальні типи — FAQPage / HowTo — поруч із власними Article та BreadcrumbList, перезаписавши їхній @id на реальний URL сторінки. Саме так робить блог Seonix. Дублювати Article двома графами не варто: конкурентні графи пошуковики ігнорують.
Очікувана відповідь
У відповіді поверніть JSON із id запису та публічним URL сторінки. Seonix зберігає цей id і використовує його для видалення; оновлення в будь-якому разі йдуть за тим самим external_id. Обгортки { "external_id": … } та { "data": { … } } теж приймаються; все інше у відповіді ігнорується.
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "42",
"url": "https://your-site.example/blog/how-to-automate-seo-content"
}Помилки й повтори
Seonix чекає до 30 секунд на запит і трактує вашу відповідь так, як описано нижче. Невдалі публікації повторюються до 3 разів (через 15 хвилин, 45 хвилин і 2 години), після чого публікація позначається failed і оператор отримує сповіщення. JSON-тіло помилки з коротким людським повідомленням показується оператору як є — зробіть його корисним.
| Ваша відповідь | Як трактує Seonix |
|---|---|
| 2xx + JSON | Успіх. Зчитуються id та url; решта ігнорується. |
| 404 | Запис не знайдено. На повторній публікації Seonix створить свіжу публікацію; для DELETE це «вже видалено». |
| інший 4xx / 5xx / таймаут | Помилка публікації: до 3 повторів через 15 хв → 45 хв → 2 год, далі failed + сповіщення оператору. message з JSON-тіла показується оператору. |
| не-JSON відповідь | Помилка конфігурації — api_url, схоже, вказує на звичайну сторінку, а не на API. Верифікація каналу це також ловить. |
Формат тіла помилки: { "error": { "code": "VALIDATION", "message": "…" } }. Порожнє чи довільне тіло теж прийнятне — тоді оператор побачить лише HTTP-статус.
Ліміти й гарантії
На що ваш ендпоінт може розраховувати і до чого має бути готовим.
- •Таймаут запиту — 30 секунд; відповідайте швидко і виносьте повільну роботу у фон.
- •Тіла статей зазвичай десятки–сотні КБ; приймайте JSON щонайменше до 5 МБ, щоб мати запас.
- •Робіть upsert атомарним та ідемпотентним: повтори й позачергові доставки можливі, тож той самий payload може прийти двічі.
- •Вважайте пару (lang, slug) унікальною на своєму боці; конфлікт зі старим записом розв'язуйте на користь свіжого external_id.
- •Транспортна безпека — HTTPS + статичний Bearer-токен. Підпису тіла немає, тож тримайте секрет довгим і ротуйте його через конфіг каналу.
- •Контракт версіонується заголовком X-Seonix-Contract (зараз 1): нові опційні поля можуть з'являтися без зміни версії — ігноруйте незнайомі поля.
Приклади клієнта
Мінімальні приймачі, які можна вставити в будь-який бекенд. Вони валідують bearer-токен за константний час, роблять upsert статті та повертають відповідь, яку очікує Seonix.
# Minimal receiver test — simulate what Seonix sends you
curl -X POST "$YOUR_ENDPOINT" \
-H "Authorization: Bearer $YOUR_SHARED_SECRET" \
-H "Content-Type: application/json" \
-d '{
"external_id": "9b2f6e0a-4b1d-4c3a-9a56-170b63f6d2c1",
"slug": "how-to-automate-seo-content",
"lang": "en",
"title": "How to automate SEO content in 2026",
"excerpt": "Short summary.",
"content_html": "<p>Body…</p>",
"category": "Automation",
"published_at": "2026-04-16T09:00:00Z"
}'Готові підключитися?
Створіть проєкт у Seonix, додайте канал блогу й опублікуйте першу статтю за десять хвилин. Один токен відкриває write, медіа і delete.
Почати безкоштовно →