Перейти к содержанию

Доставка и точки самовывоза

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

Если этого права нет, ответ 403:

{"status":"error","message":"Недостаточно прав для операции"}

Доставка

GET /admin/delivery_variants.json отдаёт все способы доставки магазина, по полю position. GET /admin/delivery_variants/by_ids.json отвечает 404, тело — HTML-страница. Несколько способов читаются общим списком или отдельным GET /admin/delivery_variants/:id.json. Неизвестный id тоже отвечает 404 и HTML.

В общем объекте есть id, position, title, description, type, charge_up_to, inverted, show_zip_code, min_order_sum, payment_delivery_variants, delivery_locations, delivery_time_intervals, created_at, updated_at. У типов с датой доставки рядом лежат show_calendar_in_checkout, delivery_date_required, forbid_weekends, utc_from_address, estimated_delivery_period, order_time_is_later, forbidden_days, show_time_intervals_in_checkout, time_intervals_required.

payment_delivery_variants — связи со способами оплаты. Пока связь не создана, покупатель этот способ оплаты для этой доставки не видит. add_payment_gateways: true при создании привязывает все способы оплаты, которые уже есть в магазине. В ответе этого ключа нет.

min_order_sum в ответе есть. Передача 1000 в теле создания оставляет в объекте null.

Ключ delivery_locations — города и регионы, для которых способ доступен. Локация передаётся массивом delivery_locations_attributes или объектом с числовыми ключами. В каждой локации нужны country и region. city можно передать null: локация остаётся на весь регион. Регион обл Ленинградская при city: null сохраняется этой же строкой. Город без региона отвечает 422:

{"delivery_locations.sanitized_region_name": ["Не заполнены обязательные поля"]}

Неизвестное имя региона сохраняется как передано. Удаление локации — тот же массив с id и _destroy: 1.

У способа «от локации» тарифные зоны живут в delivery_zones. Город зоны задаётся в locations_attributes внутри зоны. delivery_locations_attributes у этого типа пишет отдельный список delivery_locations и зону не меняет.

Тип вне списка, например DeliveryVariant::Unknown или DeliveryVariant::NovaPoshta, отвечает 422. Текст ошибки — отсутствующий перевод not_in_variants_list.

В списке магазина встречаются и другие типы. DeliveryVariant::None тоже хранит price. DeliveryVariant::NoDelivery — способ «доставка не требуется», у него нет полей даты доставки. Точки самовывоза относятся к DeliveryVariant::PickUp, а не к способу с названием «Самовывоз», если у того другой type.

DELETE /admin/delivery_variants/:id.json отвечает 200 и {"status":"ok"}.

Дата и интервалы

У фиксированной доставки, внешней, от локации, от суммы и самовывоза в том же объекте задаются календарь и интервалы времени. Список интервалов пишется строкой time_intervals, пары часов через запятую: 10-14,14-18. В ответе строка уже разобрана в delivery_time_intervals: у каждого интервала time_from, time_to и дни недели. Для такой строки все семь дней приходят true.

Повторная запись time_intervals оставляет уже сохранённые интервалы. Флаги календаря при этом меняются: show_calendar_in_checkout, estimated_delivery_period, forbidden_days, delivery_date_required, forbid_weekends, order_time_is_later, show_time_intervals_in_checkout, time_intervals_required.

Часы вроде 10:00-14:00 отвечают 422:

{"time_intervals": ["Некорректный формат! Пример: 10-14, 14-18, 18-22\n"]}
POST/admin/delivery_variants.json
Параметр Описание
delivery_variant[time_intervals] необязательный
строка
Интервалы часов: 10-14,14-18.
delivery_variant[show_time_intervals_in_checkout] необязательный
логический
Показывать интервалы при оформлении.
delivery_variant[time_intervals_required] необязательный
логический
Интервал обязателен.
delivery_variant[show_calendar_in_checkout] необязательный
логический
Показывать календарь даты доставки.
delivery_variant[delivery_date_required] необязательный
логический
Дата доставки обязательна.
delivery_variant[forbid_weekends] необязательный
логический
Запретить выходные.
delivery_variant[estimated_delivery_period] необязательный
число
Срок в днях.
delivery_variant[order_time_is_later] необязательный
строка
Время отсечки, например 15:00.
delivery_variant[forbidden_days] необязательный
строка
Запрещённые дни: 01.01,09.05.
POST /admin/delivery_variants.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "delivery_variant": {
    "type": "DeliveryVariant::PriceDepend",
    "title": "docs-api интервалы",
    "min_price": 0,
    "rules_attributes": [
      {"order_price": 1, "price": 100}
    ],
    "show_calendar_in_checkout": true,
    "delivery_date_required": true,
    "forbid_weekends": true,
    "estimated_delivery_period": 2,
    "order_time_is_later": "15:00",
    "forbidden_days": "01.01,09.05",
    "show_time_intervals_in_checkout": true,
    "time_intervals_required": true,
    "time_intervals": "10-14,14-18"
  }
}

Ответ · 201

{
  "id": 105,
  "type": "DeliveryVariant::PriceDepend",
  "show_calendar_in_checkout": true,
  "delivery_date_required": true,
  "forbid_weekends": true,
  "estimated_delivery_period": 2,
  "order_time_is_later": "15:00",
  "forbidden_days": "01.01,09.05",
  "show_time_intervals_in_checkout": true,
  "time_intervals_required": true,
  "delivery_time_intervals": [
    {
      "time_from": "10:00",
      "time_to": "14:00",
      "monday": true,
      "tuesday": true,
      "wednesday": true,
      "thursday": true,
      "friday": true,
      "saturday": true,
      "sunday": true
    },
    {
      "time_from": "14:00",
      "time_to": "18:00",
      "monday": true,
      "tuesday": true,
      "wednesday": true,
      "thursday": true,
      "friday": true,
      "saturday": true,
      "sunday": true
    }
  ]
}

Фиксированная

DeliveryVariant::Fixed требует price. Цена ноль и больше допустима. charge_up_to — сумма товаров, начиная с которой доставка бесплатна.

POST/admin/delivery_variants.json
Параметр Описание
delivery_variant[type] обязательный
строка
DeliveryVariant::Fixed.
delivery_variant[title] обязательный
строка
Название в чекауте и в бэк-офисе.
delivery_variant[price] обязательный
число
Цена доставки. Ноль и больше.
delivery_variant[description] необязательный
строка
Описание. Сохраняется как переданный текст.
delivery_variant[charge_up_to] необязательный
число
Сумма товаров, с которой доставка бесплатна.
delivery_variant[add_payment_gateways] необязательный
логический
Привязать все текущие способы оплаты.
delivery_variant[delivery_locations_attributes] необязательный
массив
Локации. У элемента country и region.
POST /admin/delivery_variants.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "delivery_variant": {
    "type": "DeliveryVariant::Fixed",
    "title": "docs-api фиксированная",
    "price": 350,
    "description": "По городу",
    "charge_up_to": "5000.0",
    "add_payment_gateways": true,
    "delivery_locations_attributes": [
      {"country": "RU", "region": "Москва", "city": "Москва"}
    ]
  }
}

Ответ · 201

{
  "id": 49,
  "position": 3,
  "type": "DeliveryVariant::Fixed",
  "title": "docs-api фиксированная",
  "description": "По городу",
  "price": "350.0",
  "charge_up_to": "5000.0",
  "inverted": false,
  "show_zip_code": false,
  "min_order_sum": null,
  "javascript": null,
  "payment_delivery_variants": [
    {"id": 4, "payment_gateway_id": 6101770}
  ],
  "delivery_locations": [
    {"id": 1, "country": "RU", "region": "Москва", "city": "Москва"}
  ],
  "delivery_time_intervals": []
}

Без price ответ 422, тело {"price":["Не заполнены обязательные поля"]}.

Внешняя

DeliveryVariant::External считает стоимость на адресе url. api_version равен v2 или остаётся пустым. Пустое значение запускает расчёт первой версии. В объекте ответа этого ключа нет, поэтому переданное v2 хранят у себя. javascript сохраняется и возвращается строкой. customer_pickup тоже есть в ответе.

Адрес http://127.0.0.1/... отвечает 422, тело {"url":["Недопустимый URL"]}.

POST/admin/delivery_variants.json
Параметр Описание
delivery_variant[type] обязательный
строка
DeliveryVariant::External.
delivery_variant[title] обязательный
строка
Название способа.
delivery_variant[url] обязательный
строка
Адрес расчёта, http или https, не локальный.
delivery_variant[api_version] необязательный
строка
v2 — вторая версия расчёта. Пусто — первая. В ответ ключ не входит.
delivery_variant[javascript] необязательный
строка
Скрипт способа. Возвращается как передан.
delivery_variant[customer_pickup] необязательный
логический
Самовывоз. Есть в ответе внешней доставки.
POST /admin/delivery_variants.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "delivery_variant": {
    "type": "DeliveryVariant::External",
    "title": "docs-api внешняя",
    "url": "https://example.com/delivery",
    "api_version": "v2",
    "javascript": "console.log('docs-api')",
    "customer_pickup": false
  }
}

Ответ · 201

{
  "id": 65,
  "type": "DeliveryVariant::External",
  "title": "docs-api внешняя",
  "url": "https://example.com/delivery",
  "javascript": "console.log('docs-api')",
  "customer_pickup": false,
  "payment_delivery_variants": [],
  "delivery_locations": [],
  "delivery_time_intervals": []
}

Первая версия: магазин делает GET на url и дописывает query. В запросе есть price (сумма товаров со скидкой), weight, region, city, zip, kladr_code, вложенный location и callback=external. Дополнительные поля заказа и адреса в этот запрос не входят. Ответ сервиса — текст, внутри которого есть external(...). В скобках JSON с delivery_price. Ошибка — error или массив errors. Строка Current carrier is not available! помечает способ недоступным. Ожидание ответа — 4 секунды.

Вторая версия: магазин делает POST на url, заголовок Content-Type: application/json; charset=UTF-8, тело {"order": ...}. В order есть account_id, currency_iso_code, delivery_variant_id, warehouse_id, items_price, total_weight, shipping_address (full_locality_name, delivery_address, location) и order_lines (product_id, variant_id, quantity, weight, dimensions). Дополнительных полей заказа в этом теле нет. Ответ — JSON-массив объектов. У тарифа магазин читает price, tariff_id, title, description, delivery_interval, shipping_company, shipping_company_handle, warnings, errors, fields_values, outlet. Пустой массив, не-JSON и HTTP-ошибка означают, что расчёт стоимости не получен. Ожидание ответа — 6 секунд. Если тарифов несколько, при повторном расчёте магазин ищет элемент с тем же tariff_id.

outlet в тарифе второй версии — пункт выдачи: адрес и описание приходят из ответа сервиса. Пустые address и description в заказе означают, что сервис прислал их пустыми.

Выбранный тариф записывается в заказ ключом order[delivery_info_attributes]. В объекте сохраняются tariff_id, price, title, shipping_company_handle, delivery_interval и outlet. В заказе они возвращаются в delivery_info. Создание заказа описано в заказах.

От локации

DeliveryVariant::LocationDepend требует хотя бы одну зону. Пустой способ отвечает 422, тело {"delivery_zones":["не может быть пустым"]}.

У зоны есть title, массив tariffs_attributes и массив locations_attributes. У тарифа обязательны max_weight, price, step и step_price. Без step и step_price ответ 422, у обоих полей текст «Не заполнены обязательные поля» и «не является числом». step и step_price задают доплату за каждый следующий шаг веса после max_weight.

POST/admin/delivery_variants.json
Параметр Описание
delivery_variant[type] обязательный
строка
DeliveryVariant::LocationDepend.
delivery_variant[title] обязательный
строка
Название способа.
delivery_variant[delivery_zones_attributes] обязательный
массив
Хотя бы одна зона с тарифом и локацией.
delivery_zones_attributes[][title] необязательный
строка
Название зоны.
delivery_zones_attributes[][tariffs_attributes] необязательный
массив
Тарифы: max_weight, price, step, step_price.
delivery_zones_attributes[][locations_attributes] необязательный
массив
Локации зоны: country, region, city.
POST /admin/delivery_variants.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "delivery_variant": {
    "type": "DeliveryVariant::LocationDepend",
    "title": "docs-api от локации",
    "delivery_zones_attributes": [
      {
        "title": "Москва",
        "tariffs_attributes": [
          {"max_weight": 5, "price": 300, "step": 1, "step_price": 50}
        ],
        "locations_attributes": [
          {"country": "RU", "region": "Москва", "city": "Москва"}
        ]
      }
    ]
  }
}

Ответ · 201

{
  "id": 57,
  "type": "DeliveryVariant::LocationDepend",
  "title": "docs-api от локации",
  "delivery_zones": [
    {
      "id": 1,
      "title": "Москва",
      "tariffs": [
        {
          "id": 1,
          "max_weight": "5.0",
          "price": "300.0",
          "step": "1.0",
          "step_price": "50.0"
        }
      ],
      "locations": [
        {"id": 9, "country": "RU", "region": "Москва", "city": "Москва"}
      ]
    }
  ]
}

От суммы

DeliveryVariant::PriceDepend требует min_price — цену, когда ни одно правило не подошло. Правила — rules_attributes. У правила order_price строго больше нуля. Ноль отвечает 422, тело {"rules.order_price":["Стоимость заказа должна быть больше нуля"]}. order_weight можно передать вместе с порогом суммы. price правила — цена доставки при достижении порога.

POST/admin/delivery_variants.json
Параметр Описание
delivery_variant[type] обязательный
строка
DeliveryVariant::PriceDepend.
delivery_variant[title] обязательный
строка
Название способа.
delivery_variant[min_price] обязательный
число
Цена, если правило не подошло. Ноль допустим.
delivery_variant[rules_attributes] необязательный
массив
Пороги. order_price больше нуля, price — цена доставки, order_weight необязателен.
POST /admin/delivery_variants.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "delivery_variant": {
    "type": "DeliveryVariant::PriceDepend",
    "title": "docs-api от суммы",
    "min_price": 200,
    "rules_attributes": [
      {"order_price": 1, "price": 500},
      {"order_price": 3000, "price": 0}
    ]
  }
}

Ответ · 201

{
  "id": 81,
  "type": "DeliveryVariant::PriceDepend",
  "title": "docs-api от суммы",
  "min_price": "200.0",
  "rules": [
    {"id": 1, "order_price": "1.0", "price": "500.0", "order_weight": null},
    {"id": 9, "order_price": "3000.0", "price": "0.0", "order_weight": null}
  ]
}

Правило с весом возвращает order_weight строкой, например "2.0".

Самовывоз

DeliveryVariant::PickUp создаёт способ точек самовывоза и, если такого ещё нет, способ оплаты PaymentGateway::PickUp с названием «Оплата в точке самовывоза». В теле ответа создания этой оплаты может ещё не быть: её показывает следующий GET того же способа. Точки этого способа читаются и создаются через точки самовывоза.

Точка внешнего пункта передаётся в заказ тем же order[delivery_info_attributes], внутри outlet. Для этого типа у точки нужны latitude и longitude. Без координат ответ 422:

{
  "delivery_variant_id": ["Не выбрана точка самовывоза"],
  "base": ["Не выбрана точка самовывоза"]
}

С координатами заказ сохраняется, а delivery_info.outlet содержит id, external_id, latitude, longitude, title, address и source_id.

В объекте есть пустые массивы pick_up_sources и pick_up_source_delivery_variants. Источник внешних пунктов — отдельный ресурс приложения.

POST/admin/delivery_variants.json
Параметр Описание
delivery_variant[type] обязательный
строка
DeliveryVariant::PickUp.
delivery_variant[title] обязательный
строка
Название способа.
delivery_variant[add_payment_gateways] необязательный
логический
Привязать текущие способы оплаты.
POST /admin/delivery_variants.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "delivery_variant": {
    "type": "DeliveryVariant::PickUp",
    "title": "docs-api самовывоз",
    "add_payment_gateways": true
  }
}

Ответ · 201

{
  "id": 73,
  "type": "DeliveryVariant::PickUp",
  "title": "docs-api самовывоз",
  "payment_delivery_variants": [
    {"id": 5, "payment_gateway_id": 6101770}
  ],
  "pick_up_sources": [],
  "pick_up_source_delivery_variants": [],
  "delivery_locations": [],
  "delivery_time_intervals": []
}

POST /admin/pick_up_sources.json создаёт источник пунктов текущего приложения. После сохранения источник появляется в pick_up_sources способа самовывоза: там есть id, url, point_info_url, method, created_at. В ответе самого создания method нет. Если способа DeliveryVariant::PickUp ещё нет, создание источника добавляет его с названием «Доставка в точки самовывоза» и привязывает уже существующие способы оплаты. Удаление источника этот способ не удаляет.

POST/admin/pick_up_sources.json
Параметр Описание
pick_up_source[title] необязательный
строка
Название источника.
pick_up_source[url] необязательный
строка
Адрес списка пунктов. Уникален в магазине. http или https, не локальный.
pick_up_source[point_info_url] необязательный
строка
Адрес карточки одного пункта.
pick_up_source[http_method] необязательный
строка
Метод запроса. В способе самовывоза приходит как method. По умолчанию POST.
POST /admin/pick_up_sources.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "pick_up_source": {
    "title": "docs-api источник",
    "url": "https://example.com/points",
    "point_info_url": "https://example.com/point",
    "http_method": "POST"
  }
}

Ответ · 201

{
  "id": 1,
  "title": "docs-api источник",
  "url": "https://example.com/points",
  "point_info_url": "https://example.com/point",
  "created_at": "2026-10-21T22:22:12.805+03:00",
  "updated_at": "2026-10-21T22:22:12.805+03:00"
}

GET /admin/pick_up_sources.json — источники текущего приложения. DELETE /admin/pick_up_sources/:id.json отвечает 200, тело пустое.

Точки самовывоза

GET /admin/outlets.json отдаёт точки способов DeliveryVariant::PickUp. Пустой список — []. Создание точки само ищет такой способ, а если его нет — создаёт способ с названием «Доставка в точки самовывоза».

Обязательны title, address, price и пара координат latitude, longitude. Цена ноль допустима.

POST/admin/outlets.json
Параметр Описание
outlet[title] обязательный
строка
Название точки.
outlet[address] обязательный
строка
Адрес.
outlet[description] необязательный
строка
Как найти точку.
outlet[price] обязательный
число
Цена выдачи. Ноль допустим.
outlet[latitude] обязательный
число
Широта.
outlet[longitude] обязательный
число
Долгота.
POST /admin/outlets.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json

{
  "outlet": {
    "title": "docs-api пункт",
    "address": "Москва, ул. Пример, 1",
    "description": "Вход со двора",
    "price": 0,
    "latitude": "55.755800",
    "longitude": "37.617300"
  }
}

Ответ · 201

{
  "id": 1,
  "account_id": 233686,
  "delivery_variant_id": 73,
  "title": "docs-api пункт",
  "description": "Вход со двора",
  "address": "Москва, ул. Пример, 1",
  "price": "0.0",
  "latitude": "55.7558",
  "longitude": "37.6173",
  "title_translations": ["docs-api пункт"],
  "description_translations": ["Вход со двора"]
}

Название и описание приходят и строкой, и массивом переводов. PUT с price и description отвечает 200 и обновлённым объектом.

Без адреса и координат ответ 422:

{
  "address": ["Не заполнены обязательные поля"],
  "coordinates": ["Не валидный формат координаты точки"]
}

Адрес без координат отвечает 422 только по coordinates.

DELETE /admin/outlets/1.json отвечает 200, тело пустое.