Интернет-заказ из внешней системы
Задача: интернет-магазин или маркетплейс оформляет заказ у себя и должен провести его в BILLZ как продажу конкретного магазина — с покупателем, скидкой и оплатой.
Развилка в терминах
Заголовок раздела «Развилка в терминах»Слово «заказ» в BILLZ занято.
| Формулировка задачи | Как это называется в BILLZ | Методы |
|---|---|---|
| Покупатель заказал товар на сайте | Продажа (Order, чек продажи) |
/v2/order, /v2/order-product, /v2/order-payment |
| Товар заказан у поставщика | Заказ поставщику (SupplierOrder) |
/v2/supplier-order, /v2/supplier-order/add-item |
Для интернет-заказа нужна первая строка.
Схема сценария
Заголовок раздела «Схема сценария»GET /v1/shop, /v1/company-payment-type справочники, один раз │GET /v1/client?phone_number=… найти клиентаPOST /v1/client создать, если не нашёлся │POST /v2/order {shop_id, cashbox_id} создать продажу ──> order_idPOST /v2/order-product/:order_id добавить товар (по одному)PUT /v2/order-customer-new/:order_id привязать клиентаPOST /v2/order-manual-discount/:order_id скидкаPOST /v1/recalculate-order-bill/:order_id сверить суммуPOST /v2/order-payment/:order_id завершить продажу │GET /v2/order/:id детали проведённой продажиСоздание продажи и методы, меняющие состав чека, — асинхронные: требуется заголовок
Billz-Response-Channel: HTTP, иначе вместо результата приходит идентификатор события.
Пересчёт и оплата — синхронные, им заголовок не нужен.
1. Клиент
Заголовок раздела «1. Клиент»curl -X GET 'https://api-admin.billz.ai/v1/client?phone_number=%2B998900000000&limit=10&page=1' \ -H 'Authorization: Bearer ТОКЕН'Параметры: phone_number, search, chat_id, limit, page. Ответ — {count, clients[]}.
Подробная карточка по найденному ID — GET /v1/customer/:id (у неё другой, более широкий
набор полей, чем у элемента clients[]).
search ищет подстроку по имени, фамилии, отчеству, телефонам, external_id, chat_id,
дате рождения, коду и названию карты лояльности. Несколько слов через пробел — «И».
Спецсимволы вырезаются: +998901234567 и 998901234567 равнозначны.
phone_number ищет по подстроке, chat_id — по точному совпадению.
Создание
Заголовок раздела «Создание»curl -X POST 'https://api-admin.billz.ai/v1/client' \ -H 'Authorization: Bearer ТОКЕН' \ -H 'Content-Type: application/json' \ -d '{ "first_name": "Иван", "last_name": "Петров", "phone_number": "+998900000000", "gender": 1, "date_of_birth": "1990-05-14" }'Ответ — { "id": "..." }: UUID клиента, который сохраняется во внешней системе.
gender: 1 — мужской, 2 — женский, прочие значения записываются как пустое.
2. Создать продажу в нужном магазине
Заголовок раздела «2. Создать продажу в нужном магазине»Продажа создаётся асинхронным методом POST /v2/order. Канал ответа задаётся заголовком
Billz-Response-Channel: HTTP или одноимённым query-параметром — как в примере ниже.
curl -X POST 'https://api-admin.billz.ai/v2/order?Billz-Response-Channel=HTTP' \ -H 'Authorization: Bearer ТОКЕН' \ -H 'Content-Type: application/json' \ -d '{ "shop_id": "c1056fcc-539b-47ea-8bc4-d9e337c433f0", "cashbox_id": "9b4a7f8c-a8ef-4870-8a1b-89869fdd4141" }'{ "session_id": "fd8d352a-6299-4489-8a6e-a5c037f3f65b", "status_code": 200, "id": "38c3920a-ffdd-4233-a823-8af3266f5f4f", "error": { "code": "", "message": "" }, "data": { "id": "38c3920a-ffdd-4233-a823-8af3266f5f4f", "order_number": "5632631379", "order_type": "SALE" }, "correlation_id": "3674f28e-7b96-4683-87c3-80892698f421"}UUID продажи — поле id (то же значение в data.id), он подставляется во все следующие
шаги. order_number — короткий номер продажи, который видит кассир в интерфейсе.
Магазин выбирается полем shop_id, касса — полем cashbox_id. Список магазинов —
GET /v1/shop.
3. Добавить товары
Заголовок раздела «3. Добавить товары»По одному товарному наименованию на запрос.
curl -X POST 'https://api-admin.billz.ai/v2/order-product/ID_ПРОДАЖИ' \ -H 'Authorization: Bearer ТОКЕН' \ -H 'Content-Type: application/json' \ -H 'Billz-Response-Channel: HTTP' \ -d '{ "product_id": "2ce40c63-4527-4898-a975-7c30c255fd50", "sold_measurement_value": 2, "used_wholesale_price": false }'Это upsert с абсолютным количеством: повторный вызов с тем же product_id
заменяет количество. sold_measurement_value: 0 удаляет позицию из чека.
4. Привязать клиента
Заголовок раздела «4. Привязать клиента»curl -X PUT 'https://api-admin.billz.ai/v2/order-customer-new/ID_ПРОДАЖИ' \ -H 'Authorization: Bearer ТОКЕН' \ -H 'Content-Type: application/json' \ -H 'Billz-Response-Channel: HTTP' \ -d '{ "customer_id": "ID_КЛИЕНТА", "check_auth_code": false }'Ответ приходит в конверте: объект лежит в поле data.
5. Скидка
Заголовок раздела «5. Скидка»curl -X POST 'https://api-admin.billz.ai/v2/order-manual-discount/ID_ПРОДАЖИ' \ -H 'Authorization: Bearer ТОКЕН' \ -H 'Content-Type: application/json' \ -H 'Billz-Response-Channel: HTTP' \ -d '{ "discount_unit": "PERCENTAGE", "discount_value": 10 }'discount_unit — PERCENTAGE или CURRENCY. Необязательный product_id применяет скидку
к одной позиции; без него — на всю корзину.
Ручная скидка запускает пересчёт корзины заново: оплата вызывается после асинхронного ответа на скидку.
6. Сверить сумму
Заголовок раздела «6. Сверить сумму»curl -X POST 'https://api-admin.billz.ai/v1/recalculate-order-bill/ID_ПРОДАЖИ' \ -H 'Authorization: Bearer ТОКЕН'Метод синхронный, возвращает актуальный чек с позициями, скидками и итогом.
Для отложенной продажи метод отказывает.
7. Завершить продажу
Заголовок раздела «7. Завершить продажу»curl -X POST 'https://api-admin.billz.ai/v2/order-payment/ID_ПРОДАЖИ' \ -H 'Authorization: Bearer ТОКЕН' \ -H 'Content-Type: application/json' \ -d '{ "payments": [ { "company_payment_type_id": "c6e84d9b-...", "paid_amount": 900000, "returned_amount": 0 } ], "comment": "Заказ №12345 с сайта", "without_cashback": false }'| Поле | Смысл |
|---|---|
payments[] |
список оплат; несколько элементов — оплата разными способами |
payments[].company_payment_type_id |
тип оплаты из GET /v1/company-payment-type |
payments[].paid_amount |
внесённая сумма |
payments[].returned_amount |
сдача |
payments[].gift_card_id |
целое число; нужно для оплаты подарочной картой |
with_cashback |
сумма (не флаг), погашаемая бонусами клиента |
without_cashback |
true — не начислять кешбэк за эту продажу |
sold_at |
дата и время продажи в формате YYYY-MM-DD HH:MM:SS — для проведения задним числом |
comment |
номер заказа внешней системы; пустая строка не затирает прежний |
skip_ofd |
снимает проверки ОФД перед оплатой, см. ниже |
Метод синхронный. В ответ приходит {"order_type": "SALE", "should_print_cheque": true}
со статусом 200.
Коды ошибок оплаты
Заголовок раздела «Коды ошибок оплаты»Ошибка приходит с HTTP 400, а номер причины лежит внутри data:
{ "status_code": 400, "error": { "code": "", "message": "status: 400 - errors: Bad request - causes: ..." }, "data": { "error_code": 20084, "message": "payment is possible only for calculated order" }}Причина определяется по data.error_code: поле error.code в этом ответе пустое.
| Код | Сообщение | Что означает |
|---|---|---|
20009 |
cashbox shop id and order shop id are different | текущая касса пользователя из другого магазина |
20010 |
user’s current cashbox id is empty | в магазине продажи нет открытой кассы |
20011 |
cashbox has not enough money | в кассе не хватает денег на возврат |
20015 |
order does not have items | в чеке нет позиций |
20016 |
not enough product | не хватает остатка; доступное количество — в data.data |
20017 |
order is deleted | продажа удалена |
20020 |
wrong payment amount | сумма оплат не сходится; в data — total_price и claimed_amount |
20047 |
not enough funds in customer balance | не хватает бонусов под with_cashback |
20063 |
order not sent to epos | чек не отправлен в ОФД (снимается флагом skip_ofd) |
20082 |
cannot make payment with closed cashbox | касса закрыта |
20084 |
payment is possible only for calculated order | корзина не пересчитана, см. шаг 3 |
claimed_amount — сумма paid_amount минус returned_amount по всем элементам,
плюс with_cashback, плюс долг; сверяется с итогом чека.
8. ID продажи и детали
Заголовок раздела «8. ID продажи и детали»ID возвращается на шаге 2. Полные детали проведённой продажи — позиции, оплаты, скидки, клиент:
curl -X GET 'https://api-admin.billz.ai/v2/order/ID_ПРОДАЖИ' \ -H 'Authorization: Bearer ТОКЕН'Ответы на частые уточнения
Заголовок раздела «Ответы на частые уточнения»Каким полем выбирается магазин
Заголовок раздела «Каким полем выбирается магазин»Полем shop_id в теле POST /v2/order; там же задаётся касса — cashbox_id.
Список магазинов — GET /v1/shop.
Можно ли оформить продажу при нехватке остатка
Заголовок раздела «Можно ли оформить продажу при нехватке остатка»Это управляется настройкой товара «разрешить отрицательный остаток». Если она выключена, добавление товара сверх остатка не пройдёт; если включена — остаток уйдёт в минус.
Ошибка — HTTP 400, data.error_code = 20016, data.message = not enough product;
доступное количество приходит в data.data.
Предварительная проверка остатка — GET /v2/products →
shop_measurement_values[].active_measurement_value по нужному shop_id. Между проверкой
и оплатой товар может быть продан офлайн: отказ на оплате также обрабатывается.
В каком виде отдаётся накладная
Заголовок раздела «В каком виде отдаётся накладная»Готовой накладной или печатной формы по продаже публичный API не отдаёт.
| Что нужно | Чем закрывается |
|---|---|
| Своя печатная форма | GET /v2/order/:id — позиции, цены, скидки, оплаты, магазин, клиент; вёрстка на стороне внешней системы |
| Выгрузка для бухгалтерии | отчёты /v1/general-report-table, /v1/transaction-report-table |
Какой идентификатор хранить у себя
Заголовок раздела «Какой идентификатор хранить у себя»UUID продажи (id из конверта ответа шага 2). order_number предназначен
для переписки с поддержкой.
- Связь «номер заказа внешней системы → UUID продажи BILLZ» хранится на стороне внешней системы; UUID записывается сразу после шага 2, до добавления товаров.
- Перед созданием продажи проверяется, нет ли уже записи по этому заказу.
- Номер заказа внешней системы передаётся в
commentпри оплате: дубль виден в интерфейсе BILLZ и в отчётах.
Разбор 403 — в решении проблем, полный перечень
доступного ключу — в справочнике.
Выпуск ключа открывает базовый набор методов; чувствительные методы открывают отдельно, настройкой прав ключа.
Сводка методов
Заголовок раздела «Сводка методов»| Шаг | Метод | Тип |
|---|---|---|
| Список магазинов | GET /v1/shop |
sync |
| Типы оплат | GET /v1/company-payment-type |
sync |
| Поиск клиента | GET /v1/client |
sync |
| Карточка клиента | GET /v1/customer/:id |
sync |
| Создать клиента | POST /v1/client |
sync |
| Изменить клиента | PUT /v1/client/:id |
sync |
| Создать продажу | POST /v2/order |
async |
| Добавить товар | POST /v2/order-product/:order_id |
async |
| Привязать клиента | PUT /v2/order-customer-new/:order_id |
async |
| Скидка | POST /v2/order-manual-discount/:order_id |
async |
| Сверить сумму | POST /v1/recalculate-order-bill/:order_id |
sync |
| Завершить продажу | POST /v2/order-payment/:order_id |
sync |
| Детали продажи | GET /v2/order/:id |
sync |