Ce guide fournit la documentation de référence technique de l'API et les schémas de charge utile nécessaires pour gérer les codes promotionnels et les remises dans la version 2026-04-08 de l'Universal Commerce Protocol (UCP).
Avant de créer vos points de terminaison, veillez à consulter la présentation des codes promotionnels et des remises pour vous familiariser avec les concepts clés, les invariants mathématiques et les règles de gestion des erreurs.
Découverte
Pour recevoir des codes de réduction de la part de Google, vous devez signaler la prise en charge des remises dans votre profil. Dans la version 2026-04-08, les plateformes s'assurent que la fonctionnalité de paiement est bien étendue avant de soumettre tout code de réduction.
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.shopping.discount": [
{
"version": "2026-04-08",
"extends": ["dev.ucp.shopping.checkout"],
"spec": "https://ucp.dev/2026-04-08/specification/discount",
"schema": "https://ucp.dev/2026-04-08/schemas/shopping/discount.json"
}
]
}
}
}
Impact sur les éléments et les totaux
Les remises appliquées sont répercutées dans les principaux champs de paiement à l'aide de deux types de totaux distincts. Si une remise comporte des allocations pointant vers des articles, elle est comptabilisée dans items_discount. Les remises sans allocation, ou avec des allocations aux frais de livraison ou aux frais divers, sont comptabilisées dans discount.
| Type de remise | Type de total | Où les remises sont-elles répercutées ? |
|---|---|---|
| Remise sur un article | items_discount |
line_items[].totals[type=items_discount] |
| Remise au niveau de la commande | discount |
totals[type=discount] |
Exigences concernant la version :
Pour la version 2026-04-08, les entrées de remise dans totals[] et line_items[].totals[] doivent utiliser des valeurs négatives pour refléter leur déduction sur le reçu. Les montants figurant dans les tableaux discounts.applied et allocations demeurent systématiquement des entiers positifs.
Exemples d'API pour les promotions appliquées automatiquement
Les exemples suivants illustrent les remises appliquées automatiquement. Les charges utiles des requêtes ne contiennent pas de tableau discounts.codes, mais les réponses incluent "automatic": true et omettent le champ code.
Remise appliquée automatiquement au niveau de l'article
Une promotion de 10 % sur tout le site appliquée automatiquement à un article spécifique.
Exemple de requête :
{
"line_items": [
{
"id": "li_1",
"item": { "title": "Sneakers", "price": 10000 },
"quantity": 1
}
]
}
Exemple de réponse :
{
"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}
]
}
Remise appliquée automatiquement au niveau de la commande
Une règle promotionnelle (par exemple, "10 € de remise dès 50 € d'achat") s'appliquant à l'ensemble de la commande, sans répartition spécifique par article.
Exemple de requête :
{
"line_items": [ ... ]
}
Exemple de réponse :
{
"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}
]
}
Exemples d'API pour les promotions appliquées par les utilisateurs
Les exemples suivants illustrent des remises déclenchées par la saisie d'un code promotionnel. Les charges utiles de requête incluent les codes demandés, et les réponses les renvoient tout en allouant les montants appliqués.
Remise au niveau de la commande
Une remise forfaitaire appliquée au total de la commande. Aucune allocation n'est nécessaire. La remise s'applique à l'ensemble de la commande et utilise type: "discount".
Exemple de requête :
{
"line_items": [ ... ],
"discounts": {
"codes": ["SAVE10"]
}
}
Exemple de réponse :
{
"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}
]
}
Remises mixtes (au niveau de l'article et de la commande)
Cet exemple illustre les deux types de remises : une remise par article (20 % de réduction) appliquée aux éléments et une remise automatique sur les frais de port au niveau de la commande.
Exemple de requête :
{
"line_items": [ ... ],
"discounts": {
"codes": ["SUMMER20"]
}
}
Exemple de réponse :
{
"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}
]
}
Code de réduction refusé
Lorsqu'un code n'est pas valide, il est renvoyé dans codes, mais ne figure pas dans applied. Le refus est signalé par un warning dans le tableau messages[].
Exemple de requête :
{
"line_items": [ ... ],
"discounts": {
"codes": ["SAVE10", "EXPIRED50"]
}
}
Exemple de réponse :
{
"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"
}
]
}
Remises cumulées avec des allocations
Plusieurs remises appliquées avec la répartition complète des allocations.
Exemple de requête :
{
"line_items": [ ... ],
"discounts": {
"codes": ["SUMMER20", "EXTRA5"]
}
}
Exemple de réponse :
{
"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}
]
}