CRM API — Справочник endpoints

Arc OS — The Orchestration System for AI Teams

Общая информация

Параметр Значение
Base URL https://arc-os.co/api/crm
Авторизация Authorization: Bearer <JWT> или ?token=<JWT> (для SSE/WebSocket)
Content-Type application/json
JWT алгоритм HMAC-SHA256
JWT TTL 24 часа

Аутентификация

Все endpoints (кроме /docs/*) требуют JWT токен в заголовке Authorization: Bearer <token>.

Для SSE и WebSocket соединений токен передаётся через query-параметр ?token=<JWT>.

Ошибки авторизации

Код Описание
401 Отсутствует или невалидный токен
403 Нет доступа к проекту (multi-tenancy)

Endpoints по категориям

Аккаунт и настройки

Метод Путь Описание
GET /account/settings Получить настройки аккаунта
PUT /account/settings Обновить настройки аккаунта
GET /account/usage История использования токенов для авторизованного пользователя (Phase 63, #148). Response: { rows: [ { project_name, worker_id, input_tokens, output_tokens, cache_tokens, total_tokens, created_at } × до 200 ], totals: { total, input, output } }. Читает token_usage_log по owner_id. Отображается в UserDropdown (UsageCard) и BillingPage (секция Token Usage).

Онбординг + Trial Credits (Phase 50.1)

Метод Путь Описание
POST /onboarding/setup Создай первый проект. Body multipart: config (JSON) + files. Поле anthropicKey теперь опциональное — если пустое + у пользователя email_verified + пробная версия ещё не выдавалась, проект создаётся в trial_mode=1 со 100K free tokens. Response: { ok, project, trial_activated }. Phase 51: возвращает 402 с {error:"plan_limit_reached", reason, current, limit, plan} когда пользователь превысил project limit для плана.
GET /account/trial-status Статус пробной версии для UI banner. Response: { email, email_verified, trial_granted, has_trial_active, total_remaining, total_granted, projects: [...] }

Onboarding Checklist (Phase 54.1, issue #56)

Post-wizard 5-шаговый чеклист вовлечённости. Каждый шаг (workers, cli, skill, bot, issue) принимает статус completed или skipped. Мутации идемпотентны: повторный идентичный POST возвращает тот же state, не пишет дубликат в activity_log. Replay не сбрасывает state, только снимает dismissed_at — UI снова показывает панель с тем же прогрессом.

Метод Путь Описание
GET /onboarding/progress Текущее состояние для авторизованного пользователя. Response: { steps:["workers","cli","skill","bot","issue"], state:{<step>:<status>}, completed_count, total_steps:5, completed_at, dismissed_at, source, started_at, updated_at }. Нетронутый пользователь → нули/null без создания строки.
POST /onboarding/event Записать переход шага. Body: { step: "workers"|"cli"|"skill"|"bot"|"issue", status: "completed"|"skipped", source?: "web"|"cli" }. Whitelist validation → 400 на неизвестный step/status. Response: тот же shape что GET. Эмитирует onboarding_step_completed/onboarding_step_skipped в activity_log только при changed; при переходе к 5/5 дополнительно эмитирует onboarding_completed с duration_ms.
POST /onboarding/dismiss Закрыть панель (dismissed_at = now). Идемпотентно. Эмитирует onboarding_dismissed при первом вызове с payload {completed_count}.
POST /onboarding/replay Снова открыть закрытую панель (dismissed_at = NULL). State шагов не затрагивается. Эмитирует onboarding_replayed при clear-event.
POST /projects/:name/active-issue Issue #115. Привязать текущую web-сессию к задаче. Body: { issue_id: number, title?: string }. Пишет событие session_active_issue в activity_log (source=web).
GET /projects/:name/active-issue Issue #115. Последняя привязанная задача для этого владельца за 7 дней. Response: { active_issue_id, title, ts }.
GET /onboarding/cli-status Phase 54.3 (issue #58). Логинился ли пользователь через arc login за последние 30 дней? Response: { installed: boolean, last_cli_at: string|null }. SSOT — строки в activity_log с event_type='cli_invocation' и actor=chatId. Frontend onboarding-чеклист опрашивает этот endpoint каждые 10s пока CLI шаг pending; когда installed=true — автоматически маркирует шаг cli как completed.
GET /analytics/onboarding-funnel Phase 54.6 (issue #61). Агрегированная воронка за скользящее окно. Query: hours=168 (1-720, default 7d). Response: { hours, total_steps:5, started_users, completed_users, completion_rate, per_step: [{step, completed, skipped}…], duration_p50_ms, duration_p90_ms, ttfc_p50_ms, ttfc_sample_size }. SSOT — события activity_log onboarding_step_* + onboarding_completed + cli_invocation. TTFC = time-to-first-arc (julianday delta от первого onboarding-step до первого cli_invocation per actor).

SSOT для funnel-метрик (Phase 54.6 / issue #61) — события в activity_log (event_type LIKE 'onboarding_%'). Таблица onboarding_progress — derived cache: UI рендерится одним запросом вместо агрегации по событиям.

Beta Feedback (Phase 53.3)

Метод Путь Описание
POST /feedback Отправить бета feedback. Body: {type: "bug"|"feature"|"other", title, description, project?, browser?}. Записывает в activity_log (event_type=feedback_report) и пингует CEO в Telegram.
GET /admin/feedback Список последних submissions (только admin). Query: limit=50 (max 500). Response: {items: [...], count}.

POST /feedback — валидация body: type ∈ {bug,feature,other}, title ≤200 chars, description ≤5000 chars. Успех → {ok: true, type, title}. Telegram ping форматируется как 🐞/💡/📝 New <type> feedback ... From: <user> Title: <title> + первые 400 символов описания.

Плавающий виджет в FeedbackWidget.jsx (CRM дашборд) автоматически передаёт browser (UA + viewport + locale) и project (technical_name активного проекта).

Beta Invites (Phase 52.1, только admin)

Метод Путь Описание
GET /admin/invites Список всех кодов приглашения + counts (total_active, total_used). Только admin.
POST /admin/invites Сгенерировать N кодов. Body: {count: N, note?: string}. Только admin. Response: {ok, codes, count}.
DELETE /admin/invites/:code Отозвать неиспользованный код приглашения.

Обновление auth flow: POST /api/auth/register теперь требует поле invite_code (Phase 52.1 closed бета). Без кода → 403 {error: "invite_required"}. Невалидный/использованный код → 403 {error: "invalid_invite"}.

Billing (Phase 51)

Метод Путь Описание
GET /billing/status Текущий план, лимиты, usage, features. Автоматически создаёт Free row при первом вызове. Response: { plan, status, current_period_end, limits, usage, features, pricing, can_upgrade, stripe_ready }
POST /billing/checkout-session Stripe Checkout (Stage 2 — возвращает 501 пока Stripe SDK не интегрирован)

Plan limits (OR-semantic):

Ответ 402 на POST /onboarding/setup или POST /projects/:name/workers при превышении лимита: { error: "plan_limit_reached", reason: "projects_limit"|"workers_limit", current, limit, plan, message }

Пользователи-admin (role=admin) полностью обходят проверку plan-limit — они операторы, а не платные тенанты.

Бета-тестеры (subscriptions.plan='beta', Phase 52 F&F) тоже обходят — неограниченное количество проектов/воркеров плюс все Max-фичи. Назначается вручную: UPDATE subscriptions SET plan='beta' WHERE user_id=?.

Bugfix (issue #25): POST /projects/create (Quick Start, Phase 50.2) раньше падал с ownerChatId is not defined из-за опечатки — исправлено, audit-actor теперь корректно записывается.

Bugfix (issue #26): allocatePort() для новых проектов теперь проверяет реальные TCP-bindings (ss -tln), а не только registry. Раньше мог выдать порт занятый не-registry сервисом (NotebookLM bridge :19213, internal bridges) → workspace bot падал на EADDRINUSE.

Auth flow (Phase 50.1): /api/auth/register и /api/auth/login теперь возвращают JWT даже для unverified email + флаг needs_verification: true. Чувствительные действия (trial grant, billing, invites) проверяют email_verified отдельно. Rate limit на signup: 3 / IP / 24h.


Проекты (9 endpoints)

Метод Путь Описание
GET /projects Список проектов пользователя
POST /projects/create Создай проект
GET /projects/:name Детали проекта
GET /projects/:name/config Конфигурация проекта
PUT /projects/:name/config Обновить конфигурацию
GET /projects/:name/protocol Протокол проекта
PUT /projects/:name/protocol Обновить протокол
GET /projects/:name/logs Логи проекта
GET /projects/:name/metrics Метрики проекта

POST /projects/create — body:

{
  "technical_name": "string",
  "displayName": "string",
  "description": "string",
  "icon": "string",
  "color": "string"
}

GET /projects/:name/logs — query: category, lines

GET /projects/:name/metrics — query: since, until


Воркеры (11 endpoints)

Метод Путь Описание
GET /projects/:name/workers Список воркеров
POST /projects/:name/workers Создай воркера
POST /projects/:name/workers/reorder Phase 53.8 — изменить порядок воркеров. Body: {order: [id1, id2, ...]}. Атомарно перезаписывает workers_registry.json. Воркеры отсутствующие в order добавляются в конец (защита от потери). Response: {ok, count, order}.
PUT /projects/:name/workers/:id Обновить воркера
DELETE /projects/:name/workers/:id Удали воркера
POST /projects/:name/workers/generate-prompt Сгенерировать системный промпт
GET /projects/:name/workers/:id/telegram-token Получить Telegram токен
POST /projects/:name/workers/:id/telegram-token Phase 53.4 — валидирует токен через Telegram getMe, сохраняет bot_username в vault, отказывает если тот же бот уже привязан к другому воркеру (409). Response: {ok, started, bot_username}.
DELETE /projects/:name/workers/:id/telegram-token Удали Telegram токен
POST /projects/:name/workers/:id/notify Phase 53.2 — отправить TG event ping ({event?, text, buttons?}). Silent no-op если токен не привязан или CRM_DISABLE_TG_NOTIFY=1.
POST /projects/:name/workers/:id/suggest-bot-username 53.11.1 (issue #48) — возвращает 5 кандидатов TG username для bot-creation wizard в формате <project>_<worker>_bot + numbered fallbacks. Slugify убирает hyphens, truncate до 32 chars (worker-часть обрезается первой). Response: {candidates: string[]}.
POST /metrics/wizard 53.11.1 (issue #48) — telemetry sink для bot-creation wizard. Body: {action, duration_ms?, attempts?, success?, project?, worker_id?}. Пишет в activity_log (event_type=wizard_metric), best-effort.
GET /analytics/wizard-metrics?hours=168 53.11.1 (issue #48) — funnel summary: {starts, completions, abandons, success_rate, avg_duration_ms_completed, avg_attempts_completed, by_action}. Default 7 дней, clamp 1-720h.
POST /projects/:name/restart Перезапустить воркера
GET /projects/:name/active-role Текущая активная роль
POST /projects/:name/active-role Изменить активную роль

POST /projects/:name/workers — body:

{
  "label": "string",
  "icon": "string",
  "type": "terminal | telegram",
  "model": "string",
  "max_turns": 20,
  "tools": ["Read", "Write", "Bash"],
  "system_prompt": "string",
  "focus_dirs": ["src/", "docs/"]
}

max_turns по умолчанию 20 (раньше было 5, вызывало ошибку "Reached max turns" в многошаговых диалогах с tool calls).

POST /projects/:name/restart — query: worker_id


Файлы и хранилище (8 endpoints)

Метод Путь Описание
GET /projects/:name/files Дерево файлов
POST /projects/:name/files/upload Загрузить файл (multipart, max 100MB)
POST /projects/:name/files/mkdir Создай директорию
POST /projects/:name/files/create Создай файл
GET /projects/:name/files/read Прочитать файл
PUT /projects/:name/files/save Сохрани файл
DELETE /projects/:name/files/delete Удали файл
POST /projects/:name/files/clone Git clone репозитория

GET /projects/:name/files — query: path

GET /projects/:name/files/read — query: path, raw


Скилы / Skills (18 endpoints)

Скилы проекта

Метод Путь Описание
GET /projects/:name/skills Список скилов проекта
POST /projects/:name/skills Создай скил
PUT /projects/:name/skills/:id Обновить скил
DELETE /projects/:name/skills/:id Удали скил

Глобальный marketplace

Метод Путь Описание
GET /skills Список глобальных скилов
POST /skills Опубликовать скил
GET /skills/:id Детали скила
PUT /skills/:id Обновить скил
DELETE /skills/:id Удали скил

Эволюция и обновления

Метод Путь Описание
GET /skills/:id/evolution История эволюции скила
GET /skill-updates Список доступных обновлений
POST /skill-updates/:id/approve Принять обновление
POST /skill-updates/:id/reject Отклонить обновление

Форки скилов

Метод Путь Описание
GET /projects/:name/skill-forks Список форков
POST /projects/:name/skill-forks Создай форк
PUT /projects/:name/skill-forks/:id Обновить форк
DELETE /projects/:name/skill-forks/:id Удали форк

Чат и сообщения

Метод Путь Описание
POST /projects/:name/chat Отправить сообщение в чат
GET /projects/:name/chat/history История чата
POST /projects/:name/message Отправить сообщение воркеру (Phase 48.6: автоматически wake-up idle-killed воркера, ~2-4с cold start; Phase 48.6.1: wake-up теперь работает и в single-mode проектах, не только parallel)
GET /projects/:name/pins Список заметок (pins)
POST /projects/:name/pins Создай заметку
DELETE /projects/:name/pins/:id Удали заметку

Wiki (4 endpoints)

Метод Путь Описание
GET /projects/:name/wiki/tree Дерево вики-страниц
GET /projects/:name/wiki/file Прочитать вики-страницу
PUT /projects/:name/wiki/save Сохрани вики-страницу
GET /projects/:name/wiki/download Скачать вики как ZIP архив

Аналитика (4 endpoints)

Метод Путь Описание
GET /analytics/activity Лента активности
GET /analytics/sidebar Данные для боковой панели
GET /analytics/phases Список фаз проекта
POST /analytics/phases Обновить фазы проекта

Marketplace и Sage (8 endpoints)

Метод Путь Описание
GET /sage/scout/categories Категории marketplace
POST /sage/scout Поиск скилов
POST /sage/scout/quick-scan Быстрое сканирование
POST /sage/scout/analyze Глубокий анализ скила
POST /sage/scout/install Установить скил
POST /sage/analyze Sage анализ
GET /sage/status Статус Sage сервиса
POST /sage/benchmark Запустить бенчмарк

Память и Knowledge

Метод Путь Описание
POST /projects/:name/memory/refresh Обновить нейронную память
POST /projects/:name/memory/fetch-artifact Загрузить артефакт
GET /projects/:name/learnings Список learnings
POST /projects/:name/learnings Добавить learning
GET /projects/:name/knowledge-graph Граф знаний проекта

Документация (глобальная, без auth)

Метод Путь Описание
GET /docs/tree?lang=<lang> Дерево документации; lang опциональный (en/uk), default en
GET /docs/file?path=<p>&lang=<lang> Прочитать файл документации с language fallback

GET /docs/tree — query: lang (опциональный)

GET /docs/file — query: path (обязательный), lang (опциональный)


Система

Метод Путь Описание
GET /system/configs Получить системные конфигурации
PUT /system/configs Обновить системные конфигурации

Коды ошибок

Код Значение
200 Успех
201 Создано
400 Невалидный запрос
401 Не авторизован
403 Запрещено (multi-tenancy)
404 Не найдено
409 Конфликт (дубликат)
429 Слишком много запросов
500 Серверная ошибка

GitHub Integration (Phase 49.3)

Endpoint Method Описание
/api/crm/projects/:name/github GET Список GitHub repos привязанных к проекту
/api/crm/projects/:name/github POST Привязать repo (body: {owner, repo}) — возвращает webhook URL + secret + setup instructions
/api/crm/projects/:name/github/:id DELETE Отвязать repo
/api/crm/projects/:name/github/events GET Список последних GitHub events (Phase 49.3.1, query: ?limit=50)
/api/webhooks/github POST Public webhook receiver (HMAC-SHA256 validated, rate-limit 100/min)

Поддерживаемые события: push, pull_request, workflow_run, issues. Уведомления роутятся в Telegram владельца проекта.

Account Security (Phase 45.4)

Endpoint Method Описание
/api/crm/account/recovery GET Список активных recovery keys
/api/crm/account/recovery POST Создай recovery key (body: encryptedKey, keyHint)
/api/crm/account/recovery DELETE Отозвать recovery key(s) (body: { id } или {} для всех)
/api/crm/account/recovery/restore GET Получить encrypted master key для восстановления

Безопасность


Phase 53.13 — type-safety baseline (2026-05-10)

Не изменение поведения endpoints — только внутренние типы. tsc --noEmit теперь блокирует push/CI:


Phase 53.15 — Sentinel Sprint 1 (2026-05-10)

Изменения поведения auth + admin endpoints (Sentinel audit P0 fixes):


Phase 53.21 — Sentinel P2 batch 2 (2026-05-12)

Phase 53.18 — tmux secret-leak fix (2026-05-11)

Не изменение поведения endpoints — только рефакторинг internal spawn paths.

Phase 53.16 — Sentinel Sprint 2 (2026-05-10)

Изменения поведения endpoints после hardening 13 × P1:

Phase 55 — Cosmic Editorial login (2026-05-13)

Новые endpoints для magic-link sign-in:

EphemeralTokenType union расширен: теперь содержит "magic_link" наряду с существующими oauth_state / password_reset / email_verification / tfa_challenge.

Frontend (CosmicCard.jsx) обрабатывает состояние magic (60-s resend countdown) и URL-параметр ?magic_token= (auto-consume → login → success animation).

Phase 56 — AI Interop / Project Context Export (2026-05-13)

Owner-only экспорт sanitized snapshot проекта как .md для передачи внешнему AI (Gemini / ChatGPT / Perplexity / Claude.ai).

Alert: когда владелец превышает 3 экспорта за 24h AND prefs.notify_on_export = true (default OFF) — logActivity("export_alert", ...) идёт через существующий Phase 53.10 TG notify pipeline (alertFired: true в response body).

Multi-tier scanner (shared/secret-scanner.ts) — Tier 1 regex (PATTERN_REGISTRY из PII sanitizer), Tier 2 Shannon entropy ≥4.5 bits/char на ≥20-char runs, Tier 3 context heuristics (key=/token:/secret=/password=). Whitelist: UUID / git SHA / SHA-256 / repeated chars / short hex / low-entropy base58. Severity tiers (critical/high/medium/low). Производительность: <500 ms / 1 MB.

DB migration 024 — таблицы export_audit_log + export_preferences.


Phase 57 — Platform Settings (Sentinel #103 follow-up, 2026-05-15)

Super-admin управление секретами через CRM UI вместо ssh/edit-.env/paste-in-chat. Backend MVP (Stage 1 из 4 stages). Все endpoints гейтованы requireAdmin (Phase 53.15) — возвращают 403 Forbidden — admin only для не-admin, 401 Unauthorized без JWT.

Список жёсткого исключения NEVER_EXPOSE: CRM_SECRET (JWT signing) + SECRET_ENCRYPTION_KEY (vault meta-key) — даже admin запрос с валидным токеном возвращает 400 "not managed". Audit лог append-only (нет UPDATE/DELETE handler), каждое действие (включая failed) пишет row с IP + UA + email.

DB migration 026 — таблица platform_audit_log. Stage 2 (frontend PlatformSettings.jsx) — задеплоен 2026-05-15 (cbc8bac): admin-only card grid + rotate modal (<input type="password"> + retype-confirm) + audit drawer; запись sidebar фильтруется по userRole === "admin", получаемому из /api/auth/me.

Polish (2026-05-15, commit 56191b0) — реструктуризация Platform Settings UI. Поля items ответа GET /api/crm/platform/settings получают 5 новых полей: category (anthropic|oauth|telegram|email), usedIn (string[] — файлы/флоу потребляющие ключ), getFromUrl (где получить свежее значение), effectAfterRotate, riskIfLeaked. Используется frontend для рендеринга 4 секционных групп карточек + per-card сворачиваемая help-панель со структурированным контекстом (Used in / Get from / Effect / Risk). Никаких изменений поведения мутирующих endpoints (PUT/POST/restart/test).

Рефакторинг (2026-05-16) — internal cleanup shared/routes/platform.ts. Удалено 39 строк (добавлено 16), никаких изменений публичного API surface. Сигнатуры и ответы endpoints PUT/POST/restart/test/audit неизменны. Задокументировано здесь только потому что doc-coverage pre-push gate срабатывает на любой diff в shared/routes/*.ts.

Backdated activity (#117, 2026-05-16)POST /api/mcp/issues/:project/:id/log теперь принимает опциональное поле ts (строка ISO-8601). Используется arc retro при реконструкции чтобы исторические записи попадали на свои оригинальные временные метки. Значения из будущего молча обрезаются до now внутри addActivity() (защита от случайных backdates). Невалидный ISO → 400.

Stage 3 (2026-05-15) — hot-reload OAuth + Resend secrets без restart. shared/auth.ts loadOAuthConfig() теперь читает getSecret("GITHUB_CLIENT_ID/SECRET" | "GOOGLE_CLIENT_ID/SECRET") при каждом вызове вместо process.env. Callsites в master-bot/routes/auth.ts уже вызывали getOAuthConfig() per request → 0 изменений callsite. RESEND_API_KEY уже hot-reload через shared/email.ts:47. Поведенческое изменение: PUT /api/crm/platform/settings/{GITHUB_CLIENT_ID|GITHUB_CLIENT_SECRET|GOOGLE_CLIENT_ID|GOOGLE_CLIENT_SECRET|RESEND_API_KEY} теперь вступает в силу со следующего запроса, не требует restart. restartTargets для этих 5 ключей пустой → кнопка Restart в UI скрыта. Edge case: OAuth flow с state-токеном выданным до rotation может получить 400 на callback при code-exchange — retry пользователя решает проблему. ANTHROPIC_API_KEY, PLATFORM_ANTHROPIC_KEY, MASTER_BOT_TOKEN, CITADEL_BOT_TOKEN остаются restart-required (читаются при child-bot spawn / TG long-poll init).

Phase 57.3.5 cleanup (2026-05-16) — allowlist MANAGED_KEYS сокращён с 9 до 6. Удалены: ANTHROPIC_API_KEY (операторы теперь используют единый PLATFORM_ANTHROPIC_KEY для trial-credits и platform inference; .env fallback по-прежнему работает для legacy code paths пока Sage/Karpathy не мигрируют), CITADEL_BOT_TOKEN (per-project bot относится к vault записям child:<name>:token, управляемым через worker onboarding flow — не Platform Settings). MASTER_BOT_TOKEN перепрофилирован: label → "Telegram — System Monitor Bot", description → "Server health alerts + on-demand status probes (admin-only, not a chat bot)". Phase 58 добавит monitoring loop (push alerts для worker crash / disk / RAM / SSH brute-force / CF bypass + команды /status, /health, /errors, /restart). Итоговый набор: PLATFORM_ANTHROPIC_KEY + GITHUB×2 + GOOGLE×2 + MASTER_BOT_TOKEN + RESEND_API_KEY (refs #103).

Phase 63 — Консолидация UI/UX + Отслеживание использования токенов (2026-05-21, #148)

Новый endpoint:

Изменения в claude-runner.ts:

Изменения UI (не API):