Остатки и импорт

Остаток связывает номенклатуру со складом. В записи хранятся количество, базовая цена, НДС, наценка, скидка и реквизиты поставки.

Вернуться к разделу: управление складом.

Не путайте три идентификатора:

  • nomenclature.id — карточка товара;
  • warehouse.id — место хранения;
  • inventory.id — конкретная складская позиция.

Для первого сквозного сценария начните с быстрого старта складского учёта.

Какой метод использовать

ЗадачаМетод
Получить список для синхронизации или админкиGET /api/tables/inventories
Получить одну складскую позициюGET /api/inventories/{inventory}
Добавить поступившее количествоPOST /api/inventories
Установить точные значенияPUT /api/inventories/{inventory}
Удалить складскую позициюDELETE /api/inventories/{inventory}
Импортировать накладнуюPOST /api/inventories/upload

GET /api/inventories не используйте в новой интеграции: текущая реализация возвращает непагинированный набор номенклатур, а не стабильный список складских позиций. Канонический метод списка — GET /api/tables/inventories.

Перед началом

Подготовьте Bearer сотрудника, warehouse_id и nomenclature_id. Получайте эти ID только из списков своего проекта.

Операции с отдельными остатками сейчас не защищены политикой склада: API находит запись по ID. Не передавайте inventory.id из браузера без серверной проверки и перед изменением сверяйте inventory.warehouse.id и inventory.nomenclature.id.

Как работают количество и цена

  • POST /api/inventories прибавляет переданное quantity к совпавшей позиции. Повтор запроса повторно увеличит остаток.
  • PUT /api/inventories/{inventory} устанавливает переданные значения для существующей позиции.
  • поле price в объекте остатка — базовая складская цена;
  • поле price в табличном ответе уже содержит наценку markup;
  • клиентское приложение использует складскую цену только при warehouse.is_price_from_inventories: true.

Не повторяйте POST автоматически после сетевой ошибки. Сначала проверьте, применился ли запрос, или используйте импорт накладной с контролем результата.

Получить таблицу остатков

Метод
GET
URL
https://api.gigma.ru/api/tables/inventories
Авторизация
Bearer сотрудника
Headers
Authorization: Bearer {token}, Accept: application/json
Успешный ответ
200

Метод возвращает складские позиции проекта, описание колонок и пагинацию. Используйте его как основной список остатков.

Параметры запроса

  • query (string, необязательный) — поиск по названию номенклатуры, от 3 до 1024 символов.
  • owned_by_us (boolean, необязательный) — принадлежность склада.
  • warehouse_id[] (integer[], необязательный) — ID складов.
  • type_id[] (integer[], необязательный) — ID типов номенклатуры.
  • city_id[] (integer[], необязательный) — ID городов складов.
  • brand_id[] (integer[], необязательный) — ID брендов.
  • vat_id[] (integer[], необязательный) — ID ставок НДС.
  • counterparty_id[] (integer[], необязательный) — ID поставщиков.
  • page (integer, необязательный) — номер страницы, по умолчанию 1.
  • per_page (integer, необязательный) — количество строк, по умолчанию 10.

Не передавайте application_id[] для фильтрации этого списка: текущий endpoint перенаправляет такой запрос в таблицу товаров приложения.

Пример запроса

GET /api/tables/inventories?warehouse_id[]=12&query=микрофон&page=1&per_page=50 HTTP/1.1
Host: api.gigma.ru
Authorization: Bearer <employee_token>
Accept: application/json

Ответ

{
	"columns": [
		{
			"id": 91,
			"table_id": 12,
			"order": 0,
			"key": "id",
			"has_icon": 0,
			"text": "№"
		},
		{
			"id": 92,
			"table_id": 12,
			"order": 1,
			"key": "name",
			"has_icon": 1,
			"text": "Наименование"
		}
	],
	"inventories": [
		{
			"id": {
				"icon": null,
				"value": 845,
				"url": "/nomenclatures/list-nomenclatures/340"
			},
			"updated_at": "2026-08-22T07:30:00.000000Z",
			"code": 84501,
			"name": {
				"icon": "https://api.gigma.ru/storage/uploads/default.svg",
				"value": "Микрофон",
				"link": "/nomenclatures/list-nomenclatures/340"
			},
			"counterparty": null,
			"category": {
				"icon": "https://api.gigma.ru/storage/uploads/default.svg",
				"value": "Звуковое оборудование",
				"link": "/categories/list-categories/44"
			},
			"warehouse": {
				"icon": "https://api.gigma.ru/storage/uploads/default.svg",
				"value": "Основной склад",
				"link": "/warehouses/list-warehouses/12"
			},
			"city": "Москва",
			"brand": null,
			"vat": "НДС 20%",
			"markup": 10,
			"unit": "шт.",
			"quantity": "25.000",
			"cost_price": null,
			"price": "1639.00",
			"country": null,
			"reserved": 3,
			"available": 22,
			"invoice_number": null,
			"invoice_date": null
		}
	],
	"pagination": {
		"total": 1,
		"per_page": 50,
		"current_page": 1,
		"last_page": 1,
		"from": 1,
		"to": 1
	}
}

Важные поля:

  • id.value — inventory.id;
  • quantity — количество на складе;
  • reserved — количество в активных резервах;
  • available — количество, доступное для заказа;
  • price — базовая цена с наценкой markup.

Получить остаток

Метод
GET
URL
https://api.gigma.ru/api/inventories/{inventory}
Авторизация
Bearer сотрудника
Headers
Authorization: Bearer {token}, Accept: application/json
Успешный ответ
200

Получите запись перед обновлением или удалением и проверьте, что она относится к ожидаемому складу и номенклатуре.

Параметры пути

  • inventory (integer, обязательный) — ID складской позиции.

Пример запроса

GET /api/inventories/845 HTTP/1.1
Host: api.gigma.ru
Authorization: Bearer <employee_token>
Accept: application/json

Ответ

{
	"inventory": {
		"id": 845,
		"code": 84501,
		"avatar": null,
		"nomenclature": {
			"id": 340,
			"code": 34001,
			"name": "Микрофон"
		},
		"warehouse": {
			"id": 12,
			"code": 12001,
			"name": "Основной склад",
			"avatar": null,
			"owned_by_us": true,
			"address": "Москва, Варшавское шоссе, 1",
			"storage_capacity": 5000,
			"storage_unit": {
				"id": 1,
				"name": "Штука",
				"abbreviation": "шт."
			},
			"city": {
				"id": 1,
				"name": "Москва",
				"avatar": "https://api.gigma.ru/storage/uploads/default.svg",
				"created_at": "2026-08-01T09:00:00.000000Z"
			},
			"counterparty": null,
			"is_price_from_inventories": true
		},
		"counterparty": null,
		"quantity": "25.000",
		"price": "1490.00",
		"discount": 0,
		"vat": {
			"id": 2,
			"name": "НДС 20%",
			"avatar": "https://api.gigma.ru/storage/uploads/default.svg",
			"created_at": "2026-08-01T09:00:00.000000Z"
		},
		"markup": 10,
		"invoice": {
			"number": null,
			"date": null,
			"row_number": null
		},
		"line_total_without_vat": null,
		"line_total_with_vat": null,
		"vat_amount": null,
		"vat_rate": null,
		"currency_code": null,
		"created_at": "2026-08-22T07:00:00.000000Z",
		"updated_at": "2026-08-22T07:30:00.000000Z"
	}
}

Объект nomenclature в реальном ответе содержит полную карточку товара. В примере оставлены ключевые поля, необходимые для сверки.

Ошибки

  • 401 — Bearer отсутствует или недействителен.
  • 404 — запись не найдена.

Добавить количество на остаток

Метод
POST
URL
https://api.gigma.ru/api/inventories
Авторизация
Bearer сотрудника
Headers
Authorization: Bearer {token}, Content-Type: application/json
Успешный ответ
200 или 201

Используйте метод для поступления товара. Если Gigma найдёт совпавшую позицию, он прибавляет переданное количество к текущему. Повтор запроса повторно увеличит остаток.

Параметры запроса

  • nomenclature_id (integer, обязательный) — ID номенклатуры своего проекта.
  • warehouse_id (integer, обязательный) — ID склада своего проекта.
  • code (integer, необязательный) — положительный код, уникальный в проекте. Если не передать, Gigma создаст его автоматически.
  • counterparty_id (integer, необязательный) — ID поставщика.
  • vat_id (integer, необязательный) — ID ставки НДС.
  • quantity (integer, необязательный) — добавляемое количество, не меньше 0.
  • price (number, необязательный) — базовая цена, не меньше 0, до двух знаков после запятой.
  • discount (integer, необязательный) — скидка от 0 до 100.
  • markup (integer, необязательный) — наценка в процентах, не меньше 0.

Не используйте discount: 100: текущий расчёт старой цены не обрабатывает стопроцентную скидку.

Пример запроса

{
	"warehouse_id": 12,
	"nomenclature_id": 340,
	"counterparty_id": 75,
	"vat_id": 2,
	"quantity": 25,
	"price": "1490.00",
	"discount": 0,
	"markup": 10
}

Ответ

Gigma возвращает созданную или найденную складскую позицию в поле inventory. Сохраните inventory.id.

Ошибки

  • 401 — Bearer отсутствует или недействителен.
  • 422 — склад или номенклатура не относятся к проекту, связанный ID не найден либо данные не прошли валидацию.

Установить значения остатка

Метод
PUT
URL
https://api.gigma.ru/api/inventories/{inventory}
Авторизация
Bearer сотрудника
Headers
Authorization: Bearer {token}, Content-Type: application/json
Успешный ответ
200

Используйте метод, чтобы установить точное количество, цену или другие свойства существующей позиции. В отличие от POST, количество здесь не прибавляется.

Параметры пути

  • inventory (integer, обязательный) — ID складской позиции.

Параметры запроса

При каждом обновлении обязательно передавайте:

  • warehouse_id (integer, обязательный) — ID склада своего проекта;
  • nomenclature_id (integer, обязательный) — ID номенклатуры своего проекта.

Остальные поля совпадают с запросом создания и передаются при необходимости: code, counterparty_id, vat_id, quantity, price, discount, markup.

Пример запроса

{
	"warehouse_id": 12,
	"nomenclature_id": 340,
	"quantity": 18,
	"price": "1520.00",
	"discount": 0,
	"markup": 10
}

Ответ

Gigma возвращает обновлённый объект в поле inventory.

Ошибки

  • 401 — Bearer отсутствует или недействителен.
  • 404 — запись не найдена.
  • 422 — обязательный ID отсутствует, связанный объект не найден или данные не прошли валидацию.

Удалить остаток

Метод
DELETE
URL
https://api.gigma.ru/api/inventories/{inventory}
Авторизация
Bearer сотрудника
Headers
Authorization: Bearer {token}, Accept: application/json
Успешный ответ
200

Перед удалением получите запись и проверьте её склад и номенклатуру. Не удаляйте позицию только потому, что количество стало нулевым: она может быть нужна для следующей синхронизации.

Параметры пути

  • inventory (integer, обязательный) — ID складской позиции.

Ответ

{
	"message": "Inventory deleted successfully."
}

Импортировать остатки

Метод
POST
URL
https://api.gigma.ru/api/inventories/upload
Авторизация
Bearer сотрудника
Headers
Authorization: Bearer {token}
Успешный ответ
200, 207

Метод принимает файл накладной или JSON-массив. В обоих режимах передавайте warehouse_id.

Импорт сопоставляет или создаёт поставщика, номенклатуру и складские строки. Повторная загрузка той же накладной обновляет совпавшие строки. Если реквизиты той же накладной конфликтуют с другим набором данных, API возвращает 409.

Режим 1. Файл

Передайте multipart/form-data.

Поддерживаемые форматы: .xmr, .xml, .csv, .xls, .xlsx. Request-валидатор принимает и .txt, но контроллер отклоняет такой файл до импорта, поэтому не используйте .txt.

Параметры запроса

  • warehouse_id (integer, обязательный) — ID склада.
  • file (binary, обязательный) — файл накладной.

Пример запроса

curl -X POST https://api.gigma.ru/api/inventories/upload 
  -H "Authorization: Bearer $TOKEN" 
  -H "Accept: application/json" 
  -F "warehouse_id=12" 
  -F "file=@./invoice.xlsx"

Режим 2. JSON

Передайте application/json.

Параметры запроса

  • warehouse_id (integer, обязательный) — ID склада.
  • invoice_number (string, обязательный) — номер накладной.
  • invoice_date (string, обязательный) — дата в формате YYYY-MM-DD.
  • supplier_inn (string, обязательный) — ИНН поставщика.
  • supplier_name (string, обязательный) — название поставщика.
  • currency_code (string, обязательный) — трёхсимвольный код валюты, например RUB.
  • items (object[], обязательный) — непустой массив строк.
  • items[].row_number (number, обязательный) — номер строки.
  • items[].item_name (string, обязательный) — название товара.
  • items[].quantity (number, обязательный) — количество.
  • items[].price (number, обязательный) — цена за единицу.
  • items[].sum_without_vat (number, обязательный) — сумма без НДС.
  • items[].sum_with_vat (number, обязательный) — сумма с НДС.
  • items[].vat_rate (string, обязательный) — ставка: 0%, 10%, 20% или без НДС.
  • items[].vat_amount (number, необязательный) — сумма НДС.
  • items[].sku (string, необязательный) — артикул.
  • items[].barcode (string, необязательный) — штрихкод.

Пример запроса

{
	"warehouse_id": 12,
	"invoice_number": "РН-2026-081",
	"invoice_date": "2026-08-22",
	"supplier_inn": "7700000000",
	"supplier_name": "ООО «Поставщик»",
	"currency_code": "RUB",
	"items": [
		{
			"row_number": 1,
			"item_name": "Микрофон",
			"quantity": 5,
			"price": "1490.00",
			"sum_without_vat": "7450.00",
			"sum_with_vat": "8940.00",
			"vat_rate": "20%",
			"vat_amount": "1490.00",
			"sku": "MIC-001",
			"barcode": "4600000000001"
		}
	]
}

Ответ

Успешная загрузка:

{
	"status": "success",
	"created": 1,
	"updated": 0,
	"skipped": 0,
	"counterparty_id": 75,
	"invoice_number": "РН-2026-081",
	"invoice_date": "2026-08-22",
	"warehouse_id": 12,
	"errors": []
}

Возможные результаты:

  • 200 и status: success — все строки обработаны;
  • 207 и status: partial — часть строк обработана, ошибки перечислены в errors;
  • 400 и status: error — строки не обработаны или файл имеет неверный формат;
  • 409 и status: conflict — накладная конфликтует с ранее импортированными данными;
  • 422 — обязательные поля отсутствуют или не прошли первичную валидацию.

Всегда проверяйте status, счётчики и errors, а не только HTTP-код.

История изменений

Не используйте GET /api/inventories/{inventory}/history: такого маршрута нет. В текущем API нет отдельного надёжного метода истории складской позиции.

Для аудита сохраняйте в своей системе:

  • ID запроса или операции;
  • inventory.id;
  • склад и номенклатуру;
  • количество и цену до и после изменения;
  • HTTP-код и тело ответа.