# API сервер

Вкладка **Настройка → API сервер** (`tpl-tab-firm-api`): токены к **вашей базе** (остатки, каталог, накладные, заказы). Ниже — элементы экрана, затем маршруты и примеры для интеграции.

Раздел: [Настройка](nastrojka.md).

## Как открыть

- **Настройка** → **API сервер**.
- **«?»** — эта страница.
- Подзаголовок: персональный доступ по ключам (как выносные ссылки на ТСД); ссылка «Справка и примеры для программиста» — сюда.

## Тулбар

| Кнопка | Назначение |
| --- | --- |
| **Сохранить** | Галочка «API включён» и связанные настройки |
| **Создать ключ** | Новый ключ (нужен включённый API); полный ключ показывается **один раз** |
| **Обновить** | Список ключей и каталог маршрутов с сервера |

## Настройки

- **API включён** — снято: все запросы с ключами → `403`; ключи сохраняются.
- Строка тарификации (`data-billing-daily="api"`).
- **Комментарий к новому ключу** — до 128 символов; подставляется при «Создать ключ».

## Новый ключ

После создания: предупреждение скопировать сейчас; **Ключ доступа** (readonly) + **Копировать**; мета (дата).

## Примеры URL с новым ключом

Таблица: **Метод**, **URL**, **Копировать** на строке — шаблоны (остатки YML/JSON, ассортимент, контрагенты, склады, приходы, расходы, заказы поставщику, заявки покупателей).

## Активные ключи

Таблица: **Комментарий**, **Создан**, **Последняя активность**, **Отозвать** (с подтверждением). Пусто: «Нет активных ключей». Ключи бессрочные; несколько на базу.

## Маршруты и URL на форме

Блок статуса: **Базовый URL** и каталог методов — Метод, Название, URL-шаблон с `{token}`, **Копировать**; сообщения об ошибках внизу вкладки.

## Что это

У каждой фирмы свои ключи и данные. Запросы на общий адрес API Меркурий-ИИ; по токену выбирается база.

Это **не** `APP_API_KEY` внутренних сервисов. Для интеграции достаточно токена с этой вкладки.

1. **API включён** → **Сохранить**.
2. **Создать ключ** → скопировать ключ и URL из таблиц.

## Базовый URL

```
https://mercury-ai.ru/api/public/index.php?route=МАРШРУТ&token=ВАШ_КЛЮЧ
```

На своём сервере адрес другой — показывает вкладка «Маршруты и URL». Готовые строки с ключом — «Примеры URL» после создания ключа.

Токен можно передать заголовком `Authorization: Bearer КЛЮЧ` или `X-Api-Key: КЛЮЧ` — в query достаточно `?route=…`.

### GET — маршруты (сводка)

| Данные | route |
| --- | --- |
| Остатки YML | `public/firm-api/stocks.yml` |
| Остатки JSON | `public/firm-api/stocks.json` |
| Ассортимент | `public/firm-api/catalog.json` |
| Контрагенты | `public/firm-api/contragents.json` |
| Склады | `public/firm-api/stores.json` |
| Приходы | `public/firm-api/prih-docs.json` (GET журнал, POST создать) |
| Расходы | `public/firm-api/rash-docs.json` (GET, POST) |
| Поиск по S/N | `public/firm-api/scan-resolve.json` (`q=SERIAL`, опц. `store_id`) |
| Реализация по S/N | `public/firm-api/serial-units/mark-realized.json` (POST) |
| Заказы поставщику | `public/firm-api/supplier-orders.json` |
| Заявки покупателей | `public/firm-api/customer-orders.json` |
| Фото товара | `public/firm-api/tovar-photo/{id}` |

Журналы: `date_from`, `date_to` (`YYYY-MM-DD`, до 366 дней); фильтр склада — `store_id` или `id_sklad`.

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

- Токен как пароль — не в открытом коде.
- HTTPS на боевом сервере.
- Отзыв ключа — запросы с ним прекращаются; обновите интеграции.
- «API включён» снят — `403`, токен сохраняется.

## Методы (ответы)

### Остатки YML (`stocks.yml`)

GET, только позиции с остатком > 0. Ответ: XML YML Yandex, несколько складов.

### Остатки JSON (`stocks.json`)

Те же данные в JSON: `updated_at`, `stores`, `products` с `stocks` по `store_id`. Без нулевых остатков (в отличие от `catalog.json`).

### Ассортимент (`catalog.json`)

Весь ассортимент: группы, штрихкоды, цены и остатки по складам, `web_photo_url` для «Большого фото для интернета». Фото — отдельный GET `tovar-photo/{id}`.

### Контрагенты (`contragents.json`)

Группы и контрагенты с реквизитами. `is_sklad`, `is_system`. Токены кассы и маркировки **не** отдаются.

### Склады (`stores.json`)

Собственные склады; те же `id`, что в `store_id` у остатков и цен.

### Приходы (`prih-docs.json`)

**GET:** проведённые за период + черновики вне периода; без приходов из производства. Параметры: `date_from`, `date_to`, опц. `store_id`.

**POST:** `store_id`, `contragent_id`, `rows` (минимум одна); опц. даты, `posted`, `is_return`; в строках `product_id`, `qty`, `price`, `retail_price`, `serials` для посерийных. Ответ `201` — объект `doc`.

### Расходы (`rash-docs.json`)

**GET:** аналогично приходам; без расходов из производства; в строках `cost`, `profit`.

**POST:** `store_id`, `contragent_id`, `rows`; опц. `date_rash`, `posted`, `is_return`, `serials`.

### Реализация по S/N (`mark-realized.json`)

POST: тело `{"serials": ["…"]}` — +1 к «Реализ.» в проведённой расходной «на реализацию» (QRStone). Повтор безопасен. Нужна миграция `00152__serial_units_realized.sql`.

### Заказы поставщику (`supplier-orders.json`)

**GET** по `date_order`. **POST:** создание заказа; товар должен относиться к поставщику. Email-отправка через API недоступна.

### Заявки покупателей (`customer-orders.json`)

**GET** по `date_order`. **POST:** `description`, связь с расходом — поля `linked_rash_id` при выгрузке.

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

Ключ из **Настройка → API сервер**; передача: `?token=`, `Authorization: Bearer`, `X-Api-Key`. Сессия и `APP_API_KEY` не нужны. API должен быть включён.

## Ошибки

JSON: `{"error": "…"}`.

| Код | Значение |
| --- | --- |
| 401 | Токен не передан или неверный |
| 403 | API выключен |
| 500 | Ошибка сервера (например YML) |

## Примеры для программиста

`BASE=https://mercury-ai.ru/api/public/index.php`, подставьте `TOKEN`.

**Остатки YML:**

```bash
curl -sS "BASE?route=public/firm-api/stocks.yml&token=TOKEN" -o stocks.yml
```

**Приходы за июль:**

```bash
curl -sS "BASE?route=public/firm-api/prih-docs.json&date_from=2026-07-01&date_to=2026-07-31&store_id=12&token=TOKEN"
```

**Создать приход (POST):**

```bash
curl -sS -X POST -H "Authorization: Bearer TOKEN" -H "Content-Type: application/json" \
  -d '{"store_id":12,"contragent_id":15,"posted":false,"rows":[{"product_id":1001,"qty":24,"price":65}]}' \
  "BASE?route=public/firm-api/prih-docs.json"
```

**Каталог (Python):** `requests.get(BASE, params={"route": "public/firm-api/catalog.json", "token": TOKEN})`; фото по `web_photo_url`.

**PowerShell:** `Invoke-WebRequest` с заголовком `Authorization: Bearer`.

**Cron (каждые 10 мин):** выгрузка `stocks.yml` в каталог сайта.

Подробные тела JSON и поля ответов — на вкладке **API сервер** в шаблонах URL и в технической документации разработчика (`docs/API_REFERENCE.md`).

## Ограничения и миграции

Данные привязаны к токену фирмы, не к текущему складу в UI. Фото товара — файл на сервере, в базе ссылка.

При обновлении программы могут понадобиться миграции: `00010__firm_public_api.sql`, `00011__firm_public_api_tokens.sql`, `00012__firm_public_api_tokens_no_expiry.sql`, `00095__tovars_web_photo_path.sql`, `00152__serial_units_realized.sql`.

См. также [HTTP-клиент](nastrojka-http-client.md) (отладка запросов, admin-only).
