Документация
API и MCP
Всё, что доступно в панели, можно сделать программно: через REST API
api.tuqo.ru
и через MCP-сервер для нейросетей
mcp.tuqo.ru.
Любая внешняя ИИ-модель может создавать сайты, деплоить и настраивать домены —
авторизация по одному ключу проекта.
Быстрый старт
- 1
Создайте проект в панели и получите ключ на вкладке API-ключи. Ключ формата
tqk_…показывается один раз. - 2
Подключите Tuqo как MCP-коннектор в нейросети — или работайте напрямую через REST.
- 3
Создайте сайт, загрузите архив исходников — он соберётся автоматически и опубликуется на
<поддомен>.tuqo.ru.
API-ключ проекта
Все запросы авторизуются заголовком
Authorization: Bearer tqk_….
Ключ привязан к конкретному проекту — операции скоупятся только в его пределах.
В базе хранится лишь argon2-хеш ключа и публичный префикс для отображения; сам ключ
восстановить нельзя — при потере выпустите новый.
Уровни доступа
-
readтолько чтение: списки и статусы -
editorсоздавать сайты, деплоить, привязывать домены, откатывать — без удаления -
fullполный доступ, включая удаление сайтов и доменов
MCP для нейросетей
Tuqo поднимает MCP-сервер (JSON-RPC 2.0) по адресу
https://mcp.tuqo.ru/mcp.
Подключите его как коннектор в вашей ИИ-модели — и агент управляет деплоем на естественном языке.
Подключение
URL и заголовок авторизации (для MCP-клиентов с HTTP-транспортом и поддержкой заголовков):
{
"mcpServers": {
"tuqo": {
"url": "https://mcp.tuqo.ru/mcp",
"headers": { "Authorization": "Bearer tqk_xxx_yyy" }
}
}
} Инструменты
-
whoami(—)project_id, название проекта и доступные scopes — ориентир в начале сессии
-
list_sites(—)список сайтов проекта (каждый сайт содержит url и form_endpoint)
-
create_site(name, subdomain)создать сайт (поддомен ≥9 символов на бесплатном тарифе)
-
get_site(site_id)получить сайт (в ответе url и form_endpoint для форм)
-
update_site(site_id, name)переименовать сайт
-
delete_site(site_id, confirm)мягко удалить сайт (корзина 24 ч)
-
restore_site(site_id)вернуть сайт из корзины
-
list_trashed(—)сайты в корзине
-
set_site_enabled(site_id, enabled)включить/выключить раздачу сайта
-
deploy_files(site_id, files)выложить файлы как есть (рекомендуется для статики) — публикуется мгновенно
-
deploy_site(site_id, source_base64)загрузить tar.gz исходников (base64) и запустить сборку
-
get_manifest(site_id)файлы активного деплоя {path, sha256} — для правки без перезаливки медиа
-
get_deploy_status(deploy_id)статус сборки: queued → building → ready → active / failed
-
list_deploys(site_id)история деплоев сайта
-
get_logs(deploy_id)логи сборки
-
activate_deploy(deploy_id)сделать готовый деплой боевым (так же откат на прошлую версию)
-
set_custom_domain(site_id, domain)привязать домен — в ответе TXT-запись _tuqo-verify
-
verify_domain(domain_id)подтвердить владение доменом после TXT + диагностика A-записи (a_record)
-
list_domains(site_id)кастомные домены сайта
-
delete_domain(domain_id, confirm)отвязать домен
-
get_forms_overview(—)сводка по формам: квота заявок, использовано, баланс, сайты, счётчики
-
get_form_submissions(site_id?, status?, limit?, offset?)заявки (лиды) с форм проекта
Пример запроса вручную (JSON-RPC tools/call):
curl -X POST https://mcp.tuqo.ru/mcp \
-H "Authorization: Bearer tqk_xxx_yyy" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {
"name": "create_site",
"arguments": { "name": "Лендинг", "subdomain": "myproject" }
}
}' REST API
Базовый адрес — https://api.tuqo.ru.
Тело и ответы — JSON (кроме загрузки деплоя: там тело — бинарный
tar.gz).
- GET
/api/v1/whoami/проверить ключ: project_id, имя, scopesread - GET
/api/v1/sites/список сайтовread - POST
/api/v1/sites/создать сайтeditor - GET
/api/v1/sites/{id}получить сайтread - PATCH
/api/v1/sites/{id}переименовать сайтeditor - DELETE
/api/v1/sites/{id}удалить сайтfull - POST
/api/v1/sites/{id}/deploysдеплой архивом (tar.gz в теле, до 50 МБ)editor - POST
/api/v1/sites/{id}/deploy-filesдеплой набором файлов (JSON, до 20 МБ)editor - POST
/api/v1/sites/{id}/deploys/checkманифест → какие блобы догрузитьeditor - PUT
/api/v1/blobs/{sha256}загрузить один блоб (сырые байты)editor - POST
/api/v1/sites/{id}/deploys/manifestсобрать деплой из блобов (до 500 МБ)editor - GET
/api/v1/deploys/{id}статус деплояread - POST
/api/v1/deploys/{id}/activateсделать деплой боевым / откатитьсяeditor - POST
/api/v1/sites/{id}/domainsпривязать доменeditor - POST
/api/v1/domains/{id}/verifyподтвердить домен (+ диагностика A-записи a_record)editor - DELETE
/api/v1/domains/{id}отвязать доменfull - GET
/api/v1/forms/overview/сводка по формам проектаread - GET
/api/v1/forms/submissions/заявки: ?site=&status=verified|spam|archive&limit=&offset=read
Деплой: форматы и статусы
Загрузите архив .tar.gz (до 50 МБ). Варианты содержимого:
- Исходники npm-проекта — Tuqo соберёт на
Node 20:
npm ci && npm run build, артефакт берётся изdist/,build/илиout/(нуженpackage-lock.json). - Готовая статика — положите файлы (с
index.html) в корень архива. Так публикуется вывод любого стека/языка, собранного локально.
Поддерживаемые стеки
Авто-сборка из коробки (вывод в dist/build/out):
Только статика — SSR и серверные функции не выполняются.
Стеки с другим каталогом вывода (Gatsby → public/, Nuxt 3, Angular,
Eleventy) и не-Node инструменты (Hugo, Jekyll) — соберите локально и залейте готовую статику
(вариант «Готовая статика» выше). Так работает любой стек.
Деплой через REST (тело — бинарный архив):
curl -X POST https://api.tuqo.ru/api/v1/sites/$SITE/deploys \
-H "Authorization: Bearer tqk_xxx_yyy" \
-H "Content-Type: application/gzip" \
--data-binary @dist.tar.gz
В MCP тот же архив передаётся как base64 в аргументе
source_base64 инструмента deploy_site.
При успешной сборке деплой активируется автоматически.
Статусы деплоя
-
queuedдеплой в очереди на сборку -
buildingидёт сборка (npm ci && npm run build) -
readyсобран, но ещё не активирован -
activeбоевой — отдаётся на поддомене сайта -
failedошибка сборки (текст — в get_logs / поле error) -
supersededзаменён более новым активным деплоем
Большие сайты: манифест-деплой
Один запрос ограничен размером тела (архив — до 50 МБ, набор файлов — до 20 МБ). Для тяжёлых сайтов (много фото/видео) и эффективных повторных деплоев — манифест-деплой: файлы грузятся поштучно по содержимому (sha256), без гигантского запроса, а совпадающие между деплоями файлы не перезаливаются (правка текста не трогает картинки).
Проще всего — CLI
Делает все шаги сам; байты читаются с диска (для агентов — без расхода токенов на base64).
Ключ — через env TUQO_API_KEY (не светится в истории шелла);
--wait дождётся публикации и напечатает боевой URL:
TUQO_API_KEY=tqk_xxx_yyy npx @tuqo/cli deploy ./dist --site $SITE --wait
Несколько сайтов из одного репозитория (локали, бренды) — файл
tuqo.json в корне
({"sites": {"site/com": "<site_id>", "site/ru": "<site_id>"}})
и одна команда npx @tuqo/cli deploy. Ключ API в
tuqo.json хранить нельзя — CLI откажется работать.
Или напрямую — 3 шага REST
- Манифест → недостающие блобы.
POST /api/v1/sites/{id}/deploys/checkс телом{"files":[{"path":"index.html","sha256":"…"},…]}→{"missing":["sha256",…]}. - Загрузка блобов. Для каждого недостающего —
PUT /api/v1/blobs/{sha256}, тело — сырые байты файла (sha256 тела должен совпадать с путём). До 50 МБ на файл. - Сборка деплоя.
POST /api/v1/sites/{id}/deploys/manifestс тем же манифестом (path+sha256) → сервер соберёт сайт из блобов и опубликует. До 2000 файлов; суммарный объём ограничен только квотой хранилища вашего тарифа.
Нужен index.html в корне. Дедуп блобов — в пределах проекта.
Для агента в браузерном чате (без файловой системы) тяжёлые медиа-сайты собираются именно так
через CLI на машине пользователя; чистый веб-чат подходит для лёгких сайтов и правок текста.
Правка существующего сайта без перезаливки медиа
Чтобы изменить текст, не пересылая картинки заново (важно для веб-агента без файлов):
GET /api/v1/sites/{id}/manifest(или MCPget_manifest) → массив{path, sha256}текущих файлов.- Деплой через
deploy_files//deploy-files: неизменные файлы передайте ссылкой{"path":…,"sha256":…}(безcontent— байты не пересылаются), изменённые — обычнымcontent.
Сослаться по sha256 можно только на блоб своего проекта.
Лимиты deploy_files: до 500 файлов и 20 МБ суммарно инлайн-контентом;
файл, переданный ссылкой на блоб, — до 50 МБ.
Раздача: маршруты, 404.html и кэш
Как edge резолвит запрос /P (путь без расширения), если файла
P нет — по порядку:
- Clean URL:
/about→ отдаётсяabout.html. - Индекс каталога: есть
about/index.html→ 301 на/about/(чтобы работали относительные ссылки), затем отдаётся индекс. Путь со слэшем (/about/) сразу отдаётabout/index.html. - Кастомный 404: положите
404.htmlв корень деплоя — при промахе он отдаётся со статусом 404 (честный код для SEO). - SPA-fallback: если
404.htmlнет — отдаётсяindex.htmlсо статусом 200 (клиентский роутинг React/Vue).
Запрос файла с расширением, которого нет
(/app.js), возвращает честный 404 — ассеты не подменяются на index.html.
Кэш-заголовки
*.html—no-cache: обновления видны сразу.- Файлы с контент-хэшем в имени
(
app.4f3a2b1c.js, вывод Vite/Astro, каталог_astro/) —max-age=31536000, immutable: год в кэше, инвалидация — новым именем файла. - Остальная статика (
hero.jpgсо стабильным именем) —max-age=300: обновление файла с тем же именем доедет за ~5 минут. Отдельно управлять заголовками нельзя — хотите immutable, используйте хэш в имени (сборщики делают это сами).
Формы (приём заявок)
Любой сайт проекта может принимать заявки без своего бэкенда — фича доступна с тарифа Профи (или при докупленных заявках на любом тарифе). Форма отправляет данные на публичный эндпоинт, заявки копятся в панели проекта (вкладка «Формы»), приходят в колокольчик и, по настройке, на email.
Эндпоинт
POST https://api.tuqo.ru/f/{site_id} —
принимает application/json,
application/x-www-form-urlencoded и
multipart/form-data — то есть обычный submit HTML-формы
и new FormData() работают наравне с JSON. Другой
Content-Type → 415
(явная ошибка, а не молчаливый 200). Авторизация
не нужна — эндпоинт публичный, привязан к домену сайта.
Где взять эндпоинт через MCP: ответы
create_site, get_site и
list_sites содержат поле
form_endpoint — готовый URL для встраивания. Он
детерминирован: https://api.tuqo.ru/f/<site_id>.
Встраивание формы
Готовый сниппет с анти-спам-полями всегда есть в панели (вкладка «Формы»). Минимальный вид:
<form onsubmit="event.preventDefault();
const f=event.target, d=Object.fromEntries(new FormData(f));
d._submit_time=f.dataset.t; d._request_id=crypto.randomUUID();
fetch('https://api.tuqo.ru/f/SITE_ID', {
method:'POST', headers:{'Content-Type':'application/json'},
body: JSON.stringify(d)
}).then(()=>{ f.reset(); alert('Заявка отправлена'); });" data-t="">
<input name="name" placeholder="Имя" required>
<input name="email" type="email" placeholder="Email" required>
<textarea name="message" placeholder="Сообщение"></textarea>
<input name="_hp_xxx" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Отправить</button>
<script>document.currentScript.closest('form').dataset.t=Date.now()</script>
</form> Служебные поля и анти-спам
_submit_time— момент показа формы (мс,Date.now()). Отправка быстрее ~3 секунд после показа считается спамом. Верхней границы нет — вкладку можно держать открытой сколько угодно._request_id— UUID запроса: повторная отправка с тем же id не задваивает заявку (идемпотентность). Необязательно.- honeypot — скрытое поле с именем вида
_hp_xxx(точное имя — в сниппете панели или вget_forms_overview). Можно не добавлять — без поля заявка проходит нормально; оно режет только если заполнено (бот). Если добавили — оставляйте пустым. - Origin — запрос должен идти с домена сайта (его
*.tuqo.ruили подтверждённого кастомного домена), иначе403. Поэтому форма работает на самом сайте, а не с произвольного origin. - Лимиты: тело ≤ 50 КБ, до 30 полей, не более 30 заявок/мин на сайт и 10/мин на IP.
Ответы
-
200заявка принята (или молча отклонена honeypot/повтором — наружу одинаковый ответ) -
400тело не распарсилось при верном Content-Type (reason: invalid_body) -
402формы недоступны: нет тарифа со Старта и нет докупленных заявок, либо проект приостановлен -
403запрос не с домена сайта (origin не в списке разрешённых; reason: origin_required / origin_not_allowed) -
415неподдерживаемый Content-Type — шлите JSON, urlencoded или multipart (reason: unsupported_content_type) -
429превышен лимит частоты
Сверх месячного лимита тарифа заявки не теряются: содержимое сохраняется скрытым и открывается при сбросе лимита, докупке пакета заявок или повышении тарифа. Лимиты по тарифам — на странице тарифов, обзор — на странице Формы.
Чтение заявок (для ИИ-агентов и автоматизаций)
Заявки можно не только принимать, но и читать программно — для отчётов, авто-ответов и дашбордов.
Скоуп — проект из API-ключа, нужен уровень read.
- MCP:
get_forms_overview(квоты, баланс, сайты, счётчики) иget_form_submissions(site_id?,status?= verified|spam|archive,limit?,offset?). - REST:
GET /api/v1/forms/overviewиGET /api/v1/forms/submissions?site=&status=&limit=&offset=.
Кастомные домены
Привязка домена — в два шага:
- 1
set_custom_domain(илиPOST /api/v1/sites/{id}/domains) — в ответе придёт токен. Добавьте в DNS домена A-запись на IP платформы и TXT-запись_tuqo-verifyс этим токеном. - 2
verify_domain(илиPOST /api/v1/domains/{id}/verify) — после распространения DNS. Владение подтверждается по TXT; в ответе также диагностика A-записи (a_record: ok / found / expected / message) — если A ведёт не на платформу, сайт по домену не откроется. Повторный вызов на уже подтверждённом домене перепроверяет A-запись. HTTPS-сертификат выпускается автоматически.
DNS обновляется не мгновенно — от нескольких минут до нескольких часов. Точные значения A- и TXT-записей всегда показываются в панели на вкладке «Домены» сайта.