Coupons and promotions
Restaurants have two kinds of offers:
- Coupon codes that the customer types, listed in
couponsinGET /menu. - Automatic promotions that need no code, listed in
promotionsinGET /menu. Show them as banners.
Neither list includes the code itself. An order gets either the code the customer typed or the best automatic promotion, never both. The server always calculates the final discount when the order is created; the endpoints below are for showing it in the cart.
The TypeScript examples use API, SLUG and headers from the shared setup.
Send the cart
Both endpoints take the restaurant’s slug in the JSON body, the subtotal in øre and the cart lines. Send the same cart you will order:
Preview the automatic promotion
The response is { "applies": true, "discount": 6900, "coupon": { ... } }, or { "applies": false, "discount": 0 } when no promotion matches.
Validate a code
A well-formed request always gets 200; read valid. When it is false, reason says why and message is a Norwegian sentence you can show the customer as it is. When the code is valid, send it as couponCode on POST /orders.
Send email when you have it. Without it, subscriber-only codes always fail, and once-per-customer codes are only checked when the order is created.
Discount types
Always show discount from the response as the amount saved. Treat unknown types as a general offer, since more may be added.
Newsletter signup
POST /newsletter/signup?slug= adds the customer to the restaurant’s newsletter and returns the welcome coupon (couponCode, discountType, discountValue and the restaurant’s successMessage, where you replace {{code}} and {{discount}}).
It only works when the restaurant has turned on its newsletter popup with an active coupon; otherwise you get 404 POPUP_NOT_AVAILABLE. Check restaurant.newsletterPopup from GET /restaurant first. It is null when signup is off, and otherwise holds the popup’s texts and when to show it.

