When a human shopper enters a discount code that doesn't work, they see a message like "Code not valid for this order." Frustrating, but they can usually figure out why — maybe the code expired, or the cart total is too low, or it's not valid for sale items.
AI agents have no such intuition. When a discount code fails, they need structured information about why it failed to make intelligent decisions. PR #271 adds exactly this: a formal schema for representing inapplicable discount codes with machine-readable failure reasons.
The PR introduces an inapplicable_discount_codes field in the checkout response with structured failure information:
{
"inapplicable_discount_codes": [
{
"code": "SAVE20",
"reason": "minimum_not_met",
"details": {
"minimum_order_value": {
"amount": 50.00,
"currency": "USD"
},
"current_order_value": {
"amount": 35.00,
"currency": "USD"
}
}
}
]
}
The schema defines standard reason codes:
expired — code has passed its validity periodnot_yet_active — code starts in the futureminimum_not_met — order total below thresholdmaximum_exceeded — order total above thresholditems_ineligible — specific items don't qualifyalready_used — single-use code exhaustedusage_limit_reached — code has hit redemption capcustomer_ineligible — customer doesn't qualify (new customer only, etc.)region_restricted — geographic restrictionscombination_not_allowed — conflicts with another discountunknown — catch-all for edge casesConsider how an AI shopping agent might handle these scenarios:
User: "Apply code SAVE20 to my order"
Agent: "The code couldn't be applied."
User: "Why not?"
Agent: "I don't have that information."
User: "Apply code SAVE20 to my order"
Agent: "SAVE20 requires a minimum order of $50. Your current total is $35. Would you like me to suggest items to reach the minimum?"
The difference is transformative for user experience. The agent becomes a helpful assistant rather than a confused messenger.
The schema is designed for extensibility:
"InapplicableDiscountCode": {
"type": "object",
"required": ["code", "reason"],
"properties": {
"code": { "type": "string" },
"reason": {
"type": "string",
"enum": ["expired", "not_yet_active", ...]
},
"details": {
"type": "object",
"additionalProperties": true
},
"message": {
"type": "string",
"description": "Human-readable explanation"
}
}
}
The details object is intentionally flexible — different reason codes populate different detail structures. minimum_not_met includes threshold and current values; items_ineligible lists specific SKUs; expired includes the expiration timestamp.
This PR builds on recent discount infrastructure:
Together, these PRs are building a complete discount lifecycle: apply codes early, understand failures semantically, and ensure legal compliance through disclosure.
The PR is currently open, with discussion around:
details should have a stricter schema per reason codemessage fieldFor AI agents operating in commerce, this is essential infrastructure. The more structured information agents have about failures, the better they can recover and assist users.