Skip to content

feat(food): add discount extension specification and schema - #992

Open
niranjanmanjunath wants to merge 2 commits into
food/checkoutfrom
discount_food_extension
Open

niranjanmanjunath wants to merge 2 commits into
food/checkoutfrom
discount_food_extension

Conversation

@niranjanmanjunath

Copy link
Copy Markdown
Contributor

Description

Stacked on top of #897 (food/checkout).

Summary

  • Adds the Food Discount Extension (dev.ucp.food.discount) specification at docs/specification/food/extensions/discount.md with Food domain examples (dish-based line items, BOGOPIZZA, delivery fee discounts, and stacked loyalty/promo allocations).
  • Adds the dev.ucp.food.discount JSON Schema at source/schemas/food/discount.json extending dev.ucp.food.cart and dev.ucp.food.checkout.
  • Registers Discounts under Specification -> Food -> Extensions and plugins.llmstxt.sections.Food Extensions in mkdocs.yml.

Category (Required)

Please select one or more categories that apply to this change.

  • Core Protocol: Changes to the base communication layer, global context, or breaking refactors. (Requires Technical Council approval)
  • Governance/Contributing: Updates to GOVERNANCE.md, CONTRIBUTING.md, or CODEOWNERS. (Requires Governance Council approval)
  • Capability: New schemas (Discovery, Cart, etc.) or extensions. (Requires Maintainer approval)
  • Documentation: Updates to README, or documentations regarding schema or capabilities. (Requires Maintainer approval)
  • Infrastructure: CI/CD, Linters, or build scripts. (Requires DevOps Maintainer approval)
  • Maintenance: Version bumps, lockfile updates, or minor bug fixes. (Requires DevOps Maintainer approval)
  • SDK: Language-specific SDK updates and releases. (Requires DevOps Maintainer approval)
  • Samples / Conformance: Maintaining samples and the conformance suite. (Requires Maintainer approval)
  • UCP Schema: Changes to the ucp-schema tool (resolver, linter, validator). (Requires Maintainer approval)
  • Community Health (.github): Updates to templates, workflows, or org-level configs. (Requires DevOps Maintainer approval)

Related Issues

Checklist

  • I have followed the Contributing Guide (including Conventional Commits title requirements and ! for breaking changes).
  • I have updated the documentation (if applicable).
  • My changes pass all local linting and formatting checks.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • (For Core/Capability) I have included/updated the relevant JSON schemas.
  • I have regenerated Python Pydantic models by running generate_models.sh under python_sdk.

Screenshots / Logs (if applicable)

@damaz91 damaz91 added status:needs-triage Signal that the PR is ready for human triage status:under-review area:food Issues and pull requests related to the Food ordering vertical gov:needs-tc-review Requires review and approval from the Technical Council and removed status:needs-triage Signal that the PR is ready for human triage labels Oct 26, 2026
@niranjanmanjunath niranjanmanjunath added this to the 2026-12-08 milestone Oct 27, 2026
@niranjanmanjunath
niranjanmanjunath requested review from nimishjs and removed request for nimishjs November 2, 2026 20:38
"each",
"across"
],
"description": "Allocation method. 'each' = applied independently per dish. 'across' = split proportionally by value."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this description accurate for BOGO's where that type of discount is triggered by other dishes (e.g. not fully independent per dish?)

| `discount_code_already_applied` | Code is already applied |
| `discount_code_combination_disallowed` | Cannot combine with another active discount |
| `discount_code_user_not_logged_in` | Code requires authenticated user |
| `discount_code_user_ineligible` | User does not meet eligibility criteria |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other types of error codes/scenarios to consider here (from Toast perspective). it really depends on how granular we want to get with these i suppose:

- Minimum order / subtotal not met
- No qualifying dish in the cart
- Not valid for this fulfillment method
- Not valid at this time: happy hour, day-part, and scheduled orders, where the promo window has to be checked against the promised time, not when the order was placed
- Usage limit reached / single-use / already redeemed by this guest
  -  perhaps could be user inelegible?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id love the agent to have enough granularity so that it can steer the buyer out of an error: "add $8 more" or "switch to pickup."


**Determining the type:** If a discount has `allocations` pointing to line
items, it contributes to `items_discount`. Discounts without allocations, or
with allocations to delivery/fees, contribute to `discount`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allocations describe where the dollars landed, not whether a discount is item-level or order-level. Toast spreads order-level promos across items so each item is taxed on its discounted price. For example, $10 off a $30 pizza (8% tax) plus a $20 beer (10% tax) lands as $6/$4, and tax is $3.52. With this rule, a business that reports that split has to present an order promo as items_discount, which contradicts Pattern 3 (Promo WELCOME10 → discount).

Suggest: allocations are informational only, and the business picks items_discount vs discount based on how the promo is presented to the buyer.

@jonhines

jonhines commented Nov 2, 2026

Copy link
Copy Markdown

also curious how platforms should be communicating what the max number of discounts an order can apply....

Toast online ordering typically allows one promo code per order, but platforms can't learn this from the profile. They'll only hit combination_disallowed after trying. An optional max_codes setting would help.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:food Issues and pull requests related to the Food ordering vertical gov:needs-tc-review Requires review and approval from the Technical Council status:under-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants