API
API позволяет читать и изменять файлы сайтов из скриптов и ИИ-агентов. Создайте токен в панели и выберите доступные ему сайты.
Токен также позволяет управлять публичным доступом по ключу. Этот ключ не ограничивает чтение и запись через API: Bearer-токен проверяется независимо, в пределах выбранных сайтов. Карантин, блокировки и отзыв токена сохраняют действие.
Публичный доступ по ключу
GET /sites/{id}/access?path=docs возвращает собственный и действующий режим доступа, источник наследования и настройку родителя. Хеш/ключ не раскрываются. Пустой path означает весь сайт.
# Закрыть папку со случайным ключом просмотра
curl -X PUT -H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"path":"docs","mode":"key","generate":true}' \
'https://vvall.ru/api/v1/sites/1/access'
# Явное публичное исключение внутри закрытой папки
curl -X PUT -H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"path":"docs/public.html","mode":"public"}' \
'https://vvall.ru/api/v1/sites/1/access'
# Удалить собственное правило папки, вернув наследование
curl -X DELETE -H "Authorization: Bearer $API_TOKEN" \
'https://vvall.ru/api/v1/sites/1/access?path=docs'
PUT принимает path, mode (inherit/public/key), необязательные key, generate или revoke. generate:true возвращает generated_key один раз; сохраните его безопасно. Для собственного ключа передайте key (12–256 символов). При сохранении существующего режима key без нового значения прежний ключ сохраняется; revoke:true отзывает посетителей. DELETE корня делает сайт открытым, DELETE вложенного объекта возвращает наследование, которое тоже может быть закрытым. Обычные GET/PUT /file продолжают работать без ключа просмотра.
Скачать спецификацию OpenAPI 3.1
Быстрый старт
Базовый адрес: https://vvall.ru/api/v1. Передавайте токен в заголовке Authorization. Каждый токен даёт чтение и запись; права администратора токенам не передаются.
Authorization: Bearer vv_…В примерах ниже переменная API_TOKEN содержит ваш токен. Никому его не публикуйте и не добавляйте в HTML-файлы сайта.
# Доступные сайты
curl -H "Authorization: Bearer $API_TOKEN" \
https://vvall.ru/api/v1/sites
# Содержимое корневой папки сайта с ID 1
curl -H "Authorization: Bearer $API_TOKEN" \
https://vvall.ru/api/v1/sites/1/files
# Скачать файл и получить ETag для защиты от перезаписи
curl -D headers.txt -H "Authorization: Bearer $API_TOKEN" \
'https://vvall.ru/api/v1/sites/1/file?path=index.html' -o index.html
# Создать новый файл (при существующем имени вернётся 409)
curl -X PUT -H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/octet-stream' --data-binary @index.html \
'https://vvall.ru/api/v1/sites/1/file?path=new.html'
# Сохранить существующий файл; ETag берётся из GET
curl -X PUT -H "Authorization: Bearer $API_TOKEN" \
-H 'If-Match: "ETAG_ИЗ_GET"' --data-binary @index.html \
'https://vvall.ru/api/v1/sites/1/file?path=index.html&overwrite=1'
# Загрузить и распаковать ZIP в папку проекта
curl -H "Authorization: Bearer $API_TOKEN" \
-F 'file=@site.zip' -F 'path=project' \
https://vvall.ru/api/v1/sites/1/uploadПримеры ответов JSON
GET /sites возвращает канонический публичный url каждого доступного сайта. При блокировке URL сохраняется, но публичный доступ закрыт.
{"sites":[{"id":1,"slug":"example","title":"Мой сайт","blocked_at":null,"url":"https://example.vvall.ru/"}]}GET /sites/1/files?path=pages:
{"entries":[{"id":42,"site_id":1,"path":"pages/index.html","kind":"file","size":34,"state":"live","etag":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}]}POST /sites/1/directories с JSON {"path":"pages"}:
{"ok":true}PUT /sites/1/file?path=pages%2Findex.html с исходным HTML в теле запроса создаёт файл; для замены добавьте overwrite=1 и передайте предыдущий ETag в If-Match. Ответ:
{"entry":{"id":42,"site_id":1,"path":"pages/index.html","kind":"file","size":34,"state":"live","etag":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}}Ответы файлов могут содержать дополнительные поля. GET /file возвращает байты файла, а не JSON. ETag в примерах условный; используйте значение реального ответа. Публичная ссылка на файл строится из url сайта и пути с URL-кодированием каждого сегмента.
Методы
| Метод | Путь после /sites/{site} | Действие |
|---|---|---|
| GET | /files?path=assets | Содержимое папки |
| GET / HEAD | /file?path=index.html | Байты файла / заголовки |
| PUT | /file?path=index.html | Создать; overwrite=1 для замены |
| DELETE | /file?path=assets | Переместить в корзину |
| POST | /directories | JSON: {"path":"assets/images"} |
| POST | /copy или /move | JSON: {"path":"a.html","to":"folder/b.html"} |
| POST | /upload | multipart: file, path, overwrite |
| GET | /archive?path=assets | ZIP папки; пустой path — весь сайт |
| GET | /trash | Список объектов корзины |
| POST | /restore или /purge | JSON: {"batch":"trash_batch из списка"} |
| POST | /optimize | JSON: path, width, height, quality, replace |
Пути и ограничения
Пути относительные, в UTF-8: assets/main.css. Начальный слеш, обратный слеш, скрытые и служебные файлы запрещены. Для query-параметров используйте URL-кодирование. Сохраняйте точный регистр родительских папок. PHP и другие серверные скрипты запрещены, в том числе внутри ZIP. Разрешены HTML, XML, JS, CSS, JSON, TXT, карты исходников, SVG, растровые изображения и шрифты.
Один файл — до 25 МиБ. ZIP — до 2000 записей, с проверкой размера после распаковки. Квота общая для всех сайтов аккаунта, включая карантин и корзину. Копирование учитывается в квоте.
Для ИИ-агента
- Получите список доступных сайтов через GET /sites и список файлов нужного сайта.
- Прочитайте исходный файл через GET /file и запомните ETag.
- Измените его и отправьте PUT с overwrite=1 и If-Match.
- При 409 прочитайте свежую версию и согласуйте изменения. Не повторяйте запись с удалённым If-Match автоматически.
- После успешной записи изменение уже опубликовано. Отдельного deploy-метода нет.
Ошибки и модерация
{"error":{"message":"Недостаточно места…","status":413}}401 — токен недействителен; 403 — операция запрещена; 404 — объект не найден или недоступен токену; 409 — конфликт пути или ETag; 413 — квота или размер; 415 — формат; 422 — некорректные данные; 429 — слишком много запросов.
Карантин доступен владельцу для чтения, скачивания и удаления. Перемещать, копировать или перезаписывать такие файлы нельзя. Восстановление из корзины сохраняет карантин. При блокировке аккаунта или сайта API также работает только на чтение. Через 30 дней блокировки аккаунта доступ закрывается, а файлы удаляются планировщиком. Управление сайтами, токенами и модерацией через этот API отсутствует.
CORS не включён. API предназначен для серверных инструментов и агентов; не храните токены в публичном JavaScript сайта.