
# CLI и cURL

Страница для тех, кто работает с API Вайбкод из терминала: скрипты для оболочки, разовые проверки утилитой `curl`, серверные интеграции на PHP без SDK. Полные справочники по операциям — на профильных страницах: [Entity API](./entity-api.md), [Фильтрация](./filtering.md), [Batch API](./batch.md), [Коды ошибок](./errors.md).

Базовый URL — `https://vibecode.bitrix24.tech`. Авторизация — через заголовок `X-Api-Key`. Ответы — JSON в формате `{ success, data, meta }` при успехе и `{ success: false, error }` при ошибке.

## На странице

- [Окружение](#окружение) — переменные `VIBE_API_KEY` / `VIBE_URL`, сохранение в `~/.zshrc` для использования между сессиями
- [Авторизация в curl](#авторизация-в-curl) — личный ключ и ключ авторизации
- [Минимальный цикл проверки](#минимальный-цикл-проверки) — создание → удаление с проверкой HTTP 204
- [Полезные приёмы curl](#полезные-приёмы-curl) — `jq`, `-s` против `-sS`, `--data-binary @file`, `read -s`, `X-RateLimit-*`
- [OpenAPI-спецификация](#openapi-спецификация) — `/v1/openapi.json`, срез по скоупу и сторонняя утилита `openapi-to-cli`
- [PHP](#php) — шаблон `vibeRequest` без внешних зависимостей
- [Обработка ошибок](#обработка-ошибок) — формат `{ success: false, error }`

## Окружение

Сохраните ключ и базовый URL в переменные окружения — это убирает повторы в каждой команде и не оставляет ключ в истории команд оболочки.

```bash
export VIBE_API_KEY="vibe_api_xxx..."
export VIBE_URL="https://vibecode.bitrix24.tech"
```

Проверка — должен вернуться JSON с порталом и скоупами:

```bash
curl -s -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/me" | head -c 200
```

Чтобы переменные сохранились между сессиями, добавьте строки `export ...` в `~/.zshrc` (для оболочки `zsh`) или `~/.bashrc` (для `bash`) и перезапустите терминал.

Для ключа авторизации (`vibe_app_...`) дополнительно понадобится токен сессии:

```bash
export VIBE_APP_KEY="vibe_app_xxx..."
export VIBE_SESSION_TOKEN="vibe_session_xxx..."
```

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

Личный ключ — один заголовок:

```bash
curl -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/deals"
```

Ключ авторизации — два заголовка, `X-Api-Key` для приложения и `Authorization: Bearer` для сессии конкретного пользователя:

```bash
curl -H "X-Api-Key: $VIBE_APP_KEY" \
     -H "Authorization: Bearer $VIBE_SESSION_TOKEN" \
     "$VIBE_URL/v1/deals"
```

Подробнее о типах ключей и получении токена сессии — [Ключи и авторизация](./keys-auth.md).

## Минимальный цикл проверки

Один сценарий, чтобы убедиться, что ключ работает и API отвечает: создать сделку → удалить. Формат вызова у остальных сущностей такой же, а набор операций и поля у каждой свои (см. [Обзор API](./entity-api.md) и [справочник сущностей](./entities-index.md)).

```bash
# 1. Создать сделку — вернёт объект с присвоенным id
curl -X POST "$VIBE_URL/v1/deals" \
  -H "X-Api-Key: $VIBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "title": "CLI test", "stageId": "NEW", "categoryId": 0 }'

# 2. Удалить созданную сделку — успех = HTTP 204 с пустым телом
curl -i -X DELETE "$VIBE_URL/v1/deals/<id-из-первого-ответа>" \
  -H "X-Api-Key: $VIBE_API_KEY"
```

Признак успеха `DELETE` — код ответа, не тело ответа. Чтобы увидеть только код:

```bash
curl -s -o /dev/null -w "%{http_code}\n" -X DELETE \
  -H "X-Api-Key: $VIBE_API_KEY" \
  "$VIBE_URL/v1/deals/<id>"
```

Полные примеры запросов с фильтрами, сортировкой, выбором полей и автопагинацией — на странице нужной сущности, например [Сделки](./entities/deals.md). Синтаксис фильтров (MongoDB-style, префиксы, операторы как ключи) — [Фильтрация и поиск](./filtering.md).

## Полезные приёмы curl

### Читаемый JSON в терминале

`curl` выдаёт ответ одной строкой. Для просмотра подключите `jq` или `python3 -m json.tool`:

```bash
curl -s -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/deals?limit=5" | jq
curl -s -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/deals?limit=5" | python3 -m json.tool
```

### `-s` против `-sS` в скриптах

Флаг `-s` (тихий режим) подавляет индикатор прогресса вместе с сообщениями о сетевых ошибках — например, `Could not resolve host`. В скриптах это скрывает реальные сбои. Флаг `-sS` подавляет только индикатор прогресса, а текст ошибки выводится в `stderr`:

```bash
# Тихо, но при сетевой ошибке скрипт молча получит пустой ответ
curl -s "$VIBE_URL/v1/deals" -H "X-Api-Key: $VIBE_API_KEY"

# Тихо для нормальной работы, ошибки сети видны
curl -sS "$VIBE_URL/v1/deals" -H "X-Api-Key: $VIBE_API_KEY"
```

В скриптах для оболочки используйте `-sS`: ошибки сети попадут в `stderr` и не потеряются при отладке.

### Большое тело запроса через `--data-binary @file.json`

При длинном теле (batch на 50 операций, импорт OpenAPI, развёрнутый фильтр) флаг `-d` не справляется с экранированием кавычек оболочки и переносами строк. Сохраните тело в файл и передайте его через `@`:

```bash
cat > body.json <<'EOF'
{
  "calls": [
    { "id": "newDeals", "entity": "deals", "action": "list",
      "params": { "filter": { "stageId": "NEW" }, "limit": 100 } },
    { "id": "user", "entity": "users", "action": "get", "entityId": 1 }
  ]
}
EOF

curl -X POST "$VIBE_URL/v1/batch" \
  -H "X-Api-Key: $VIBE_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @body.json
```

`--data-binary` сохраняет переносы и кавычки как есть, в отличие от `-d`, который вырезает `\n`.

Ответ группирует результаты по `id` каждого вызова — `results` содержит данные, `meta` — статистику пагинации, `summary` — итог по всему пакету:

```json
{
  "success": true,
  "data": {
    "results": {
      "newDeals": [ { "id": 7720, "title": "Поставка серверов", "stageId": "NEW" } ],
      "user": { "id": 1, "name": "Иван Петров" }
    },
    "totals": { "newDeals": 311 },
    "meta": {
      "newDeals": { "total": 311, "returned": 100, "hasMore": true }
    },
    "errors": [],
    "summary": { "total": 2, "succeeded": 2, "failed": 0 }
  }
}
```

Полные правила batch (лимит 50 вызовов, стоимость в единицах rate-limit, поведение `action: "list"` с `limit > 50`) — [Batch API](./batch.md).

### Экспорт ключа без сохранения в истории оболочки

Команда `export VIBE_API_KEY="vibe_api_..."` сохранится в `~/.zsh_history` или `~/.bash_history` — оттуда ключ может попасть на демонстрацию экрана или в резервную копию системы. Альтернатива — `read -s`: оболочка прочитает ключ без отображения на экране, в истории останется только команда `read`, без значения.

```bash
read -s VIBE_API_KEY && export VIBE_API_KEY
# курсор не двигается, вставляете ключ, Enter
```

Тот же приём подходит для `VIBE_APP_KEY` и `VIBE_SESSION_TOKEN`.

### Заголовки и код ответа

```bash
# -i — заголовки + тело
curl -i -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/me"

# -w — только выбранные поля статистики (код, время)
curl -s -o /dev/null -w "HTTP %{http_code}, %{time_total}s\n" \
  -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/deals"
```

### Лимиты запросов

В заголовках ответа приходят `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` — текущий остаток лимита запросов для ключа:

```bash
curl -s -D - -o /dev/null -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/me" | grep -i ratelimit
```

### Сохранение ответа в файл

```bash
curl -s -H "X-Api-Key: $VIBE_API_KEY" "$VIBE_URL/v1/openapi.json" -o openapi.json
```

## OpenAPI-спецификация

Полный машинно-читаемый каталог эндпоинтов — `/v1/openapi.json` в формате OpenAPI 3.1:

```bash
curl -s "$VIBE_URL/v1/openapi.json" -o openapi.json
```

Файл импортируется в Postman, Insomnia, Swagger UI и любые инструменты, поддерживающие OpenAPI 3.1. На основе спецификации можно генерировать клиентские библиотеки (`openapi-generator`, `oazapfts` и аналоги). Инструменту, который читает только 3.0, спецификация не подойдёт: нулевые значения в ней описаны как объединение типов (`["number","null"]`) — форма, появившаяся в 3.1.

### Срез по скоупу

Параметр `?scope=<скоуп>` отдаёт спецификацию, урезанную до сущностей одного скоупа, — служебные и мета-эндпоинты остаются в любом срезе. Файл получается в разы меньше полного. Применяйте срез, когда инструмент или модель работают с одним разделом:

```bash
curl -s "$VIBE_URL/v1/openapi.json?scope=crm" -o openapi-crm.json
```

Принимается ровно один известный скоуп из списка [Скоупы](/docs/scopes). Неизвестное значение и пустая строка возвращают полную спецификацию, а не ошибку. Перечисление через запятую тоже даёт полную спецификацию — кроме случая, когда все перечисленные значения сводятся к одному скоупу (`task,tasks`), тогда вернётся срез.

### Утилита `openapi-to-cli`

> Сторонний инструмент, не часть API Вайбкод. Платформа не следит за его работоспособностью. За обновлениями, ошибками и совместимостью со спецификацией обращайтесь в [репозиторий автора](https://github.com/EvilFreelancer/openapi-to-cli).

[`openapi-to-cli`](https://github.com/EvilFreelancer/openapi-to-cli) — CLI-утилита, которая собирает команды на основе любой OpenAPI-спецификации. Подключается к API Вайбкод без кодогенерации: указываете URL спецификации и заголовок авторизации.

```bash
npm install -g openapi-to-cli

ocli profile add vibecode \
  --spec https://vibecode.bitrix24.tech/v1/openapi.json \
  --base-url https://vibecode.bitrix24.tech \
  --header "X-Api-Key: $VIBE_API_KEY"

# Поиск эндпоинта по слову
ocli vibecode search "deals"

# Вызов
ocli vibecode exec GET /v1/deals
ocli vibecode exec POST /v1/deals \
  --body '{ "title": "Новая сделка", "stageId": "NEW", "categoryId": 0 }'
```

Утилита сторонняя, поддерживается своим автором — за обновлениями и ошибками обращайтесь в её репозиторий. После изменений в API Вайбкод обновлённая спецификация подхватывается `ocli` при следующем запуске.

## PHP

Минимальный шаблон для скриптов и серверных интеграций — без внешних зависимостей, только встроенный `curl`. Тот же шаблон подходит для всех эндпоинтов: `vibeRequest($url, $method, $data)`.

```php
<?php

$VIBE_URL = getenv('VIBE_URL') ?: 'https://vibecode.bitrix24.tech';
$VIBE_API_KEY = getenv('VIBE_API_KEY') ?: 'vibe_api_xxx...';

function vibeRequest(string $url, string $method = 'GET', ?array $data = null): array {
    global $VIBE_API_KEY;

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_HTTPHEADER     => [
            'X-Api-Key: ' . $VIBE_API_KEY,
            'Content-Type: application/json',
        ],
    ]);
    if ($data !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
    }

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // DELETE возвращает 204 с пустым телом
    if ($httpCode === 204) {
        return ['success' => true];
    }

    $body = json_decode($response, true);
    if ($body === null) {
        throw new RuntimeException("HTTP $httpCode: некорректный JSON в ответе");
    }
    if (empty($body['success'])) {
        $code = $body['error']['code'] ?? 'UNKNOWN';
        $msg  = $body['error']['message'] ?? 'Неизвестная ошибка';
        throw new RuntimeException("$code: $msg (HTTP $httpCode)");
    }
    return $body;
}
```

### Примеры использования

```php
// Список
$result = vibeRequest("$VIBE_URL/v1/deals?limit=20");
foreach ($result['data'] as $deal) {
    echo $deal['id'] . ': ' . $deal['title'] . PHP_EOL;
}

// Создание
$result = vibeRequest("$VIBE_URL/v1/deals", 'POST', [
    'title'      => 'Поставка серверов',
    'stageId'    => 'NEW',
    'categoryId' => 0,
    'amount'     => 1500000,
    'currency'   => 'RUB',
]);
$dealId = $result['data']['id'];

// Поиск с фильтром
$result = vibeRequest("$VIBE_URL/v1/deals/search", 'POST', [
    'filter' => [
        'stageId' => ['$ne' => 'LOST'],
        'amount'  => ['$gte' => 100000],
    ],
    'sort'  => ['createdAt' => 'desc'],
    'limit' => 50,
]);

// Удаление — внутри vibeRequest 204 превращается в ['success' => true]
vibeRequest("$VIBE_URL/v1/deals/$dealId", 'DELETE');
```

Полные форматы тел запроса и поля ответа — на страницах конкретных сущностей, например [Сделки](./entities/deals.md).

## Обработка ошибок

При неуспехе тело ответа имеет вид `{ success: false, error: { code, message } }` и соответствующий HTTP-статус. Пример — запрос без ключа:

```bash
curl -i "$VIBE_URL/v1/deals"
```

```
HTTP/2 401
content-type: application/json; charset=utf-8

{
  "success": false,
  "error": {
    "code": "MISSING_API_KEY",
    "message": "API key required. Pass via X-Api-Key header."
  }
}
```

Полный справочник кодов и рекомендуемых действий — [Коды ошибок](./errors.md).

## Смотрите также

- [Быстрый старт](./quickstart.md) — первый запрос за 2 минуты
- [Ключи и авторизация](./keys-auth.md) — типы ключей, скоупы, лимиты, токены сессии
- [Entity API](./entity-api.md) — CRUD, пагинация, выбор полей для всех сущностей
- [Фильтрация и поиск](./filtering.md) — три синтаксиса фильтров с примерами
- [Batch API](./batch.md) — объединение запросов, ускорение в 50 раз
- [Оптимизация](./optimization.md) — паттерны для дашбордов и массовых операций
- [Коды ошибок](./errors.md) — справочник по ошибкам
- [MCP для AI](./mcp.md) — интеграция с AI-инструментами
