#API Ridna
API для сайту магазину. Через нього сайт:
- передає замовлення в Ridna — з товарами, покупцем і адресою доставки;
- дописує оплату, коли покупець заплатив на сайті;
- читає замовлення: статус, товари, покупця, оплати й номер ТТН;
- читає товари з ціною й залишком.
Замовлення з API приходить у Ridna так само, як із вітрини. Покупця знаходимо за телефоном. Адреса Нової Пошти чи Укрпошти одразу з кодами, тож ТТН створюється одним тапом. Залишок списується, а власниці приходить пуш «Нове замовлення з сайту».
Версія — v1. Адреси з /v1 не зміняться так, щоб зламати інтеграцію. У відповідях можуть зʼявлятись нові поля — незнайомі просто ігноруй.
#Швидкий старт
- Отримай ключ. Поки його видає підтримка: напиши в Telegram @ridna_crm, з якого акаунта Ridna ти пишеш. Ключ показуємо один раз — збережи його одразу.
- Перевір ключ — попроси перелік товарів:
curl https://api.ridna.net/v1/products?limit=1 \
-H "Authorization: Bearer ridna_ТВІЙ_КЛЮЧ"
- Надішли перше замовлення — приклад нижче, у розділі «Створити замовлення».
#Адреса, ключ і обмеження
| Адреса | https://api.ridna.net/v1 |
| Ключ | заголовок Authorization: Bearer ridna_… |
| Формат | JSON у UTF-8, заголовок Content-Type: application/json |
| Тариф | Pro або пробний період |
| Ліміт | 120 запитів за хвилину на один ключ |
Ключ секретний. Надсилай запити лише із сервера сайту, а не з браузера: ключ у JavaScript сторінки побачить будь-хто. Не клади його в репозиторій. Якщо ключ засвітився, напиши нам: відкличемо його й видамо новий.
Тариф. Якщо в магазину не Pro і не пробний період, API відповідає 403 plan_required, а власниця отримує сповіщення, що замовлення з сайту не створено.
Ліміт. Понад 120 запитів за хвилину API відповідає 429 rate_limited із заголовком Retry-After: 60.
#Гроші, дати й номери
- Суми — у гривнях:
1200або1200.5. Рядок"1200.50"теж приймаємо. - Дати — ISO 8601, UTC:
2026-10-31T14:05:12.345Z. - Замовлення має два ідентифікатори.
id— UUID, його повертаємо при створенні.number— номер, який власниця бачить у застосунку («№6401»). У запитах підходить будь-який з них.
#Створити замовлення
POST /v1/orders
curl https://api.ridna.net/v1/orders \
-H "Authorization: Bearer ridna_ТВІЙ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"external_id": "1052",
"customer": {
"first_name": "Олена",
"last_name": "Коваленко",
"phone": "+380671234567",
"email": "olena@example.com"
},
"items": [
{ "sku": "DR-001-M", "qty": 1 },
{ "name": "Подарункове пакування", "price": 50, "qty": 1 }
],
"delivery": {
"carrier": "nova_poshta",
"method": "warehouse",
"city": "Київ",
"warehouse": "Відділення №15"
},
"payment_method": "postpay",
"total": 1250,
"comment": "Подзвоніть перед відправкою"
}'
Відповідь:
201— створено;200— таке замовлення вже є (той самийexternal_id). Повертаємо його ж, нового не створюємо.
В обох випадках тіло — замовлення в тому ж вигляді, що й у GET /v1/orders/{id}, плюс масив warnings.
#Поля
| Поле | Що це | |
|---|---|---|
external_id |
бажано | Номер замовлення на сайті, до 100 символів. З ним повтор того самого запиту не створить дубль — передавай завжди. |
customer |
так | Покупець, див. нижче. |
items |
так | Позиції, від 1 до 100. |
delivery |
ні | Доставка, див. нижче. Без неї замовлення буде без адреси. |
payment_method |
ні | Домовленість про оплату: prepay_full — передоплата 100%, prepay_partial — часткова передоплата, postpay — післяплата (накладений платіж). Без цього поля тип визначить перша оплата. |
discount |
ні | Знижка на все замовлення в гривнях (купон, акція). |
total |
ні | Сума, яку сайт узяв із покупця. Якщо передаси, ми її звіримо: товари мінус знижка мають дати total (з точністю до гривні). Інакше відповімо 422. Радимо передавати: так одразу видно, що ми порахували інакше. |
comment |
ні | Коментар покупця, до 500 символів. Лягає в нотатку замовлення. |
Покупець (customer)
| Поле | Що це | |
|---|---|---|
first_name, last_name |
так* | Імʼя й прізвище окремо — тоді ТТН знає, де що. |
name |
так* | Або повне імʼя одним рядком, якщо окремо їх немає. |
middle_name |
ні | По батькові. Для Укрпошти з оплатою при отриманні без нього ТТН не створиться. |
phone |
так | Телефон. Український номер у будь-якому вигляді (0671234567, +38 (067) 123-45-67) зведемо до +380671234567. |
email |
ні | Пошта. |
instagram |
ні | Нік або посилання на профіль. |
* Потрібне або first_name з last_name, або name.
Покупця шукаємо серед контактів магазину за телефоном, потім за ніком Instagram. Тоді замовлення лягає на того самого клієнта, з яким уже є переписка в Direct. Не знайшли — створюємо нового.
Позиції (items)
| Поле | Що це |
|---|---|
product_id, variant_id |
Id товару й варіанта з GET /v1/products. |
sku |
Або артикул товару чи варіанта. |
name |
Назва — потрібна, якщо товару немає в каталозі Ridna. |
price |
Ціна за одиницю, за яку купили на сайті. Не передаси — візьмемо ціну й знижку з каталогу Ridna. Для товару не з каталогу обовʼязкова. |
qty |
Кількість, від 1 до 999. За замовчуванням 1. |
Як знаходимо товар у каталозі:
- За
variant_idабоproduct_id. Якщо такого id в магазині немає —422. - Інакше за
sku: спершу серед варіантів, потім серед товарів. - Не знайшли — позиція лягає текстом, без привʼязки до каталогу. Тоді потрібні
nameіprice.
Доставка, яку сайт бере з покупця. Окремого поля для неї в Ridna немає. Передай її окремою позицією, наприклад
{ "name": "Доставка", "price": 70 }. Тоді сума замовлення зійдеться з тим, що заплатив покупець.
Залишок. Позицію, привʼязану до товару з обліком залишку, списуємо, як продаж у застосунку. Якщо залишку не вистачає, замовлення однаково створюємо: сайт його вже продав. У warnings і в нотатці замовлення буде, що саме не списали.
У товару з варіантами залишок живе у варіантах. Тому передавай варіант: variant_id або артикул варіанта. Якщо прийде сам товар без варіанта, залишок не спишемо, а в warnings попросимо вказати варіант.
Доставка (delivery)
carrier |
method |
Обовʼязково | Бажано |
|---|---|---|---|
nova_poshta |
warehouse, postomat |
city, warehouse — номер ("15") або назва ("Відділення №15") |
city_ref, warehouse_ref — якщо сайт уже працює з API Нової Пошти |
nova_poshta |
courier |
city, street, building |
city_ref, street_ref, flat |
ukrposhta |
warehouse, postomat, pudo |
postcode — індекс відділення, 5 цифр |
city |
ukrposhta |
courier |
postcode, street, building |
flat |
pickup |
— | — | address. Без нього — адреса самовивозу з налаштувань магазину |
other |
— | address — куди везти, текстом |
city |
Без кодів Нової Пошти ми самі знайдемо місто й відділення за назвою та номером. Не знайшли — замовлення однаково створюємо, але в warnings про це скажемо, і ТТН власниця заповнить уручну. Для курʼєра Нової Пошти без street_ref вулицю доведеться обрати в застосунку.
#warnings
Масив рядків. Він каже, що замовлення створено, але щось варто перевірити:
"warnings": [
"Не знайшли «Відділення №1500» у місті «Київ» у Новій Пошті — ТТН заповниш вручну",
"Залишку не вистачило — не списали: Сукня льон — M"
]
#Записати оплату
POST /v1/orders/{id}/payments
Надсилай, щойно сайт отримав гроші: після відповіді платіжки (LiqPay, WayForPay, monobank тощо) чи після переказу на рахунок. Без цього Ridna вважатиме замовлення неоплаченим, і ТТН із накладеним платежем візьме з покупця всю суму вдруге.
curl https://api.ridna.net/v1/orders/6402/payments \
-H "Authorization: Bearer ridna_ТВІЙ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{ "amount": 1250, "method": "online", "external_id": "liqpay-2266718907" }'
| Поле | Що це | |
|---|---|---|
amount |
так | Сума в гривнях, більша за нуль. |
method |
ні | online — онлайн-оплата (за замовчуванням), transfer — переказ на рахунок, cash — готівка. |
external_id |
бажано | Номер оплати на сайті чи в платіжці, до 100 символів. З ним повтор не запише гроші двічі — передавай завжди. |
Відповідь:
201— записали;200— оплата з такимexternal_idуже є, повертаємо її.
В обох випадках у відповіді — оплата і стан оплати замовлення:
{
"id": "0b8e2f7a-5d1c-4c3e-9a77-2f4b6c8d9e10",
"external_id": "liqpay-2266718907",
"amount": 1250,
"method": "online",
"status": "success",
"refund_of": null,
"created_at": "2026-10-31T14:07:40.120Z",
"order": {
"id": "4d2e1f0a-9b8c-4d7e-a6f5-3c2b1a0f9e8d",
"number": 6402,
"status": "new",
"status_label": "Нове",
"payment": { "method": "prepay_full", "status": "paid", "paid": 1250, "due": 0 }
}
}
Коли відмовимо:
- Більше, ніж лишилось сплатити, —
422 overpayment. Найчастіше це та сама оплата вдруге під іншим номером. - Той самий
external_idз іншою сумою —409 conflict. - Скасоване замовлення —
422 order_cancelled.
Накладений платіж не передавай. Його Ridna записує сама, коли замовлення виконано.
Чеки Checkbox. Якщо в магазині ввімкнені автоматичні чеки Checkbox, Ridna випише чек і на оплату з сайту. Сайт чи платіжка вже видає фіскальний чек сама? Тоді автоматичні чеки в Ridna треба вимкнути, інакше на ті самі гроші вийде два чеки.
#Прочитати замовлення
GET /v1/orders/{id} — за id (UUID) або номером (number).
curl https://api.ridna.net/v1/orders/6401 \
-H "Authorization: Bearer ridna_ТВІЙ_КЛЮЧ"
{
"id": "6a0f8a3e-2c4b-4f1e-9d6a-1b2c3d4e5f60",
"number": 6401,
"external_id": "1052",
"source": "api",
"status": "shipped",
"status_label": "Відправлено",
"cancel_reason": null,
"created_at": "2026-10-31T14:05:12.345Z",
"total": 1250,
"discount": null,
"payment": { "method": "postpay", "status": "unpaid", "paid": 0, "due": 1250 },
"customer": {
"id": "1c9d4b7e-8f2a-4e6b-b3c1-0a9e8d7c6b5a",
"name": "Олена Коваленко",
"first_name": "Олена",
"last_name": "Коваленко",
"middle_name": null,
"phone": "+380671234567",
"email": "olena@example.com",
"instagram": null
},
"delivery": {
"carrier": "nova_poshta",
"method": "warehouse",
"city": "м. Київ, Київська обл.",
"city_ref": "8d5a980d-391c-11dd-90d9-001a92567626",
"warehouse": "Відділення №15 (до 30 кг на одне місце): вул. Приклад, 1",
"warehouse_ref": "7b422fc5-e1b8-11e3-8c4a-0050568002cf",
"postcode": null,
"street": null,
"street_ref": null,
"building": null,
"flat": null
},
"items": [
{
"id": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9",
"product_id": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"variant_id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"sku": "DR-001-M",
"name": "Сукня льон — M",
"variant": "M",
"price": 1200,
"discount": null,
"final_price": 1200,
"qty": 1,
"total": 1200
},
{
"id": "7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
"product_id": null,
"variant_id": null,
"sku": null,
"name": "Подарункове пакування",
"variant": null,
"price": 50,
"discount": null,
"final_price": 50,
"qty": 1,
"total": 50
}
],
"payments": [],
"shipments": [
{
"ttn": "20451234567890",
"carrier": "nova_poshta",
"status": null,
"status_at": null,
"cash_on_delivery": 1250,
"created_at": "2026-10-31T16:20:03.000Z"
}
],
"comment": "Подзвоніть перед відправкою"
}
status — статус замовлення в Ridna. Власниця змінює його вручну, тож статуси можуть іти не по порядку.
status |
status_label |
|---|---|
new |
Нове |
processing |
В обробці |
paid |
Оплачено |
ready_to_ship |
Готово до відправки |
shipped |
Відправлено |
awaiting_customer |
Чекає клієнта |
done |
Виконано |
cancelled |
Скасовано (причина — у cancel_reason) |
payment — оплата замовлення:
status—unpaid,partialабоpaid;paid— скільки сплачено;due— скільки лишилось;method— домовленість про оплату (див.payment_methodвище).
payments — усі записи оплат:
status: "success"— гроші прийшли;- від'ємна сума з
refund_of— повернення.
shipments — ТТН замовлення:
cash_on_delivery— сума накладеного платежу, абоnull, якщо його немає;status— останній статус посилки Укрпошти (CREATED,REGISTERED,DELIVERING…). Для Нової Пошти вінnull, а стан посилки видно вstatusзамовлення.
items:
price— ціна за одиницю;final_price— ціна після знижки;total—final_price × qty;sku— артикул, як він зараз записаний у каталозі.
#Товари
GET /v1/products — товари магазину з ціною й залишком.
| Параметр | Що це |
|---|---|
sku |
Лише товар із цим артикулом — свій або артикул одного з варіантів. |
limit |
Скільки на сторінці, від 1 до 200. За замовчуванням 100. |
offset |
Скільки пропустити — для наступних сторінок. |
curl "https://api.ridna.net/v1/products?limit=100&offset=0" \
-H "Authorization: Bearer ridna_ТВІЙ_КЛЮЧ"
{
"data": [
{
"id": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"name": "Сукня льон",
"sku": "DR-001",
"category": "Сукні",
"brand": null,
"price": 1200,
"discount": null,
"final_price": 1200,
"stock": null,
"variants": [
{ "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e", "name": "M", "sku": "DR-001-M", "price": 1200, "discount": null, "final_price": 1200, "stock": 3 },
{ "id": "3c4d5e6f-7a8b-4c9d-8e0f-2a3b4c5d6e7f", "name": "L", "sku": "DR-001-L", "price": 1300, "discount": { "type": "fixed", "value": 100 }, "final_price": 1200, "stock": 0 }
]
}
],
"limit": 100,
"offset": 0,
"has_more": false
}
stock— скільки є в наявності.nullозначає, що облік не ведеться (послуга, товар під замовлення): такий товар доступний завжди.- Товар з варіантами. Залишок і ціна — у
variants.stockсамого товару — сума залишків варіантів, як у застосунку; якщо хоч один варіант без обліку —null. final_price— ціна після знижки: стільки заплатить покупець.discount—{ "type": "percent" | "fixed", "value": … }абоnull.- Порядок — за часом додавання товару. Поки
has_more: true, проси наступну сторінку зoffset+limit.
#Помилки
Помилка завжди має той самий вигляд:
{
"error": {
"code": "validation_failed",
"message": "Потрібен телефон покупця (customer.phone): за ним знаходимо клієнта, і без нього не створиться ТТН",
"field": "customer.phone"
}
}
code— стабільний, по ньому розгалужуй логіку.message— для людини, що налаштовує інтеграцію.field— яке поле не так. Є не завжди.
| HTTP | code |
Коли |
|---|---|---|
| 400 | bad_json |
Тіло — не JSON-обʼєкт |
| 401 | unauthorized |
Немає ключа, він неправильний або відкликаний |
| 403 | plan_required |
У магазину не Pro і не пробний період |
| 404 | not_found |
Немає такої адреси або замовлення (чуже замовлення теж «немає») |
| 405 | method_not_allowed |
Адреса приймає інший метод |
| 409 | conflict |
Оплата з цим external_id уже є, але на іншу суму |
| 413 | too_large |
Запит більший за 256 КБ |
| 422 | validation_failed |
Поле відсутнє або неправильне — див. field |
| 422 | overpayment |
Оплата більша за залишок до сплати |
| 422 | order_cancelled |
Оплата до скасованого замовлення |
| 429 | rate_limited |
Понад 120 запитів за хвилину |
| 500 | internal |
Збій на нашому боці. Повтори за хвилину: з external_id дубля не буде |
#Часті питання
Сайт не дочекався відповіді — повторювати?
Так, з тим самим external_id. Якщо замовлення чи оплата вже записались, отримаєш 200 і той самий запис, а не дубль.
Як дізнатись, що замовлення відправили?
Питай GET /v1/orders/{id}: status стане shipped, а в shipments зʼявиться номер ТТН. Повідомлень від Ridna на сайт (вебхуків) поки немає.
Як не продати те, що вже пішло в Direct?
Перед оформленням перевір залишок через GET /v1/products?sku=…. Або раз на кілька хвилин забирай увесь каталог і оновлюй наявність на сайті.
Чи можна передати замовлення, якого товару немає в Ridna?
Так. Передай name і price, і позиція ляже текстом. Каталог Ridna з таких позицій не поповнюється.
Є питання чи чогось не вистачає? Пиши в Telegram @ridna_crm.