Внедрение промокодов и скидок, Внедрение промокодов и скидок

В этом руководстве представлены технические сведения об API и схемы полезной нагрузки для обработки промокодов и скидок в версии 2026-01-23 протокола Universal Commerce Protocol (UCP).

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

Открытие

Чтобы получать скидочные купоны от Google, необходимо указать поддержку скидок в своем профиле. В версии 2026-01-23 возможность получения скидок распространяется только на продление сеансов оформления заказа.

{
  "ucp": {
    "version": "2026-01-23",
    "capabilities": {
      "dev.ucp.shopping.discount": [
        {
          "version": "2026-01-23",
          "extends": "dev.ucp.shopping.checkout",
          "spec": "https://ucp.dev/2026-01-23/specification/discount",
          "schema": "https://ucp.dev/2026-01-23/schemas/shopping/discount.json"
        }
      ]
    }
  }
}

Влияние на отдельные статьи расходов и итоговые суммы.

Примененные скидки отображаются в основных полях оформления заказа с использованием двух различных типов итоговых сумм. Если скидка имеет allocations на отдельные позиции, она учитывается в значении items_discount . Скидки без отчислений или с отчислениями на доставку или сборы учитываются в значении discount .

Тип скидки Всего типов Где отражено
Скидка по отдельным позициям items_discount line_items[].totals[type=items_discount]
Скидка на уровне заказа discount totals[type=discount]

Требования к версии:

В версии 2026-01-23 суммы скидок в totals[] и line_items[].totals[] представлены положительными целыми числами , даже несмотря на то, что они представляют собой вычитаемую сумму из чека. Суммы внутри массивов discounts.applied и allocations также остаются положительными целыми числами.

Примеры API для автоматического применения рекламных акций

Следующие примеры демонстрируют автоматическое применение скидок. В запросах отсутствует массив discounts.codes , но в ответах указывается значение "automatic": true , а поле code опущено.

Автоматически применяемая скидка на уровне товара

Скидка 10% на весь ассортимент автоматически применяется к конкретной позиции товара.

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

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1
    }
  ]
}

Пример ответа:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 10000},
        {"type": "items_discount", "amount": 1000},
        {"type": "total", "amount": 9000}
      ]
    }
  ],
  "discounts": {
    "applied": [
      {
        "title": "10% Off Sitewide Sale",
        "amount": 1000,
        "automatic": true,
        "method": "each",
        "allocations": [
          {"path": "$.line_items[0]", "amount": 1000}
        ]
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 9000}
  ]
}

Автоматически применяемая скидка на уровне заказа

Акционное правило (например, «скидка 10 долларов на заказы свыше 50 долларов») применяется ко всему заказу целиком, без учета конкретных позиций.

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

{
  "line_items": [ ... ]
}

Пример ответа:

{
  "line_items": [ ... ],
  "discounts": {
    "applied": [
      {
        "title": "$10 Off Orders Over $50",
        "amount": 1000,
        "automatic": true
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 6000},
    {"type": "discount", "display_text": "Order Promo", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 5000}
  ]
}

Примеры API для применения пользователями рекламных акций

Следующие примеры демонстрируют скидки, активируемые при вводе пользователем промокода. Запросы содержат запрошенные коды, а ответы повторяют их, одновременно распределяя примененные суммы.

Скидка на уровне заказа

Фиксированная скидка применяется к общей сумме заказа. Распределение средств не требуется; скидка применяется ко всему заказу и имеет type: "discount" .

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10"]
  }
}

Пример ответа:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10"],
    "applied": [
      {
        "code": "SAVE10",
        "title": "$10 Off Your Order",
        "amount": 1000
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 5000},
    {"type": "discount", "display_text": "Order Discount", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 4000}
  ]
}

Смешанные скидки (на товар + на уровень заказа)

В этом примере показаны оба типа скидок: скидка за единицу товара (20%), применяемая к отдельным позициям заказа, и автоматическая скидка на доставку на уровне всего заказа.

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20"]
  }
}

Пример ответа:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "T-Shirt", "price": 2000 },
      "quantity": 2,
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "items_discount", "amount": 800},
        {"type": "total", "amount": 3200}
      ]
    }
  ],
  "discounts": {
    "codes": ["SUMMER20"],
    "applied": [
      {
        "code": "SUMMER20",
        "title": "Summer Sale 20% Off",
        "amount": 800,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 800}
        ]
      },
      {
        "title": "Free shipping on orders over $30",
        "amount": 599,
        "automatic": true
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 4000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": 800},
    {"type": "discount", "display_text": "Order Discounts", "amount": 599},
    {"type": "fulfillment", "display_text": "Shipping", "amount": 0},
    {"type": "total", "display_text": "Total", "amount": 2601}
  ]
}

Отклоненный промокод

Если код недействителен, он отображается в codes , но не applied . Отклонение сообщается с помощью warning в массиве messages[] .

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10", "EXPIRED50"]
  }
}

Пример ответа:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10", "EXPIRED50"],
    "applied": [
      {
        "code": "SAVE10",
        "title": "$10 Off Your Order",
        "amount": 1000
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 5000},
    {"type": "discount", "display_text": "Order Discount", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 4000}
  ],
  "messages": [
    {
      "type": "warning",
      "code": "discount_code_expired",
      "path": "$.discounts.codes[1]",
      "content": "Code 'EXPIRED50' expired on December 1st"
    }
  ]
}

Скидки суммируются при распределении средств.

Применяются множественные скидки с полным распределением средств.

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"]
  }
}

Пример ответа:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "T-Shirt", "price": 6000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 6000},
        {"type": "items_discount", "amount": 1500},
        {"type": "total", "amount": 4500}
      ]
    },
    {
      "id": "li_2",
      "item": { "title": "Socks", "price": 4000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "items_discount", "amount": 1000},
        {"type": "total", "amount": 3000}
      ]
    }
  ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"],
    "applied": [
      {
        "code": "SUMMER20",
        "title": "Summer Sale 20% Off",
        "amount": 2000,
        "method": "each",
        "priority": 1,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 1200},
          {"path": "$.line_items[1]", "amount": 800}
        ]
      },
      {
        "code": "EXTRA5",
        "title": "Extra $5 Off",
        "amount": 500,
        "method": "across",
        "priority": 2,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 300},
          {"path": "$.line_items[1]", "amount": 200}
        ]
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": 2500},
    {"type": "total", "display_text": "Total", "amount": 7500}
  ]
}
,

В этом руководстве представлены технические сведения об API и схемы полезной нагрузки для обработки промокодов и скидок в версии 2026-01-23 протокола Universal Commerce Protocol (UCP).

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

Открытие

Чтобы получать скидочные купоны от Google, необходимо указать поддержку скидок в своем профиле. В версии 2026-01-23 возможность получения скидок распространяется только на продление сеансов оформления заказа.

{
  "ucp": {
    "version": "2026-01-23",
    "capabilities": {
      "dev.ucp.shopping.discount": [
        {
          "version": "2026-01-23",
          "extends": "dev.ucp.shopping.checkout",
          "spec": "https://ucp.dev/2026-01-23/specification/discount",
          "schema": "https://ucp.dev/2026-01-23/schemas/shopping/discount.json"
        }
      ]
    }
  }
}

Влияние на отдельные статьи расходов и итоговые суммы.

Примененные скидки отображаются в основных полях оформления заказа с использованием двух различных типов итоговых сумм. Если скидка имеет allocations на отдельные позиции, она учитывается в значении items_discount . Скидки без отчислений или с отчислениями на доставку или сборы учитываются в значении discount .

Тип скидки Всего типов Где отражено
Скидка по отдельным позициям items_discount line_items[].totals[type=items_discount]
Скидка на уровне заказа discount totals[type=discount]

Требования к версии:

В версии 2026-01-23 суммы скидок в totals[] и line_items[].totals[] представлены положительными целыми числами , даже несмотря на то, что они представляют собой вычитаемую сумму из чека. Суммы внутри массивов discounts.applied и allocations также остаются положительными целыми числами.

Примеры API для автоматического применения рекламных акций

Следующие примеры демонстрируют автоматическое применение скидок. В запросах отсутствует массив discounts.codes , но в ответах указывается значение "automatic": true , а поле code опущено.

Автоматически применяемая скидка на уровне товара

Скидка 10% на весь ассортимент автоматически применяется к конкретной позиции товара.

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

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1
    }
  ]
}

Пример ответа:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 10000},
        {"type": "items_discount", "amount": 1000},
        {"type": "total", "amount": 9000}
      ]
    }
  ],
  "discounts": {
    "applied": [
      {
        "title": "10% Off Sitewide Sale",
        "amount": 1000,
        "automatic": true,
        "method": "each",
        "allocations": [
          {"path": "$.line_items[0]", "amount": 1000}
        ]
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 9000}
  ]
}

Автоматически применяемая скидка на уровне заказа

Акционное правило (например, «скидка 10 долларов на заказы свыше 50 долларов») применяется ко всему заказу целиком, без учета конкретных позиций.

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

{
  "line_items": [ ... ]
}

Пример ответа:

{
  "line_items": [ ... ],
  "discounts": {
    "applied": [
      {
        "title": "$10 Off Orders Over $50",
        "amount": 1000,
        "automatic": true
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 6000},
    {"type": "discount", "display_text": "Order Promo", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 5000}
  ]
}

Примеры API для применения пользователями рекламных акций

Следующие примеры демонстрируют скидки, активируемые при вводе пользователем промокода. Запросы содержат запрошенные коды, а ответы повторяют их, одновременно распределяя примененные суммы.

Скидка на уровне заказа

Фиксированная скидка применяется к общей сумме заказа. Распределение средств не требуется; скидка применяется ко всему заказу и имеет type: "discount" .

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10"]
  }
}

Пример ответа:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10"],
    "applied": [
      {
        "code": "SAVE10",
        "title": "$10 Off Your Order",
        "amount": 1000
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 5000},
    {"type": "discount", "display_text": "Order Discount", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 4000}
  ]
}

Смешанные скидки (на товар + на уровень заказа)

В этом примере показаны оба типа скидок: скидка за единицу товара (20%), применяемая к отдельным позициям заказа, и автоматическая скидка на доставку на уровне всего заказа.

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20"]
  }
}

Пример ответа:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "T-Shirt", "price": 2000 },
      "quantity": 2,
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "items_discount", "amount": 800},
        {"type": "total", "amount": 3200}
      ]
    }
  ],
  "discounts": {
    "codes": ["SUMMER20"],
    "applied": [
      {
        "code": "SUMMER20",
        "title": "Summer Sale 20% Off",
        "amount": 800,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 800}
        ]
      },
      {
        "title": "Free shipping on orders over $30",
        "amount": 599,
        "automatic": true
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 4000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": 800},
    {"type": "discount", "display_text": "Order Discounts", "amount": 599},
    {"type": "fulfillment", "display_text": "Shipping", "amount": 0},
    {"type": "total", "display_text": "Total", "amount": 2601}
  ]
}

Отклоненный промокод

Если код недействителен, он отображается в codes , но не applied . Отклонение сообщается с помощью warning в массиве messages[] .

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10", "EXPIRED50"]
  }
}

Пример ответа:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10", "EXPIRED50"],
    "applied": [
      {
        "code": "SAVE10",
        "title": "$10 Off Your Order",
        "amount": 1000
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 5000},
    {"type": "discount", "display_text": "Order Discount", "amount": 1000},
    {"type": "total", "display_text": "Total", "amount": 4000}
  ],
  "messages": [
    {
      "type": "warning",
      "code": "discount_code_expired",
      "path": "$.discounts.codes[1]",
      "content": "Code 'EXPIRED50' expired on December 1st"
    }
  ]
}

Скидки суммируются при распределении средств.

Применяются множественные скидки с полным распределением средств.

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

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"]
  }
}

Пример ответа:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "T-Shirt", "price": 6000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 6000},
        {"type": "items_discount", "amount": 1500},
        {"type": "total", "amount": 4500}
      ]
    },
    {
      "id": "li_2",
      "item": { "title": "Socks", "price": 4000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "items_discount", "amount": 1000},
        {"type": "total", "amount": 3000}
      ]
    }
  ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"],
    "applied": [
      {
        "code": "SUMMER20",
        "title": "Summer Sale 20% Off",
        "amount": 2000,
        "method": "each",
        "priority": 1,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 1200},
          {"path": "$.line_items[1]", "amount": 800}
        ]
      },
      {
        "code": "EXTRA5",
        "title": "Extra $5 Off",
        "amount": 500,
        "method": "across",
        "priority": 2,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 300},
          {"path": "$.line_items[1]", "amount": 200}
        ]
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": 2500},
    {"type": "total", "display_text": "Total", "amount": 7500}
  ]
}