Документація API VibeCode
REST API для публікації двомовних постів, завантаження медіа, коментарів, пошуку та аналітики.
Зміст
- Автентифікація
- Конвенції постів
- Пости
- Теги
- Медіа
- Коментарі
- Пошук
- Аналітика
- SEO та фіди
- Коди помилок
- Кешування та ліміти
Автентифікація
API підтримує два способи автентифікації:
- API ключ — для програмного доступу до v1-ендпоінтів. Передавайте у заголовку:
Authorization: Bearer vc_your_api_key_hereСтворити ключ можна в адмін-панелі. Ключ показується лише раз при створенні. Префікс — vc_, далі 64 hex-символи.
- Сесія через cookie — для дій від імені залогіненого користувача (коментарі, адмін-аналітика). Видається після входу через /api/auth/sign-in.
Конвенції постів
- Сайт двомовний: локалі uk та en. Один пост може мати обидві мовні версії, об'єднані спільним translationId.
- slug спільний для обох мов. URL формуються як /uk/blog/{slug} та /en/blog/{slug}.
content— Markdown (не HTML).- При створенні поста має бути задана щонайменше одна локаль (uk або en); другу можна додати пізніше через адмінку.
- Поле tags приймає рядки (slug існуючого тега) або об'єкти {slug, nameUk?, nameEn?} — відсутні теги створяться автоматично.
Пости
GET /api/v1/posts
Список опублікованих постів з пагінацією. Авторизація не потрібна.
Параметри запиту
| Параметр | Тип | За замовч. | Опис |
|---|---|---|---|
locale | uk | en | "uk" | Мова постів |
page | number | 1 | Номер сторінки (≥ 1) |
limit | number | 10 | 1–50 |
Приклад
curl https://www.vaibecod.com/api/v1/posts?locale=uk&page=1&limit=5Відповідь (200)
{
"posts": [
{
"id": "abc123",
"slug": "my-post",
"locale": "uk",
"title": "Мій пост",
"excerpt": "Короткий опис…",
"coverImage": "/api/media/9f3…",
"published": true,
"publishedAt": "2026-04-15T10:00:00.000Z",
"viewCount": 42,
"authorName": "Admin",
"createdAt": "2026-04-15T10:00:00.000Z"
}
],
"pagination": { "page": 1, "limit": 5, "total": 12, "totalPages": 3 }
}POST /api/v1/posts
Створити пост. Можна одразу обома мовами. Потребує API ключ.
Тіло запиту (JSON)
| Поле | Тип | Обов'язкове | Опис |
|---|---|---|---|
slug | string | так | URL-slug, 1–200 символів. Спільний для обох мов. |
uk | { title, excerpt?, content } | одна з uk/en | Українська версія (Markdown у content). |
en | { title, excerpt?, content } | одна з uk/en | Англійська версія (Markdown у content). |
coverImage | string | ні | URL обкладинки (зазвичай /api/media/{id}). |
published | boolean | ні | За замовч. false (чернетка). |
publishedAt | string (ISO 8601) | ні | Дата публікації, можна заднім числом. |
tags | (string | { slug, nameUk?, nameEn? })[] | ні | Slug існуючого тега або об'єкт для створення нового. |
Приклад: пост одразу двома мовами
curl -X POST https://www.vaibecod.com/api/v1/posts \
-H "Authorization: Bearer vc_your_key" \
-H "Content-Type: application/json" \
-d '{
"slug": "getting-started-ai-coding",
"uk": {
"title": "Початок роботи з AI-кодингом",
"excerpt": "Гайд по AI-розробці",
"content": "## Вступ\n\nAI змінює спосіб писати код…"
},
"en": {
"title": "Getting Started with AI Coding",
"excerpt": "A guide to AI-assisted development",
"content": "## Introduction\n\nAI is changing how we code…"
},
"coverImage": "/api/media/9f3a…",
"published": true,
"publishedAt": "2026-04-15T12:00:00Z",
"tags": ["ai", { "slug": "next-js", "nameUk": "Next.js", "nameEn": "Next.js" }]
}'Відповідь (201)
{
"translationId": "tr_8b2…",
"slug": "getting-started-ai-coding",
"published": true,
"posts": [
{ "id": "abc-uk", "slug": "getting-started-ai-coding", "locale": "uk", "url": "/uk/blog/getting-started-ai-coding" },
{ "id": "abc-en", "slug": "getting-started-ai-coding", "locale": "en", "url": "/en/blog/getting-started-ai-coding" }
]
}Після створення інвалідуються кеші: /uk, /en, /uk/blog, /en/blog, /sitemap.xml.
Теги
GET /api/v1/tags
Усі теги. Без авторизації.
curl https://www.vaibecod.com/api/v1/tags{
"tags": [
{ "id": 1, "slug": "react", "nameUk": "React", "nameEn": "React" },
{ "id": 2, "slug": "ai", "nameUk": "AI", "nameEn": "AI" }
]
}POST /api/v1/posts/tags
Додати теги до існуючого поста за slug (одразу до всіх його мовних версій). Потребує API ключ.
curl -X POST https://www.vaibecod.com/api/v1/posts/tags \
-H "Authorization: Bearer vc_your_key" \
-H "Content-Type: application/json" \
-d '{
"slug": "getting-started-ai-coding",
"tags": [
{ "slug": "tutorial", "nameUk": "Туторіал", "nameEn": "Tutorial" },
{ "slug": "ai" }
]
}'{ "success": true, "added": 2, "posts": 2 }Медіа
Файли зберігаються як BLOB у БД. Завантажений файл доступний за URL /api/media/{id} і дедуплікується за розміром та MIME-типом.
POST /api/upload (публічний)
Публічне завантаження зображень з фронтенду. Без авторизації.
| Параметр | Значення |
|---|---|
| Формат | multipart/form-data, поле file |
| Дозволені типи | image/jpeg, image/png, image/webp, image/gif, image/avif |
| Макс. розмір | 10 MB |
curl -X POST https://www.vaibecod.com/api/upload -F "file=@photo.jpg"{ "url": "/api/media/9f3a…" }POST /api/v1/upload (з API ключем)
Завантаження зображень та відео для програмного використання. Потребує API ключ.
| Тип | Формати | Макс. розмір |
|---|---|---|
| Зображення | JPEG, PNG, WebP, GIF, AVIF | 50 MB |
| Відео | MP4, WebM, OGG | 50 MB |
curl -X POST https://www.vaibecod.com/api/v1/upload \
-H "Authorization: Bearer vc_your_key" \
-F "file=@video.mp4"{
"url": "/api/media/4d8c…",
"type": "video",
"size": 8421376,
"deduplicated": false
}Якщо такий файл (за розміром і MIME) уже є — повертається статус 200 з тим самим URL і deduplicated: true.
GET /api/media/{id}
Віддає завантажений файл з заголовком Cache-Control: public, max-age=31536000, immutable.
GET /api/media/{id}/thumbnail
Для відео повертає SVG-плейсхолдер 640×360 з кнопкою play. Реальний кадр не витягується (немає ffmpeg).
Коментарі
GET /api/comments?postId={id}
Видимі коментарі до поста (без прихованих модератором), у порядку від нових до старих.
curl "https://www.vaibecod.com/api/comments?postId=abc123"[
{
"id": "c_1",
"content": "Дякую за статтю!",
"parentId": null,
"createdAt": "2026-04-20T08:30:00.000Z",
"hidden": false,
"authorId": "u_1",
"authorName": "Ivan",
"authorImage": "/api/media/…"
}
]POST /api/comments
Створити коментар. Потрібна сесія (cookie після входу).
| Поле | Тип | Обов'язкове | Опис |
|---|---|---|---|
postId | string | так | ID поста |
content | string | так | 1–5000 символів |
parentId | string | ні | ID батьківського коментаря (для відповідей) |
{ "id": "c_42", "success": true }PATCH /api/comments
Редагувати власний коментар (поле content) або приховати/показати (admin, поле hidden). Поля взаємовиключні.
{ "id": "c_42", "content": "оновлений текст" }DELETE /api/comments
Видалити коментар. Дозволено власнику або адміну.
{ "id": "c_42" }Пошук
GET /api/search
Повнотекстовий пошук по постах. Без авторизації.
| Параметр | Тип | Обов'язкове | Опис |
|---|---|---|---|
q | string | так | Запит, 2–100 символів |
locale | uk | en | ні | За замовч. uk |
curl "https://www.vaibecod.com/api/search?q=next.js&locale=uk"Аналітика
POST /api/track
Клієнтський трекінг подій: перегляди сторінок, кліки, тривалість сесії. Без авторизації, з автодетектом ботів за User-Agent.
Тіло запиту залежить від поля type:
// pageview
{ "type": "pageview", "path": "/uk/blog/x", "sessionId": "uuid", "referrer": "https://google.com/", "utmSource": "google" }
// click
{ "type": "click", "sessionId": "uuid", "path": "/uk/blog/x", "element": "a.cta", "href": "https://...", "x": 100, "y": 200 }
// duration (мс)
{ "type": "duration", "sessionId": "uuid", "path": "/uk/blog/x", "duration": 45000 }Усі типи повертають { ok: true } (200).
SEO та фіди
| Шлях | Опис | Кеш |
|---|---|---|
| /sitemap.xml | Повний sitemap з hreflang-альтернативами uk/en | 1h |
| /news-sitemap.xml | Google News sitemap (останні 48 постів) | 10m |
| /robots.txt | Директиви для пошукових і AI-ботів | — |
| /llms.txt | Список постів у форматі для LLM (markdown зі ссилками) | 24h |
| /llms-full.txt | Останні 50 постів повним текстом (markdown) | 24h |
Коди помилок
| Код | Опис |
|---|---|
| 400 | Невалідні дані запиту (часто з полем details від Zod) |
| 401 | Немає або невалідний API ключ / сесія |
| 403 | Недостатньо прав (наприклад, не admin) |
| 404 | Ресурс не знайдено |
| 500 | Внутрішня помилка сервера |
Формат помилки:
{ "error": "Validation failed", "details": [ /* Zod issues */ ] }Кешування та ліміти
- Жорсткого rate-limit на API наразі немає. Просимо не перевищувати 60 запитів на хвилину.
- /api/media/{id} і /api/media/{id}/thumbnail — immutable, кеш 1 рік.
- Створення/оновлення поста інвалідує кеші /uk, /en, /uk/blog, /en/blog, /sitemap.xml.