A valid request URL is required to generate request examples{
"id": "disc-2026-04-17-0142",
"scope": "ticket",
"lineId": null,
"basis": "percent",
"baseCents": 3980,
"amountCents": -398,
"effectiveBps": 1000,
"reason": "manual_markdown",
"note": "Damaged packaging on the display unit",
"actorId": "usr-manager-3",
"at": "2026-04-17T14:32:05.000Z"
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123,
"fieldErrors": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}Apply an authorised discount to a whole ticket
Applies a manager-authorised reduction to the WHOLE ticket and persists the traced record. This is the deliberate, one-off human decision — reach for it only when no automatic promotion or presented coupon covers the case, and never to reproduce an offer that should be a rule (POST /v1/promotions) or a code (POST /v1/coupons). You supply the id, which is the IDEMPOTENCY ANCHOR: a second post of the same id is rejected 409 rather than doubling the reduction, so generate one id per intended discount and retry with the same one. reason is a closed vocabulary (manual_markdown, promotional, loyalty_reward, damaged_goods, manager_goodwill) and note carries up to 280 characters of free-text justification. Express the reduction either as basis:'percent' with percentBps in BASIS POINTS (1000 = 10%) or basis:'amount' with amountCents in integer CENTS; the cart snapshot you pass is what the gross is computed from, and it is read, never mutated. The default policy caps a discount at 50% and at 50.00 € and refuses a reduction larger than the base — breaching any of those gives 422, which means ‘the request was well-formed but too deep’, not a malformed body. Applying a discount records it; it does not settle a sale, which stays POST /v1/checkout/finalize.
A valid request URL is required to generate request examples{
"id": "disc-2026-04-17-0142",
"scope": "ticket",
"lineId": null,
"basis": "percent",
"baseCents": 3980,
"amountCents": -398,
"effectiveBps": 1000,
"reason": "manual_markdown",
"note": "Damaged packaging on the display unit",
"actorId": "usr-manager-3",
"at": "2026-04-17T14:32:05.000Z"
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123,
"fieldErrors": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}Authorizations
Authorization: Bearer <token>. Accepts EITHER a Keycloak access token (scopes-in-token) OR an opaque POS session token; both resolve to the same pos.* scope vocabulary the route guards enforce.
Body
- Option 1
- Option 2
1manual_markdown, promotional, loyalty_reward, damaged_goods, manager_goodwill Show child attributes
Show child attributes
percent 1 <= x <= 10000280Response
The persisted discount record, with the valued signed reduction.
The persisted discount record, with the valued signed reduction.
line, ticket percent, amount -9007199254740991 <= x <= 9007199254740991-9007199254740991 <= x <= 9007199254740991-9007199254740991 <= x <= 9007199254740991manual_markdown, promotional, loyalty_reward, damaged_goods, manager_goodwill 
