SparkUAPIЭкспериментальноllms.txtEnglish

Разделы · 6/11

HTTP API

Транспорт, авторизация и полный список маршрутов /v1 — запрос, тело, ответ, коды ошибок.

Markdown ↗

TIP

Машиночитаемое описание всех маршрутов — /openapi.json (OpenAPI 3.1). Схему с полями конкретной интеграции печатает sparku openapi <адрес>.

Транспорт#

SparkU слушает HTTP/1.1 на UNIX-сокете ~/.sparku/run/api.sock. Сокет существует, только пока в Настройках включены «Свои интеграции» и SparkU запущен — если файла нет, функция выключена или приложение не работает (см. Если не работает).

Права на сокет — 0700 на каталог и 0600 на файл: доступ только тому же пользователю. Никакого TCP-порта нет, поэтому запросы можно слать только с этого же Mac.

curl --unix-socket ~/.sparku/run/api.sock http://sparku/v1/health

Хост в URL (http://sparku/...) не резолвится — соединение всё равно идёт через сокет, имя нужно только curl, чтобы собрать корректный запрос.

Тело запросов и ответов — JSON (Content-Type: application/json; charset=utf-8). Кодировка тела — Content-Length; Transfer-Encoding: chunked не поддерживается.

Авторизация#

Все маршруты интеграции (/v1/integrations/{slug}/...) требуют заголовок:

Authorization: Bearer <токен>

Токен выдаётся на интеграцию при её создании (Настройки → Свои интеграции → «slug» → Подключение) или при импорте .sparku (Файлы .sparku и импорт). Без заголовка — 401 unauthorized, с чужим или отозванным токеном — 401 invalid_token.

GET /v1/health и POST /v1/imports токена не требуют: первому нечего защищать, а второй ещё не знает, к какой интеграции относится запрос — интеграции пока нет.

Маршруты#

Метод Путь Назначение
GET /v1/health версия протокола и приложения
GET /v1/integrations/{slug} схема полей и текущие значения
POST /v1/integrations/{slug}/fields частичная запись значений (upsert)
DELETE /v1/integrations/{slug}/fields очистить значения
POST /v1/integrations/{slug}/notify вспышка и строка на несколько секунд
POST /v1/integrations/{slug}/glow пятна света в заданных местах контура
DELETE /v1/integrations/{slug}/glow погасить пятна
POST /v1/integrations/{slug}/dialogs вопрос человеку — Вопросы человеку
GET /v1/integrations/{slug}/events поток нажатий (SSE) — Кнопки и события
POST /v1/imports импорт .sparku — Файлы .sparku и импорт

Метод, которого маршрут не поддерживает, отвечает 405 method_not_allowed с заголовком Allow. Неизвестный путь под /v1 — 404 not_found.

GET /v1/health#

Без токена. Не проверяет, что интеграция существует, — просто «SparkU здесь».

curl --unix-socket ~/.sparku/run/api.sock http://sparku/v1/health
{"status": "ok", "api_version": 1, "app_version": "2.4.0"}

GET /v1/integrations/{slug}#

Схема полей интеграции и текущие значения (если они ещё не истекли по TTL).

curl --unix-socket ~/.sparku/run/api.sock \
  -H "Authorization: Bearer $SPARKU_TOKEN_DEPLOY" \
  http://sparku/v1/integrations/deploy
{
  "slug": "deploy",
  "name": "Деплой",
  "enabled": true,
  "fields": [
    {"key": "progress", "type": "progress", "label": "Прогресс"},
    {"key": "stage", "type": "state", "label": "Этап", "states": ["running", "done", "failed"]},
    {"key": "title", "type": "text", "label": "Сервис", "max_length": 60}
  ],
  "values": {"progress": 0.4, "stage": "running", "title": "api · prod"},
  "updated_at": "2026-09-28T10:15:00Z",
  "expires_at": "2026-09-28T11:15:00Z"
}

expires_at в ответе нет, если у значений нет срока жизни. Если значений ещё не было или они истекли, values — пустой объект, updated_at/expires_at отсутствуют.

Коды: 200, 404 unknown_integration, 401.

POST /v1/integrations/{slug}/fields#

Частичная запись значений — upsert: перечисленные поля меняются, остальные не трогаются. null у поля очищает его. Запись всё или ничего: если хоть одно поле не проходит проверку, не применяется ни одно.

curl --unix-socket ~/.sparku/run/api.sock \
  -H "Authorization: Bearer $SPARKU_TOKEN_DEPLOY" \
  -H "Content-Type: application/json" \
  -d '{"progress": 0.72, "stage": "running", "title": "api · prod"}' \
  http://sparku/v1/integrations/deploy/fields
{"ok": true, "updated": ["progress", "stage", "title"], "cleared": []}

Типы значений в теле — см. Типы полей. Тело {"progress": null} попадает в cleared, а не в updated.

?ttl= — на сколько запомнить значения этой записи: число секунд (?ttl=90) или относительное время (?ttl=5m, ?ttl=1h30m), не больше 7 дней. Без параметра действует срок жизни из настроек интеграции (по умолчанию — «до перезапуска SparkU»). Отсчёт начинается заново от каждой записи. Если срок задан, ответ дополнительно содержит expires_at:

{"ok": true, "updated": ["progress"], "cleared": [], "expires_at": "2026-09-28T11:20:00Z"}

?bind= — привязать значения к процессу: process (тот, что прислал запрос), PID (?bind=$ из shell) или none (снять привязку). Процесс завершился — значения сняты. Ответ с привязкой содержит bound_pid. Подробнее — привязка к процессу.

Коды: 200, 400 empty_body, 400 invalid_json, 400 invalid_ttl, 400 invalid_bind, 409 integration_disabled, 422 invalid_fields, 401, 404.

422 invalid_fields перечисляет каждое неверное поле:

{"error": {"code": "invalid_fields", "message": "progress: ожидалось 0…1, пришло 70",
 "fields": [{"field": "progress", "message": "progress: ожидалось 0…1, пришло 70"}]}}

DELETE /v1/integrations/{slug}/fields#

Очищает все значения интеграции — эквивалент sparku end. Ответ — 204 No Content, тела нет.

curl --unix-socket ~/.sparku/run/api.sock -X DELETE \
  -H "Authorization: Bearer $SPARKU_TOKEN_DEPLOY" \
  http://sparku/v1/integrations/deploy/fields

Коды: 204, 401, 404. Работает и для выключенной интеграции.

POST /v1/integrations/{slug}/notify#

Вспышка на окантовке и/или переключение строки на несколько секунд. Нужно хотя бы одно из text и state.

curl --unix-socket ~/.sparku/run/api.sock \
  -H "Authorization: Bearer $SPARKU_TOKEN_DEPLOY" \
  -d '{"text": "Сборка упала", "state": "failed", "color": "red", "duration": 4}' \
  http://sparku/v1/integrations/deploy/notify
Поле Тип Правило
text строка обрезается до 120 символов (с …)
state строка значение любого поля типа state у интеграции
color строка одно из семантических имён (blue, red, success, …)
duration число 1…10 секунд, по умолчанию 4
{"ok": true}

Не чаще раза в 2 секунды на интеграцию: следующий вызов раньше — 429 too_many_notices с заголовком Retry-After (секунды до разрешённого вызова).

Коды: 200, 400 invalid_json, 409 integration_disabled, 409 notify_disabled (notify выключен в настройках интеграции), 422 invalid_notice, 429 too_many_notices, 401, 404.

POST /v1/integrations/{slug}/glow#

Координатная подсветка: свет загорается в заданных местах контура островка и стоит там, пока не придёт следующий кадр. Подходит для визуализации звука, нескольких параллельных задач «по участкам», шкал.

curl --unix-socket ~/.sparku/run/api.sock \
  -H "Authorization: Bearer $SPARKU_TOKEN_DEPLOY" \
  -d '{"spots": [{"position": 0.2, "color": "green"},
                 {"position": 0.8, "color": "#FF3B30", "intensity": 0.6, "width": 0.15}]}' \
  "http://sparku/v1/integrations/deploy/glow?ttl=10"
Поле Тип Правило
spots массив обязателен, не больше 64 пятен; пустой массив — темно
spots[].position число 0…1 слева направо по ширине островка, 0.5 — середина под вырезом
spots[].color строка семантическое имя (blue, red, success, …) или #RRGGBB
spots[].intensity число 0…1, по умолчанию 1
spots[].width число полуширина пятна в долях ширины островка, 0.005…1, по умолчанию 0.08
intensity число толщина обводки и сила свечения, 0.2…3, по умолчанию 1
{"ok": true}
  • Каждый запрос заменяет кадр целиком. Соседние пятна, которые перекрываются, смешивают цвета.
  • Частота не ограничена: шлите кадры хоть 60 раз в секунду, на островок попадёт не больше ~30.
  • ?ttl= — сколько кадр горит без следующего: секунды или 5m / 1h30m, по умолчанию 5 секунд. Скрипт упал — подсветка гаснет сама.
  • Пока горит вспышка или статус другого виджета, она принимает форму ваших пятен: цвета её, а яркость вдоль контура — от пятен (не ниже 30 %). Между интеграциями с пятнами решает приоритет интеграции.
  • DELETE …/glow и sparku end гасят пятна сразу.

Коды: 200, 400 invalid_ttl, 409 integration_disabled, 422 invalid_glow, 401, 404.

POST /v1/integrations/{slug}/dialogs#

Вопрос человеку на островке. Подробности — Вопросы человеку.

GET /v1/integrations/{slug}/events#

Поток нажатий в карточке (SSE). Подробности — Кнопки и события.

POST /v1/imports#

Импорт .sparku. Подробности — Файлы .sparku и импорт.

Единый формат ошибок#

Любая ошибка — JSON вида:

{"error": {"code": "invalid_fields", "message": "человекочитаемый текст"}}

message пишется для человека и рассчитан на то, что клиент — чаще всего shell-скрипт: текст можно выводить в терминал как есть. Некоторые ошибки добавляют поля в объект error (например fields у invalid_fields).

Коды ошибок#

Код HTTP Где
not_found 404 путь не под /v1 или не существует
unknown_integration 404 нет интеграции с таким slug
unauthorized 401 нет заголовка Authorization: Bearer …
invalid_token 401 токен не подходит к интеграции
method_not_allowed 405 метод не поддерживается на этом пути
empty_body 400 тело запроса пустое (fields)
invalid_json 400 тело — не JSON-объект
invalid_ttl 400 ?ttl= не разобрать
invalid_bind 400 ?bind= не process, none или PID живого процесса
invalid_fields 422 значение(я) не прошли проверку типа
invalid_notice 422 notify: неверные text/state/color/duration
invalid_glow 422 glow: неверные пятна, цвет или интенсивность
invalid_dialog 422 dialogs: тело вопроса не разобрать
invalid_package 422 imports: файл .sparku не разобрать
integration_disabled 409 интеграция выключена в Настройках
notify_disabled 409 notify выключен в настройках интеграции
dialog_pending 409 у интеграции уже есть вопрос без ответа
import_pending 409 SparkU уже предлагает человеку другой импорт
import_declined 403 человек отклонил предложенную интеграцию
too_many_notices 429 notify чаще раза в 2 секунды
too_many_connections 503 больше 64 одновременных соединений
unavailable 503 SparkU ещё не готов принимать запросы
withdrawn 503 SparkU закрывается или API выключили во время ожидания
bad_request 400 / 411 / 413 / 431 / 505 нарушение HTTP: плохие заголовки, нет Content-Length, тело больше 1 МБ, слишком большие заголовки, неподдерживаемая версия

NOTE

bad_request — единый код для ошибок разбора HTTP; конкретную причину и статус смотрите в message.

Коалесценция и лимиты#

  • fields принимает запросы без ограничения частоты, но на островок попадает не чаще одного обновления за кадр отрисовки — быстрый цикл push не мигает промежуточными значениями.
  • notify — не чаще раза в 2 секунды на интеграцию (429 при превышении).
  • glow — без ограничения частоты, на островок попадает не больше ~30 кадров в секунду.
  • Диалог — не больше одного ожидающего вопроса на интеграцию (409 dialog_pending).
  • Импорт — не больше одного предложения на всё приложение одновременно (409 import_pending).
  • Соединения — не больше 64 одновременных на весь сервер (503 too_many_connections).
  • Тело запроса — не больше 1 МБ (лимит рассчитан на поле image в base64).
  • История чисел для графика и тренда — не больше точки в секунду, 120 точек на поле, только в памяти процесса SparkU.

Совместимость /v1#

Внутри /v1 изменения только добавляющие: новые маршруты и новые поля ответа, но не изменение уже существующего поведения. Скрипт, написанный сегодня, продолжит работать после обновления SparkU без правок.