RidnaAPI v1

API Ridna

API для сайту магазину. Через нього сайт:

  1. передає замовлення в Ridna — з товарами, покупцем і адресою доставки;
  2. дописує оплату, коли покупець заплатив на сайті;
  3. читає замовлення: статус, товари, покупця, оплати й номер ТТН;
  4. читає товари з ціною й залишком.

Замовлення з API приходить у Ridna так само, як із вітрини. Покупця знаходимо за телефоном. Адреса Нової Пошти чи Укрпошти одразу з кодами, тож ТТН створюється одним тапом. Залишок списується, а власниці приходить пуш «Нове замовлення з сайту».

Версія — v1. Адреси з /v1 не зміняться так, щоб зламати інтеграцію. У відповідях можуть зʼявлятись нові поля — незнайомі просто ігноруй.


Швидкий старт

  1. Отримай ключ. Поки його видає підтримка: напиши в Telegram @ridna_crm, з якого акаунта Ridna ти пишеш. Ключ показуємо один раз — збережи його одразу.
  2. Перевір ключ — попроси перелік товарів:
curl https://api.ridna.net/v1/products?limit=1 \
  -H "Authorization: Bearer ridna_ТВІЙ_КЛЮЧ"
  1. Надішли перше замовлення — приклад нижче, у розділі «Створити замовлення».

Адреса, ключ і обмеження

Адреса 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.

Гроші, дати й номери


Створити замовлення

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": "Подзвоніть перед відправкою"
  }'

Відповідь:

В обох випадках тіло — замовлення в тому ж вигляді, що й у 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.

Як знаходимо товар у каталозі:

  1. За variant_id або product_id. Якщо такого id в магазині немає — 422.
  2. Інакше за sku: спершу серед варіантів, потім серед товарів.
  3. Не знайшли — позиція лягає текстом, без привʼязки до каталогу. Тоді потрібні 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 символів. З ним повтор не запише гроші двічі — передавай завжди.

Відповідь:

В обох випадках у відповіді — оплата і стан оплати замовлення:

{
  "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 }
  }
}

Коли відмовимо:

Накладений платіж не передавай. Його 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 — оплата замовлення:

payments — усі записи оплат:

shipments — ТТН замовлення:

items:


Товари

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
}

Помилки

Помилка завжди має той самий вигляд:

{
  "error": {
    "code": "validation_failed",
    "message": "Потрібен телефон покупця (customer.phone): за ним знаходимо клієнта, і без нього не створиться ТТН",
    "field": "customer.phone"
  }
}
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.