Examples are partial payloads: omitted context is not shown. All code examples are valid JSON.
Every normal webhook event request contains the following two objects in the payload:
event Contains metadata about the event.
sender Contains the details of the workplace that is sending the event.
Most webhooks, with the exception of a few like backgroundPoll, also contain the following object:
session Contains the details of the current session.
Then there are some objects that only occur with specific webhook events:
scanCode (scanned-code events and requested-scan follow-ups)
Contains the scanned code’s details.
addSessionLine (only occurs with addSessionLine event)
Contains the added line’s details.
updateSessionLine (only occurs with updateSessionLine event)
Contains the updated line’s details.
removeSessionLine (only
occurs with removeSessionLine event)
Contains the removed line’s details.
mergeSession (only occurs with mergeSession event)
Contains the ID of the session that the current session is merging with.
moveSession (only occurs with moveSession event)
Contains the table number that the session is being moved from and to.
completeSession (only occurs with completeSession event)
Contains the payment details of the session.
creditSession Contains payments associated with crediting a session.
determinePricing Contains pricing context.
selectRelation (only occurs with selectRelation event)
Contains the selected relation details.
printBill (only occurs with printBill event)
Contains the details of previous payments to the bill.
customAction (only occurs with customAction event)
Contains the details of the custom action.
course (only occurs with kitchen…Course event)
Contains the details of the underlying course.
externalPayment (only occurs with …ExternalPayment event)
Contains the external payment’s details.
cafeteriaOrder
Contains the details of the underlying cafeteria order.
tableOrder
Contains the details of the underlying table order.
order
Contains the details of the underlying order.
table
Contains the details of the underlying table.
Finally, some objects may only occur in certain circumstances.
dialog (only occurs after a dialog response)
Contains selected dialog options.
form (only occurs after a form response)
Contains submitted form values.
openUrl (only occurs when the client supports it)
Contains preferences regarding usage of the openUrl response.
An invalid reply can cause an error notification. This uses an error and original envelope, with the original event and sender nested under original; it does not have the normal top-level envelope. Some transport, timeout and authentication failures are not sent back to the endpoint:
error
Signify an error in the response that was sent.
When replying to a webhook, return a JSON object containing the applicable response properties below. An empty body is accepted for most events, but not for startExternalPayment. Some properties are scalars or arrays rather than objects.
error
Signify an error in the request that was sent.
scanCode (only works with scanCode)
Response to the scanCode event.
lineChanges
Request changes to the session’s lines.
lineAdditions
Request additions to the session’s lines.
lineDeletions
Request deletions from the session’s lines.
lockSession
Lock the session from further changes.
lockSessionForAdditions
Lock the session from further additions (deletions/decreases is allowed).
receiptFooter (only works with completeSession)
Request some extra data to be printed on the footer of the receipt.
billFooter (only works with printBill)
Request some extra data to be printed on the footer of the bill.
dialog
Request a dialog to show up on screen.
form
Request a form with various input fields to show up on screen.
message
Request messages to show up on the user screen and/or the customer screen.
requestScanCode
Request a code to be scanned in the POS.
displayBarcode
Display a code on the POS customer display.
hideBarcode
Instantly hide a code that is currently displayed.
openUrl
Display or redirect to a website
customActionChange
Change the caption of a customAction button.
vatMethodChange
Change the VAT method of the current session.
externalCardScan
Notify the POS that an external card was scanned, that the POS should know about.
prepayTable
Register payment on a table.
requestCustomAction
Request the POS to execute a specific custom action.
entityAnnotations Replaces this consumer’s annotations for an entity.
version
A string that represent the version of your external software (or webhook middleware).
externalPayment (only works with …ExternalPayment)
Influence the currently running external payment.
For a polling event (event.eventPolling: true), explicitly return polling.finished to control whether polling continues. External-payment completion and certain background-poll responses also end the current request; see polling.
polling Tell MplusKASSA to continue polling or not, and optionally display some messages.
Event reference and response rules
All normal events use event and sender, with session when supplied by the caller. Follow-up dialog, form, scanCode and openUrl context can accompany the applicable event. Event availability depends on configuration and the sending application.
| Event | Purpose | Additional request payload |
|---|---|---|
| startSession | Start a session. | No additional event-specific object. |
| scanCode | Process a scanned code. | scanCode |
| addSessionLine | Add a session line. | addSessionLine.line |
| updateSessionLine | Update a session line. | updateSessionLine.line |
| removeSessionLine | Remove a session line. | removeSessionLine.line |
| pauseSession | Pause a session. | No additional event-specific object. |
| resumeSession | Resume a session. | No additional event-specific object. |
| startPayment | Enter payment processing. | No additional event-specific object. |
| cancelPayment | Cancel payment processing. | No additional event-specific object. |
| mergeSession | Merge sessions. | mergeSession |
| moveSession | Move a session between tables. | moveSession |
| cancelSession | Cancel a session. | No additional event-specific object. |
| completeSession | Complete a session. | completeSession.payments |
| creditSession | Credit a session. | creditSession.payments |
| startExternalPayment | Start an external payment. | externalPayment |
| pollExternalPayment | Check external-payment status. | externalPayment |
| requestCancelExternalPayment | Request external-payment cancellation. | externalPayment |
| cancelExternalPayment | Notify external-payment cancellation. | externalPayment |
| customAction | Invoke a configured custom action. | customAction |
| backgroundPoll | Background polling. | No additional event-specific object. |
| printBill | Print an intermediate bill. | printBill.prepayments |
| kitchenStartCourse | Start a kitchen course. | course; optional order, tableOrder, cafeteriaOrder, table, relation. |
| kitchenCompleteCourse | Complete preparation of a kitchen course. | course; optional order, tableOrder, cafeteriaOrder, table, relation. |
| kitchenServeCourse | Serve a kitchen course. | course; optional order, tableOrder, cafeteriaOrder, table, relation. |
| startPOS | Start the POS application. | No additional event-specific object. |
| openPOS | Open the POS. | No additional event-specific object. |
| closePOS | Close the POS. | No additional event-specific object. |
| exitPOS | Exit the POS application. | No additional event-specific object. |
| selectRelation | Select or deselect a relation. | selectRelation.relation |
| determinePricing | Request pricing evaluation. | determinePricing |
Successful endpoint replies should use HTTP 200. The implementation parses JSON bodies for HTTP 200 and 400; an error object marks the response as an error even when delivered with HTTP 200. A nonempty reply must be a JSON object. Unknown properties can be ignored, so acceptance alone does not demonstrate support. Interactive response processing requires a blocking event.
Session edits require a supplied session and are rejected for completeSession, creditSession, cancelSession and pauseSession. This restriction covers line additions/changes/deletions, session locks and VAT-method changes. Line edits are additionally rejected when the session contains an invoice or receipt reference. Ownership, article lookup and consumer settings impose further checks.
scanCode responses are specifically parsed for scanCode events; receipt footers for completeSession; bill footers for printBill; and externalPayment responses for the four external-payment events. The shared response properties are still subject to their own validation and client capabilities. Sending a response property does not create a guarantee that it can be executed in every event.
Request objects
event
{
"event": {
"eventBlocking": true,
"eventCounter": 1,
"eventTimestamp": "2017-08-09T16:07:33.964+02:00",
"eventPolling": false
}
}
| Property | Type | Explanation |
|---|---|---|
| event.eventBlocking | boolean | Is the event blocking? When this is true, MplusKASSA is waiting for your response. |
| event.eventPolling | boolean | Is the event polling? When this is true, MplusKASSA will continue to query your endpoint until you respond that polling is finished (see polling response). |
| event.eventCounter | int | An increasing counter that helps you check if you already processed an event. Please note that the counter may occasionally reset. |
| event.eventTimestamp | datetime | The date and time that the event occurred. |
The event name is not a property of event; it is conveyed separately from this JSON object. eventCounter is a 64-bit integer and is not globally unique; retain sender context when identifying deliveries. Timestamps are ISO 8601 strings with a timezone offset. Optional fields may be omitted; arrays built from available entries may also be absent when empty.
sender
{
"sender": {
"branchNumber": 1,
"browser": {
"browserFamily": "Chrome Mobile",
"browserVersion": "109.0.5414",
"deviceType": "Mobile",
"platformFamily": "Android",
"platformVersion": "10"
},
"hasReceiptPrinter": true,
"employeeNumber": 6,
"instanceId": "f9fac333-9fa7-45fe-8e9c-2c1e6465942f",
"language": "nl",
"paymentStarted": false,
"productName": "MplusQservice",
"versionNumber": "48.0.0",
"workplaceNumber": 1
}
}
| Property | Type | Explanation |
|---|---|---|
| branchNumber | int | The branch the event was sent from. |
| workplaceNumber | int | The workplace the event was sent from. |
| instanceId | uuid | Every time the POS is restarted, this UUID is regenerated. |
| paymentStarted | boolean | When the POS is in the payment screen, this variable will be true. To detect changes to and from the payment screen, you can listen to the startPayment and cancelPayment events. |
| productName | string | Whether the webhooks are triggered from the Desktop POS MplusQ or through the API MplusQservice. |
| Browser details have been added in v48.0.0 | ||
| When webhooks are triggered through one of our web apps, this will contain information about the browser that was used. | ||
| browserFamily | string (optional) | The browser used. |
| browserVersion | string (optional) | The version of the browser used. |
| deviceType | string | Mobile, Tablet, Desktop, or Bot |
| platformFamily | string (optional) | The platform (or OS) used. |
| platformVersion | string (optional) | The version of the platform used. |
| hasReceiptPrinter was added in v57.0.0 | ||
| hasReceiptPrinter | boolean (optional) | Whether the workplace has a receipt printer configured. |
| Property | Type | Explanation |
|---|---|---|
| sender.employeeNumber | integer | Currently logged-in employee number. |
| sender.versionNumber | string | Version of the sending application. Available by MplusKASSA v17.0.0. |
| sender.language | string | Normalized language: eng becomes en, deu becomes de, an empty language becomes nl; other values are lowercased. Available by MplusKASSA v47.0.2. |
| sender.activity | object (optional) | Current activity, when available; see below. Available by MplusKASSA v14.0.0. |
Browser properties above are nested under sender.browser and are emitted only when nonempty. sender.hasReceiptPrinter is separate from browser. Printer status fields such as overallState, coverState, paperState and ageInSeconds are not emitted by this serializer.
Activity
The same activity structure is used by sender.activity and determinePricing.activity.
| Property | Type | Explanation |
|---|---|---|
| activityId | uuid | Activity identifier. |
| activityNumber | string | Activity number/reference. Available by MplusKASSA v47.1.0. |
| description | string | Activity description. Available by MplusKASSA v47.1.0. |
| interfaceLayoutId | integer or null | Interface layout ID; null when not positive. Available by MplusKASSA v47.1.0. |
| articleLayoutId | integer or null | Article layout ID; null when not positive. Available by MplusKASSA v47.1.0. |
| location | string | Activity location. Available by MplusKASSA v47.1.0. |
| priceGroupNumber | integer or null | Price group number; null when not positive. Available by MplusKASSA v47.1.0. |
| employeeStartTimestamp | datetime or null | Employee start timestamp. Available by MplusKASSA v47.1.0. |
| employeeEndTimestamp | datetime or null | Employee end timestamp. Available by MplusKASSA v47.1.0. |
| managerStartTimestamp | datetime or null | Manager start timestamp. Available by MplusKASSA v47.1.0. |
| managerEndTimestamp | datetime or null | Manager end timestamp. Available by MplusKASSA v47.1.0. |
| activityTypeId | integer or null | Activity type ID; null when not positive. Available by MplusKASSA v47.1.0. |
session
{
"session": {
"sessionId": "5eea25d4-4188-43b8-9a66-8086561d590c",
"table": {
"number": 11,
"subNumber": 4
},
"relation": {
"relationNumber": 54,
"extRelationId": "CST042",
"name": "John Doe",
"address": "",
"zipcode": "",
"city": "",
"country": "",
"deliveryAddress": "",
"deliveryZipcode": "",
"deliveryCity": "",
"deliveryCountry": "",
"telephone": "",
"mobile": "",
"email": "",
"cardNumber": "",
"bankAccountNumber": "",
"vatNumber": "",
"commerceNumber": ""
},
"lines": [
{
"lineId": "c686f63d-46a7-498e-b421-c72e5cb7136b",
"extLineId": "External line reference #32424",
"articleNumber": 1,
"priceIncl": 2.5,
"quantity": 1,
"text": "Coffee",
"discountPercentage": 50,
"discountAmount": 1,
"barcode": "8712345678901",
"supplierArticleNumber": "XR-123",
"pluNumber": "9864",
"extArticleId": "651",
"externalDiscount": {
"discountId": "d2091980-7e7d-11e7-bb31-be2e44b06b34",
"discountDescription": "Sample Voucher",
"discountPercentage": 10,
"discountAmount": 2
}
}
],
"invoice": {
"invoiceId": "3ce511eb-1ef2-4d36-8057-8a2d7f51aebe",
"year": 2025,
"number": 113
},
"payments": [
{
"amount": 1,
"description": "With cash",
"method": "CONTANT"
}
]
}
}
| Property | Type | Explanation |
|---|---|---|
| session.sessionId | uuid | The session’s unique ID. |
| session.table.number | bigint (optional) | The table number that the session is attached to. |
| session.table.subNumber | bigint (optional) | The table sub number that the session is placed upon. |
| session.lines | array | The session’s lines. |
| session.lines[].lineId | uuid (optional) | The line’s unique ID. |
| session.lines[].articleNumber | bigint (optional) | The line’s article number. |
| session.lines[].priceIncl | number (optional) | The line’s price including VAT. |
| session.lines[].quantity | number (optional) | The line’s quantity. |
| session.lines[].text | string | The line’s textual description. |
| session.lines[].discountPercentage | number (optional) | The line’s percentual discount, this stacks with the discount amount. |
| session.lines[].discountAmount | number (optional) | The line’s discount amount, this stacks with the discount percentage. |
| session.lines[].supplierArticleNumber | string (optional) | Article number from the supplier, if available. |
| session.lines[].pluNumber | string (optional) | PLU number, if available. |
| session.lines[].extArticleId | string (optional) | External article ID, if available. |
| Note that you would normally not be able to have a line with a discount from MplusKASSA and an external discount. It can only be one or the other. | ||
| session.lines[].externalDiscount.discountId | uuid (optional) | This is a UUID you generate and store to remember that you applied this discount. |
| session.lines[].externalDiscount.discountDescription | string (optional) | A textual description for the external discount. |
| session.lines[].externalDiscount.discountPercentage | number (optional) | The line’s external percentual discount, this stacks with the external discount amount. |
| session.lines[].externalDiscount.discountAmount | number (optional) | The line’s external discount amount, this stacks with the external discount percentage. |
| Note that you would normally not be able to have a line with a discount from MplusKASSA and an external discount. It can only be one or the other. | ||
| session.payments[] | payment (optional) | The session’s payments, including any prepayments that were made at any point in its history. Available by MplusKASSA v55.0.8. |
| Look at the completeSession object for a description of the payment’s properties. | ||
Additional session properties
| Property | Type | Explanation |
|---|---|---|
| session.totalInclAmount | number (optional) | Total including VAT. |
| session.totalExclAmount | number (optional) | Total excluding VAT. Available by MplusKASSA v18.0.0. |
| session.paidAmount | number (optional) | Paid amount on the underlying sale. Available by MplusKASSA v21.3.0. |
| session.prepaidAmount | number (optional) | Prepayments on the underlying order. Available by MplusKASSA v21.3.0. |
| session.openAmount | number (optional) | Outstanding amount: total including VAT minus paid and prepaid amounts. Available by MplusKASSA v21.3.0. |
| session.order | object (optional) | Underlying order; see order. When a sale combines multiple orders, the current conversion includes only the first order reference. |
| session.invoice | object (optional) | Invoice reference: invoiceId (UUID), year (integer), number (64-bit integer). Available by MplusKASSA v10.0.3. |
| session.receipt | object (optional) | Receipt reference containing receiptId (UUID). Available by MplusKASSA v16.1.0. |
| session.cafeteriaOrder | object (optional) | Underlying cafeteria order; see cafeteriaOrder. |
| session.webhookConsumerId | uuid (optional) | Webhook consumer associated with the session, when supplied. Available by MplusKASSA v61.0.0. |
| session.salesBaseId | uuid (optional) | Underlying sales record ID. Available by MplusKASSA v61.0.0. |
| session.salesTypeId | string (optional) | Underlying record type: order or turnover in the current converter. Available by MplusKASSA v61.0.0. |
| session.nutritionalData | object (optional) | Aggregated nutritional values when ingredient functionality is licensed and nutritional data exists. Available by MplusKASSA v16.1.0. |
Additional session-line properties
The same line structure is used recursively and in addSessionLine.line, updateSessionLine.line and removeSessionLine.line. Article-specific pricing, VAT, identifiers, discounts and amounts are emitted only when articleNumber is present. lineId itself can be omitted when unavailable.
| Property | Type | Explanation |
|---|---|---|
| session.lines[].extLineId | string (optional) | External line reference, omitted if empty. Available by MplusKASSA v16.1.0. |
| session.lines[].barcode | string (optional) | Article barcode. Available by MplusKASSA v14.0.0. |
| session.lines[].priceExcl | number (optional) | Unit price excluding VAT. Available by MplusKASSA v18.0.0. |
| session.lines[].vatCode | integer (optional) | VAT code. Available by MplusKASSA v11.3.0. |
| session.lines[].vatPercentage | number (optional) | VAT percentage. Available by MplusKASSA v11.3.0. |
| session.lines[].totalInclAmount | number (optional) | Line total including VAT. |
| session.lines[].totalExclAmount | number (optional) | Line total excluding VAT. Available by MplusKASSA v18.0.0. |
| session.lines[].turnoverGroup | integer (optional) | Turnover group number. Available by MplusKASSA v14.0.0. |
| session.lines[].allowPointsDistribution | boolean (optional) | Whether points may be awarded for this line. Available by MplusKASSA v14.0.0. |
| session.lines[].allowPointsPayment | boolean (optional) | Whether points may be used to pay for this line. Available by MplusKASSA v14.0.0. |
| session.lines[].allowDiscount | boolean (optional) | Whether this line allows discount. Available by MplusKASSA v14.0.0. |
| session.lines[].preparationMethods | array of lines (optional) | Preparation-method sublines, using this same line structure. Available by MplusKASSA v14.0.0. |
| session.lines[].componentArticles | array of lines (optional) | Component-article sublines, using this same line structure. Available by MplusKASSA v14.0.0. |
Money is serialized to two decimal places, discount percentages to four and quantities to ten. Internal line consumer IDs and external-discount discountType are not emitted by the request-line serializer.
Relation
A relation has relationNumber (64-bit integer) and name (string). The following strings are optional and omitted when empty: extRelationId, address, zipcode, city, country, deliveryAddress, deliveryZipcode, deliveryCity, deliveryCountry, telephone, mobile, email, cardNumber, bankAccountNumber, vatNumber, and commerceNumber. cardNumbers is an optional array of strings containing all card numbers; the standard converter also sets cardNumber to the first entry. This structure is shared by session.relation, selectRelation.relation, determinePricing.relation and the optional top-level relation on kitchen events.
Nutritional data
Each field below is an optional number under session.nutritionalData. Values follow the configured nutritional data; this serializer does not attach units or convert units.
| Property | Type | Explanation |
|---|---|---|
| calories | number (optional) | Energy in the calorie-based nutritional field. |
| joules | number (optional) | Energy in the joule-based nutritional field. |
| fat | number (optional) | Fat. |
| saturatedFat | number (optional) | Saturated fat. |
| monounsaturatedFat | number (optional) | Monounsaturated fat. |
| polyunsaturatedFat | number (optional) | Polyunsaturated fat. |
| carbohydrate | number (optional) | Carbohydrates. |
| fiber | number (optional) | Fiber. |
| starch | number (optional) | Starch. |
| sugar | number (optional) | Sugars. |
| protein | number (optional) | Protein. |
| sodium | number (optional) | Sodium. |
| calcium | number (optional) | Calcium. |
| iron | number (optional) | Iron. |
scanCode
{
"scanCode": {
"scannedCode": "8712345678901",
"codeType": "barcode"
}
}
| Property | Type | Explanation |
|---|---|---|
| scanCode.scannedCode | string (optional) | A textual representation of the code that was scanned. |
| scanCode.codeType | string (optional) | barcode, rfid |
| Property | Type | Explanation |
|---|---|---|
| scanCode.requestId | integer (optional) | Echoes the ID supplied in a requestScanCode response. A requested scan can accompany a repeat of the original event; it is not limited to a standalone scanCode event. Available by MplusKASSA v14.0.0. |
scannedCode and codeType are omitted when unavailable or empty.
addSessionLine
{
"addSessionLine": {
"line": {
"lineId": "c686f63d-46a7-498e-b421-c72e5cb7136b",
"articleNumber": 1,
"priceIncl": 2.5,
"quantity": 1,
"text": "Coffee"
}
}
}
| Property | Type | Explanation |
|---|---|---|
| addSessionLine.line.lineId | string | The added line’s unique ID. |
| addSessionLine.line.articleNumber | bigint (optional) | The added line’s article number. |
| addSessionLine.line.priceIncl | number (optional) | The added line’s price including VAT. |
| addSessionLine.line.quantity | number (optional) | The added line’s quantity. |
| addSessionLine.line.text | string | The added line’s textual description. |
| On top of this the added line can also contain all the additional properties a session.lines[] object can contain. | ||
updateSessionLine
{
"updateSessionLine": {
"line": {
"lineId": "c686f63d-46a7-498e-b421-c72e5cb7136b",
"articleNumber": 1,
"priceIncl": 2.5,
"quantity": 2,
"text": "Coffee"
}
}
}
| Property | Type | Explanation |
|---|---|---|
| updateSessionLine.line.lineId | string | The updated line’s unique ID. |
| updateSessionLine.line.articleNumber | bigint (optional) | The updated line’s article number. |
| updateSessionLine.line.priceIncl | number (optional) | The updated line’s price including VAT. |
| updateSessionLine.line.quantity | number (optional) | The updated line’s quantity. |
| updateSessionLine.line.text | string | The updated line’s textual description. |
| On top of this the updated line can also contain all the additional properties a session.lines[] object can contain. | ||
removeSessionLine
{
"removeSessionLine": {
"line": {
"lineId": "c686f63d-46a7-498e-b421-c72e5cb7136b",
"articleNumber": 1,
"priceIncl": 2.5,
"quantity": 1,
"text": "Coffee"
}
}
}
| Property | Type | Explanation |
|---|---|---|
| removeSessionLine.line.lineId | string | The removed line’s unique ID. |
| removeSessionLine.line.articleNumber | bigint (optional) | The removed line’s article number. |
| removeSessionLine.line.priceIncl | number (optional) | The removed line’s price including VAT. |
| removeSessionLine.line.quantity | number (optional) | The removed line’s quantity. |
| removeSessionLine.line.text | string | The removed line’s textual description. |
| On top of this the removed line can also contain all the additional properties a session.lines[] object can contain. | ||
mergeSession
{
"mergeSession": {
"mergeWithSessionId": "f232b716-8ab4-419e-b45e-e70720203e57"
},
"session": {
"sessionId": "15a0ea55-3ae8-4191-a7c1-3e93984e23b4"
}
}
| Property | Type | Explanation |
|---|---|---|
| mergeSession.mergeWithSessionId | string | The session that the current session is merged with. |
| session.sessionId | string | The session that is merged. |
moveSession
{
"moveSession": {
"moveFromTable": {
"number": 2,
"subNumber": 1
},
"moveToTable": {
"number": 3,
"subNumber": 1
}
}
}
| Property | Type | Explanation |
|---|---|---|
| moveSession.moveFromTable | object | Source table. |
| moveSession.moveToTable | object | Destination table. |
| session.sessionId | uuid | The session being moved. |
completeSession
{
"completeSession": {
"payments": [
{
"amount": 5,
"description": "Contant",
"method": "CONTANT"
},
{
"amount": 10,
"description": "Cadeaubon",
"method": "CADEAUBON"
}
]
},
"session": {
"sessionId": "15a0ea55-3ae8-4191-a7c1-3e93984e23b4"
}
}
| Property | Type | Explanation |
|---|---|---|
| completeSession.payments[].amount | number | The amount that was paid with this specific payment method. |
| completeSession.payments[].description | string (optional) | The description label of this payment method. |
| completeSession.payments[].method | string | The reference id of this payment method. |
| The completeSession.payments list only contains the payments that were made in the final transaction, and does not include any previous prepayments that were made to the session. You can find a list of all (pre)payments in the session.payments list. | ||
| Property | Type | Explanation |
|---|---|---|
| completeSession.payments[].paymentId | uuid (optional) | Payment identifier, when supplied. |
description is optional and omitted when empty. This payment structure is also used by session.payments, creditSession.payments and printBill.prepayments. Empty payment arrays may be absent.
creditSession
Contains the payments associated with a credit session.
{
"creditSession": {
"payments": [
{
"method": "CONTANT",
"amount": -5.0
}
]
}
}
creditSession.payments is an optional array using the payment structure. Use the supplied amounts, including their signs.
printBill
Contains payments previously made to the bill.
{
"printBill": {
"prepayments": [
{
"method": "CONTANT",
"amount": 5.0
}
]
}
}
printBill.prepayments is an optional array using the payment structure.
selectRelation
{
"selectRelation": {
"relation": {
"relationNumber": 1
}
}
}
Check the definition of session for possible contents of relation.
| When a relation is deselected, the value of relation will be null. |
customAction
{
"customAction": {
"customActionId": "A_CUSTOM_ACTION_ID",
"buttonCaption": "The Button Caption",
"onStartup": false,
"longClick": false,
"numpadValue": 1.5
},
"session": {
"sessionId": "15a0ea55-3ae8-4191-a7c1-3e93984e23b4"
}
}
| Property | Type | Explanation |
|---|---|---|
| customAction.customActionId | text | The manually configured ID of the customAction button that was clicked. |
| customAction.buttonCaption | text | The manually configured caption of the customAction button that was clicked, can be changed through a webhook response. |
| customAction.onStartup | boolean | Whether or not the webhook was called during POS startup. You may use this to set initial state. |
| customAction.longClick | boolean (optional) | Whether or not the button was held for a long time. You may decide to alternate behaviour based on this. Available by MplusKASSA v59.3.0. |
| customAction.numpadValue | number (optional) | The current value of the POS numpad input. |
| Property | Type | Explanation |
|---|---|---|
| customAction.annotationId | string (optional) | Identifier of the annotation that triggered this custom action. See entityAnnotations. Added in MplusKASSA v68.0.0 |
course
Sent for kitchenStartCourse, kitchenCompleteCourse and kitchenServeCourse. These events can also include top-level order, tableOrder, cafeteriaOrder, table and relation objects when available.
{
"course": {
"courseNumber": 1,
"name": "Starter",
"abbreviation": "ST",
"sequenceNumber": 1,
"expectedPreparationTime": 600,
"actualPreparationTime": 540
}
}
| Property | Type | Explanation |
|---|---|---|
| course.courseNumber | integer | Course number. |
| course.name | string | Course name. |
| course.abbreviation | string | Course abbreviation. |
| course.sequenceNumber | integer | Course sequence number. |
| course.expectedPreparationTime | integer (optional) | Expected preparation time in seconds. Available by MplusKASSA v13.0.0. |
| course.actualPreparationTime | integer (optional) | Actual preparation time in seconds. Available by MplusKASSA v13.0.0. |
externalPayment
{
"externalPayment": {
"externalPaymentId": "7d5b3a3a-9330-11ed-a1eb-0242ac120002",
"amount": 3.14,
"method": "K_WEBHOOK",
"callbackUrl": "https://yourplatform.example.com/callback"
}
}
| Property | Type | Explanation |
|---|---|---|
| externalPaymentId | string | Each external payment receives a new id. |
| amount | number | The amount that has to be paid. |
| method | string | The name of the payment method that was configured to trigger the webhook. |
| callbackUrl | string (optional) | If this URL is provided, please call it when you have the final status of the external payment. This is an important step in speeding up certain parts of the payment processing. You don’t need to do anything with the result of this request. |
| callbackUrl has been added in v56.0.0 | ||
| Property | Type | Explanation |
|---|---|---|
| externalPayment.description | string (optional) | Description of the payment method; omitted when empty. |
cafeteriaOrder
{
"cafeteriaOrder": {
"orderId": "8fdcaa6d-9908-4c16-b594-ee0f1ae10279",
"year": 2019,
"number": 13465,
"ticketNumber": 465
}
}
| Property | Type | Explanation |
|---|---|---|
| cafeteriaOrder.orderId | uuid | Order identifier. |
| cafeteriaOrder.year | integer | Order numbering year. |
| cafeteriaOrder.number | 64-bit integer | Order number. |
| cafeteriaOrder.ticketNumber | integer | Cafeteria ticket number. |
tableOrder
{
"tableOrder": {
"orderId": "c7ec2390-9333-11ed-a1eb-0242ac120002",
"year": 2023,
"number": 1
}
}
| Property | Type | Explanation |
|---|---|---|
| tableOrder.orderId | uuid | Order identifier. |
| tableOrder.year | integer | Order numbering year. |
| tableOrder.number | 64-bit integer | Order number. |
order
{
"order": {
"orderId": "c7ec2390-9333-11ed-a1eb-0242ac120002",
"year": 2023,
"number": 1
}
}
| Property | Type | Explanation |
|---|---|---|
| order.orderId | uuid | Order identifier. |
| order.year | integer | Order numbering year. |
| order.number | 64-bit integer | Order number. |
table
{
"table": {
"number": 3,
"subNumber": 1,
"numberOfGuests": 2
}
}
| Property | Type | Explanation |
|---|---|---|
| table.number | integer | Table number. |
| table.subNumber | integer (optional) | Table subnumber. |
| table.tableName | string (optional) | Table name; omitted when empty. Available by MplusKASSA v10.0.3. |
| table.numberOfGuests | integer (optional) | Number of guests. Available by MplusKASSA v10.0.3. |
The same object shape is used by session.table and both moveSession table objects.
determinePricing
Pricing event context, alongside the normal event, sender and available session. The serializer supports the fields below; values not supplied by the caller are explicitly null. There is no separate determinePricing response object; use the applicable standard response properties.
{
"determinePricing": {
"date": null,
"timestamp": null,
"pricegroup": null,
"activity": null,
"relation": null
}
}
| Property | Type | Explanation |
|---|---|---|
| determinePricing.date | date or null | Date-only string in YYYY-MM-DD format. |
| determinePricing.timestamp | datetime or null | ISO 8601 timestamp including timezone offset. |
| determinePricing.pricegroup | integer or null | Price group. The JSON spelling is exactly pricegroup. |
| determinePricing.activity | object or null | Activity context. |
| determinePricing.relation | object or null | Relation context. |
dialog
When you reply with a dialog, the user will be able to select some dialog options. Afterwards, the same event will be sent to you again, but this time including the selected dialog options.
{
"dialog": {
"selectedDialogOptionIds": [
1,
2
]
}
}
| Property | Type | Explanation |
|---|---|---|
| dialog.selectedDialogOptionIds | string[] or integer[] | The ID’s of the selected dialog option. Can be zero, one or more. |
| On top of this, you also receive all the original data from the event. | ||
| Property | Type | Explanation |
|---|---|---|
| dialog.dialogId | string or integer (optional) | Echoes a nonempty dialog ID from the response. Available by MplusKASSA v14.0.0. |
Use a consistent ID type for all dialog options; the implementation uses a shared integer-ID flag when serializing the selection. An empty selection may omit selectedDialogOptionIds.
form
When you reply with a form, the user will be able to fill out and submit it. Afterwards, the same event will be sent to you again, but this time including the submitted form values.
{
"form": {
"id": "customer_registration",
"cancelled": false,
"fields": [
{
"id": "name",
"value": "John Doe",
"type": "text"
},
{
"id": "email",
"value": "john@doe.example.com",
"type": "email"
},
{
"id": "allergies",
"selected": [
"peanut",
"gluten"
],
"type": "select"
}
]
}
}
| Property | Type | Explanation |
|---|---|---|
| form.id | string | Form identifier as specified in the initial form response. |
| form.cancelled | boolean | If the form was explicitly cancelled, this will be true. |
| form.fields[].id | string | Field identifier as specified in the initial form response. |
| form.fields[].value | string (optional) | No matter the original field type, submitted values are always sent as string. |
| form.fields[].selected | string[] (optional) | Contains the selected options in case of a select field. |
| On top of this, you also receive all the original data from the event. | ||
| Property | Type | Explanation |
|---|---|---|
| form.fields[].type | string | Field type, using the same names as in the form response. |
form.cancelled is always serialized. value is optional; selected is only emitted when nonempty. The fields array can be absent when empty.
openUrl
Contains preferences regarding usage of the openUrl response.
{
"openUrl": {
"redirectUrl": "https://mpluskassa.online/handheld/webhook/0f2e40a6-9336-11ed-a1eb-0242ac120002"
}
}
| Property | Type | Explanation |
|---|---|---|
| redirectUrl | string | If you plan to redirect the client to another URL during webhook interaction, please redirect back to this URL after completion. |
error
{
"error": {
"code": "LINE_ALREADY_HAS_DISCOUNT",
"message": "Line ID c686f63d-46a7-498e-b421-c72e5cb7136b already has a discount applied to it."
},
"original": {
"event": {},
"sender": {},
"session": {}
}
}
| Property | Type | Explanation |
|---|---|---|
| error.code | string | One of the Error Codes. |
| error.message | string | Additional descriptive explanation of the cause of the error. |
| original | object | All of the details of the original event. |
Response objects
error
{
"error": {
"code": "INVALID_SUBSCRIPTION_ID",
"message": "The supplied subscription does not exist in our database. Please contact support at ... to set-up your account."
}
}
| Property | Type | Explanation |
|---|---|---|
| error.code | string | One of the Error Codes. |
| error.message | string | Additional descriptive explanation of the cause of the error. |
scanCode
{
"scanCode": {
"recognized": true,
"relationNumber": 123
}
}
| Property | Type | Explanation |
|---|---|---|
| scanCode.recognized | boolean | Did you recognize the code or not? If you respond with true, the POS will stop looking for the code in its own data. |
| scanCode.relationNumber | int (optional) | A relation to select in the POS. |
lineChanges
{
"lineChanges": [
{
"lineId": "c686f63d-46a7-498e-b421-c72e5cb7136b",
"externalDiscount": {
"discountId": "12551430-7ce9-11e7-bb31-be2e44b06b34",
"applyToQuantity": 1,
"discountPercentage": 50,
"discountAmount": 1,
"discountDescription": "Sample Voucher",
"discountType": "promotional"
}
}
]
}
| Property | Type | Explanation |
|---|---|---|
| lineChanges[].lineId | uuid | The UUID of the session line that you want to change. |
| lineChanges[].externalDiscount | externalDiscount (optional) | The details of an external discount are explained below. |
| externalDiscount.discountId | uuid | This is a UUID you generate and store to remember that you applied this discount. |
| externalDiscount.discountPercentage | number (optional) | The discount percentage that you want to apply to the line. |
| externalDiscount.applyToQuantity | number (optional) | The quantity of this line that you want to apply the discount too. For example, if the quantity of the line is 2, but you want to apply the discount to 1 of these 2. |
| externalDiscount.discountAmount | number (optional) | The exact discount amount that you want to apply to the line. |
| externalDiscount.discountDescription | string (optional) | A descriptive label for the discount. |
| externalDiscount.discountType | string (optional) | Can be any kind of text, will be usable as a filter in reports Available by MplusKASSA v58.0.0. |
Only external-discount changes are parsed here; arbitrary changes to price, text or quantity are not supported by lineChanges. Discount percentages must be between 0 and 100. applyToQuantity defaults to 1 for quantity validation, must have the same sign as the line quantity, and combined applications to the same line must not exceed its quantity. Existing discounts and discounts owned by another consumer are subject to configuration restrictions.
Implementation limitation: externalDiscount: null is recognized internally as deletion, but the current line parser does not propagate it as a completed discount response. Do not rely on null to remove a discount in this checkout.
lineAdditions
{
"lineAdditions": [
{
"lineId": "f1b8a9aa-9875-11e7-abc4-cec278b6b50a",
"extLineId": "foobar-123",
"articleNumber": 1005,
"barcode": "8712345678901",
"pluNumber": "9864",
"supplierArticleNumber": "XR-123",
"extArticleId": "651",
"priceIncl": 2.1,
"quantity": 3,
"text": "Chocolate Milk",
"externalDiscount": {
"discountId": "d2091980-7e7d-11e7-bb31-be2e44b06b34",
"discountPercentage": 10
}
}
]
}
| Property | Type | Explanation |
|---|---|---|
| lineAdditions[].lineId | uuid (optional) | The UUID of the session line that you want to add. You are allowed to generate this. If you omit this an UUID will be generated automatically, but it will be more difficult for you to know which line you added. |
| lineAdditions[].extLineId | string (optional) | An identifier so you can recognize this line in a later stage. |
| lineAdditions[].articleNumber | bigint (optional) | This number should be present in the MplusKASSA administration. |
| lineAdditions[].barcode | string (optional) | This barcode should be present in the MplusKASSA administration. |
| lineAdditions[].pluNumber | string (optional) | This PLU number should be present in the MplusKASSA administration. |
| lineAdditions[].supplierArticleNumber | string (optional) | This supplier article number should be present in the MplusKASSA administration. |
| lineAdditions[].extArticleId | string (optional) | This external article ID should be present in the MplusKASSA administration. |
| You can add an article through articleNumber, barcode, pluNumber, supplierArticleNumber, extArticleId, or a combination thereof. | ||
| lineAdditions[].priceIncl | number (optional) | The line’s price including VAT. If you omit this, the default price will be used. |
| lineAdditions[].quantity | number (optional) | The line’s quantity (how many). If you omit this, a default quantity of 1 will be used. |
| lineAdditions[].text | string (optional) | The line’s text (description). If you omit this, the default article text will be used. |
| You can add a simple text line (without any article references) by using only text. | ||
| lineAdditions[].externalDiscount | externalDiscount (optional) | See the explanation at session for more details. |
| Property | Type | Explanation |
|---|---|---|
| lineAdditions[].vatCode | integer (optional) | VAT code accepted by the response parser; application depends on the receiving line-addition handler. |
| lineAdditions[].vatPercentage | number (optional) | VAT percentage accepted by the parser, rounded to two decimals; application depends on the receiving handler. |
articleNumber also accepts a decimal integer string. priceIncl and quantity accept numeric strings, but JSON numbers are recommended. Prices are rounded to two decimals and quantities to ten. For an external discount, use the response definition in lineChanges, including discountId.
lineDeletions
{
"lineDeletions": [
{
"lineId": "f1b8a9aa-9875-11e7-abc4-cec278b6b50a"
}
]
}
| Property | Type | Explanation |
|---|---|---|
| lineDeletions[].lineId | uuid | The UUID of the session line that you want to delete. |
| It is possible that your request for deletion will be denied. For example, you can only delete lines that you yourself added. You will receive an error message if this is the case. | ||
| Since v11.3.0 this behaviour depends on the setting “Webhooks mogen alle regels verwijderen”. | ||
lockSession
{
"lockSession": true
}
| Property | Type | Explanation |
|---|---|---|
| lockSession | boolean | Locks or unlocks the session from further changes. |
lockSessionForAdditions
{
"lockSessionForAdditions": true
}
| Property | Type | Explanation |
|---|---|---|
| lockSessionForAdditions | boolean | Locks or unlocks the session from further additions (deletions/decreases are allowed). |
receiptFooter
A top-level receiptFooter is handled for completeSession. The wrapper completeSession.receiptFooter is also accepted. External-payment responses can supply their own nested footers; see externalPayment.
{
"receiptFooter": {
"textBefore": "Thank you!\nPlease visit again.",
"barcode": {
"codeType": "qrcode",
"code": "https://example.com/receipt"
},
"textAfter": "Your receipt reference",
"printSeparate": false
}
}
Use an array of these objects for multiple footers.
| Property | Type | Explanation |
|---|---|---|
| textBefore | string (optional) | Text before the barcode. text and message are also accepted. Newlines are supported. |
| barcode | object (optional) | Barcode to print. Null means no barcode. |
| barcode.codeType | string (optional) | code128 (default) or qrcode. |
| barcode.code | string | Barcode contents; code128: 1–48 characters; qrcode: 1–2953 characters. |
| textAfter | string (optional) | Text after the barcode. Available by MplusKASSA v21.2.1. |
| printSeparate | boolean (optional) | Print separately, with a cut between receipt and footer; defaults to false. |
The pre-barcode text is limited to 10,000 characters by footer validation. Receipt layout configuration must support webhook footers.
Implementation limitation: the supplied documentation listed textBeforeOptions and textAfterOptions for alignment, size, underline and bold. The current webhook footer parser does not read these objects; they are not supported by this JSON path.
billFooter
Attention: billFooter only works with the printBill event.
The JSON details of billFooter are identical to receiptFooter.
The printBill.billFooter wrapper is also accepted. The same formatting limitations and footer validation rules apply.
dialog
{
"dialog": {
"required": false,
"requireConfirmation": true,
"allowMultipleOptions": false,
"dialogTitle": "Select the voucher to apply",
"columns": 2,
"dialogOptions": [
{
"optionId": 1,
"optionName": "Second cup of coffee for free!",
"optionColor": "#00ff00"
},
{
"optionId": 2,
"optionName": "5% discount over the entire order"
},
{
"optionId": 3,
"optionName": "Coffee + Cake 3,-"
}
]
}
}
| Property | Type | Explanation |
|---|---|---|
| dialog.required | boolean | Is a choice required? |
| dialog.allowMultipleOptions | boolean | Is more than one choice allowed? |
| dialog.dialogTitle | string | Which title should the dialog show? |
| dialog.columns | int (optional) | How many columns should the dialog use to display the options? |
| dialog.dialogOptions[].optionId | string or integer | The option’s ID; use one consistent ID type within the dialog. |
| dialog.dialogOptions[].optionName | string | The option’s textual description. |
| dialog.dialogOptions[].optionColor | string (optional) | The option’s color in hexadecimal format. |
| requireConfirmation was added in v46 | ||
| dialog.requireConfirmation | boolean (optional) | Do you need to click confirm after selecting an option? Useful to prevent misclicks. |
| Property | Type | Explanation |
|---|---|---|
| dialog.dialogId | string or integer (optional) | Identifier echoed in the follow-up request. Available by MplusKASSA v14.0.0. |
| dialog.dialogOptions[].disabled | boolean (optional) | Prevents selection; defaults to false. Available by MplusKASSA v59.3.0. |
| dialog.dialogOptions[].enabled | boolean (optional) | Inverse of disabled. Supply only one of these flags. Available by MplusKASSA v59.3.0. |
| dialog.dialogOptions[].image | string (optional) | Image reference for the option; rendering depends on the client. Available by MplusKASSA v59.3.2. |
required, allowMultipleOptions and requireConfirmation default to false. Use six-digit RGB hex colors such as #00ff00. Article lookup properties are parsed for form options, but not for dialog options in this checkout.
form
{
"form": {
"id": "customer_registration",
"title": "Register New Customer",
"enableReset": true,
"fields": [
{
"id": "name",
"type": "text",
"required": true,
"label": "Your name",
"hint": "Use your official name",
"value": "John",
"minimumLength": 1,
"maximumLength": 200
},
{
"type": "label",
"value": "Just some information",
"separator": "below"
},
{
"id": "email",
"type": "email"
},
{
"id": "card_number",
"type": "text",
"regex": "^C\\d{8}$"
},
{
"id": "family_size",
"type": "number",
"decimals": 0,
"minimumValue": 1,
"maximumValue": 9
},
{
"id": "allergies",
"type": "select",
"multiple": true,
"columns": 3,
"options": [
{
"id": "peanut",
"label": "Peanuts",
"color": "#a52a2a",
"selected": false,
"image": "https://mpluskassa.nl/images/peanut.png"
},
{
"id": "gluten",
"label": "Gluten",
"color": "#00ff00",
"selected": true
}
]
},
{
"id": "welcome_gift",
"type": "select",
"multiple": false,
"columns": 2,
"options": [
{
"id": "gift_01",
"label": "Peanuts",
"articleNumber": "2343241"
},
{
"id": "gift_02",
"label": "Gluten",
"articleNumber": "2136533",
"disabled": true
}
]
},
{
"id": "start_of_contract",
"type": "date"
},
{
"id": "preferred_delivery_time",
"type": "time"
},
{
"id": "accept_terms",
"type": "checkbox",
"label": "I accept the Terms and Conditions"
}
]
}
}
| Property | Type | Explanation |
|---|---|---|
| form.id | string | Form identifier that will be included when the form is submitted. |
| form.title | string | Title will be displayed above the form. |
| form.enableReset | boolean (optional) | Whether to display the button that will reset the form to its original state. |
| form.fields[].id | string | Field identifier that will be included when the form is submitted. |
| form.fields[].type | string | text, email, password, postalcode, number, date, time, datetime, select, checkbox, label, postaladdress |
| form.fields[].required | boolean | Whether the field is required. |
| form.fields[].separator | string (optional) | none, above, below Available by MplusKASSA v59.3.0. |
| form.fields[].label | string | What caption to display with the form field. |
| form.fields[].hint | string (optional) | A longer explanation to clarify the requirements. |
| form.fields[].value | string (optional) | A default value to populate the field with. |
| form.fields[].minimumLength | int (optional) | A minimum required text length. |
| form.fields[].maximumLength | int (optional) | Maximum permitted text length. |
| form.fields[].regex | string (optional) | A regex pattern to validate the input. |
| form.fields[].decimals | int (optional) | How many decimals to allow on a number field. |
| form.fields[].minimumValue | number (optional) | Minimum value of a number field. |
| form.fields[].maximumValue | number (optional) | Maximum value of a number field. |
| form.fields[].multiple | boolean (optional) | Whether to allow multiple selections on a select field. |
| form.fields[].columns | integer (optional) | How many columns to use to display the select options. |
| form.fields[].options[].id | string | Option identifier that will be included when the form is submitted. |
| form.fields[].options[].label | string | The label that will be display on the option. |
| form.fields[].options[].color | string (optional) | Six-digit RGB hexadecimal color (with optional #) that will be used as background color. |
| form.fields[].options[].selected | boolean (optional) | Whether the option should already be selected. |
| form.fields[].options[].image | string (optional) | This image will be shown on the option. |
| image was added in v59.3.2 | ||
| form.fields[].options[].articleNumber | string (optional) | Will enrich the option button with article information and imagery from the POS system. |
| form.fields[].options[].barcode | string (optional) | Article lookup reference; client support varies. |
| form.fields[].options[].pluNumber | string (optional) | Article lookup reference; client support varies. |
| form.fields[].options[].supplierArticleNumber | string (optional) | Article lookup reference; client support varies. |
| form.fields[].options[].extArticleId | string (optional) | Article lookup reference; client support varies. |
| form.fields[].options[].disabled | boolean (optional) | Can be used to show an option that is not selectable. |
| disabled was added in v59.3.2 | ||
Additional form properties
| Property | Type | Explanation |
|---|---|---|
| form.submitText | string (optional) | Custom submit-button caption. Available by MplusKASSA v59.0.1. |
| form.cancelText | string (optional) | Custom cancel-button caption. Available by MplusKASSA v59.3.0. |
| form.fields[].prefix | string (optional) | Parsed prefix; client support varies. Available by MplusKASSA v59.0.1. |
| form.fields[].suffix | string (optional) | Recognized, but currently assigned to the prefix member by the parser. Do not rely on suffix behavior. Available by MplusKASSA v59.0.1. |
| form.fields[].allowNegative | boolean (optional) | Allow negative numeric input. Available by MplusKASSA v59.0.1. |
| form.fields[].color | string (optional) | Six-digit RGB hexadecimal field color, with optional #. Available by MplusKASSA v59.0.1. |
| form.fields[].futureOnly | boolean (optional) | Parsed future-date constraint; see client limitations below. Available by MplusKASSA v59.0.1. |
| form.fields[].pastOnly | boolean (optional) | Parsed past-date constraint; see client limitations below. Available by MplusKASSA v59.0.1. |
| form.fields[].earliestDate | string (optional) | Parsed using the POS locale date parser, not an ISO 8601 timestamp parser. Available by MplusKASSA v59.0.1. |
| form.fields[].latestDate | string (optional) | Parsed using the POS locale date parser, not an ISO 8601 timestamp parser. Available by MplusKASSA v59.0.1. |
| form.fields[].sunday | object (optional) | Sunday schedule; fields below. Available by MplusKASSA v59.0.1. |
| form.fields[].monday | object (optional) | Monday schedule. Available by MplusKASSA v59.0.1. |
| form.fields[].tuesday | object (optional) | Tuesday schedule. Available by MplusKASSA v59.0.1. |
| form.fields[].wednesday | object (optional) | Wednesday schedule. Available by MplusKASSA v59.0.1. |
| form.fields[].thursday | object (optional) | Thursday schedule. Available by MplusKASSA v59.0.1. |
| form.fields[].friday | object (optional) | Friday schedule. Available by MplusKASSA v59.0.1. |
| form.fields[].saturday | object (optional) | Saturday schedule. Available by MplusKASSA v59.0.1. |
| form.fields[].options[].enabled | boolean (optional) | Inverse of disabled; supply only one flag. Available by MplusKASSA v59.3.0. |
Each weekday object accepts available (boolean, default true), fromHour, fromMinute, throughHour and throughMinute (optional integers). These properties are directly on the field, not inside calendar or number wrappers.
form.enableReset and field required default to false. Form field and option IDs are strings. Option articleNumber accepts an integer or decimal integer string; barcode, pluNumber, supplierArticleNumber and extArticleId are strings.
Client limitations: the current desktop form adapter forwards weekday availability, but not the schedule time ranges, futureOnly, pastOnly, earliest/latest dates or prefix/suffix. Its option conversion forwards ID, label, color and disabled status, but not article/image enrichment or preselection. These fields may be parsed without taking effect in that desktop path. Validate behavior on the target client.
message
{
"message": [
{
"message": "We encountered a situation that requires your attention",
"customerMessage": "ATTENTION REQUIRED",
"displayTime": 5,
"messageDisplayTime": 5,
"customerMessageDisplayTime": 15,
"hideTimestamp": false,
"clearScreen": true,
"clearCustomerScreen": true,
"monospacedFont": true,
"backgroundColor": "#ff0000"
}
]
}
| The message property accepts one message object or an array for multiple messages. | ||
| Property | Type | Explanation |
| message[].message | text (optional) | Show a message on the POS user’s display. |
| message[].customerMessage | text (optional) | Show a message on the POS customer display. |
| message[].displayTime | int (optional) | This will ensure the message and customerMessage are shown for at least this amount of seconds. |
| message[].messageDisplayTime | int (optional) | This will ensure the message is shown for at least this amount of seconds. |
| message[].customerMessageDisplayTime | int (optional) | This will ensure the customerMessage is shown for at most this amount of seconds. |
| message[].hideTimestamp | boolean (optional) | When set to true, this will hide the timestamps that are usually shown in front of the messages. |
| message[].clearScreen | boolean (optional) | When set to true, this will clear all previous messages. |
| message[].clearCustomerScreen | boolean (optional) | When set to true, this will clear the current customer message. |
| message[].monospacedFont | boolean (optional) | When set to true, this will display the messages in a monospaced font so you can better align multiple lines. |
| message[].backgroundColor | string (optional) | The background color of the message popup in hexadecimal format. Or preset color names, like “red” and “green”. Available by MplusKASSA v22.2.0. |
message and messages both accept one message object or an array. Display times are clamped: operator messages to 0–10 seconds, customer messages to 0–60 seconds. displayTime supplies both durations; explicit per-screen durations take precedence. Preset background colors recognized by the parser are red, green, error, success and alert; otherwise use six-digit RGB hex. Boolean message flags default to false. The same message properties can be embedded in scanCode, polling and externalPayment.
requestScanCode
{
"requestScanCode": {
"required": true,
"requestTitle": "Please scan your code now",
"requestId": 1
}
}
| Property | Type | Explanation |
|---|---|---|
| requestScanCode.required | boolean | Is a scan required? |
| requestScanCode.requestTitle | string | What would you like the POS screen to display to the user? |
| Property | Type | Explanation |
|---|---|---|
| requestScanCode.requestId | integer | Supply an ID to correlate the next scan through scanCode.requestId. |
required defaults to true. requestScanCode is rejected as a response to the standalone scanCode event.
displayBarcode
{
"displayBarcode": {
"codeType": "qrcode",
"code": "https://example.com/loremipsum"
}
}
| Property | Type | Explanation |
|---|---|---|
| displayBarcode.codeType | string (optional) | Code type, for example code128 or qrcode; support depends on the display client. |
| displayBarcode.code | string | The contents of the barcode |
| Property | Type | Explanation |
|---|---|---|
| displayBarcode.text | string (optional) | Text displayed alongside the code; message is also accepted. |
codeType defaults to code128. Actual display support depends on the client; the parser does not validate display code types. displayQrcode is a legacy alias for the response property and does not change the default code type.
hideBarcode
{
"hideBarcode": true
}
| Property | Type | Explanation |
|---|---|---|
| hideBarcode | boolean | Instantly hide a code that is currently displayed. |
The current parser acts on the presence of hideBarcode, regardless of its boolean value. Omit the property when you do not want to hide the code. hideQrcode is an alias. If both display and hide are supplied, hide takes precedence.
openUrl
{
"openUrl": {
"url": "https://payment-platform.example.com/transaction/123",
"autoOpen": false,
"urlTitle": "Click here to start payment",
"closeOnDomainChange": true,
"minimumWidth": 800,
"minimumHeight": 500
}
}
| Property | Type | Explanation |
|---|---|---|
| url | text | The actual URL to open. |
| autoOpen | boolean (optional) | Whether or not to automatically open the URL. |
| urlTitle | text (optional) | The title of the link/button in case the URL is not set to open automatically, or is unable to open automatically. |
| closeOnDomainChange | boolean (optional) | Set this if you want the browser component to automatically close when the current domain changes, e.g. from payment-platform.example.com to some-other-domain.com. Available by MplusKASSA v47.1.0. |
| minimumWidth | int (optional) | In case of a browser popup, determines the minimum width the popup should receive. Available by MplusKASSA v48.1.2. |
| minimumHeight | int (optional) | In case of a browser popup, determines the minimum height the popup should receive. Available by MplusKASSA v48.1.2. |
polling
{
"polling": {
"finished": false,
"message": "The process has been completed for 55%",
"customerMessage": "Progress: 55%",
"displayTime": 5,
"messageDisplayTime": 5,
"customerMessageDisplayTime": 15,
"hideTimestamp": false,
"clearScreen": true,
"clearCustomerScreen": true,
"monospacedFont": true
}
}
| Property | Type | Explanation |
|---|---|---|
| polling.finished | boolean | Tell MplusKASSA whether the polling process is finished or not. When you return false, MplusKASSA schedules another request using the configured polling interval. |
| polling.message | text (optional) | Show a message on the POS user’s display. Use this to update the user on progress made in the polling process. |
| polling.customerMessage | text (optional) | Show a message on the POS customer display. Use this to update the customer on progress made in the polling process. |
| polling.displayTime | int (optional) | This will ensure the message and customerMessage are shown for at least this amount of seconds. |
| polling.messageDisplayTime | int (optional) | This will ensure the message is shown for at least this amount of seconds. |
| polling.customerMessageDisplayTime | int (optional) | This will ensure the customerMessage is shown for at most this amount of seconds. |
| polling.hideTimestamp | boolean (optional) | When set to true, this will hide the timestamps that are usually shown in front of the messages. |
| polling.clearScreen | boolean (optional) | When set to true, this will clear all previous messages. |
| polling.clearCustomerScreen | boolean (optional) | When set to true, this will clear the current customer message. |
| polling.monospacedFont | boolean (optional) | When set to true, this will display the messages in a monospaced font so you can better align multiple lines. |
finished defaults to false. Polling also accepts backgroundColor and the other shared message properties.
For backgroundPoll, a response containing requestCustomAction, externalCardScan, prepayTable or entityAnnotations implicitly ends the current poll if no explicit polling object is present. The background thread then starts a fresh request with a new event counter. Explicit polling instructions take precedence.
The desktop dispatcher applies a delay bounded to 10–3000 milliseconds. Polling without an explicit polling or external-payment response uses at least a one-second interval. Successful or cancelled external payments can terminate polling independently. MplusQservice does not perform these automatic retries: its API client must drive continuation.
customActionChange
{
"customActionChange": {
"customActionId": "STATUS_BUTTON",
"buttonCaption": "Current status: ON"
}
}
| Property | Type | Explanation |
|---|---|---|
| customActionChange.customActionId | text | The ID of the customAction button that should be changed. |
| customActionChange.buttonCaption | text | The desired new caption for the customAction button. |
vatMethodChange
{
"vatMethodChange": "shifted"
}
| Property | Type | Explanation |
|---|---|---|
| vatMethodChange | text | inclusive, exclusive, shifted |
externalCardScan
Notify the POS that an external card was scanned, that the POS should know about.
{
"externalCardScan": {
"cardIdentifier": "b4a7689d-4332-4b94-9f97-1dce8dcdca64",
"cardDescription": "My Special Card",
"cardBalance": 76.5,
"cardExpiration": "2019-12-31",
"cardBlocked": false,
"displayTime": 5,
"isNewBalance": false
}
}
| Property | Type | Explanation |
|---|---|---|
| externalCardScan.cardIdentifier | text (optional) | Use any kind of string that you use as identifier for this card within your system. Does not need to be present within the POS. |
| externalCardScan.cardDescription | text (optional) | Enter the name of the card owner, or a description of the card itself. |
| externalCardScan.cardBalance | number (optional) | The card’s current balance. |
| externalCardScan.cardExpiration | datetime (optional) | The date and time when the card expires and is no longer usable. Please note that we do not actually do anything with this date, it is only used for informational purposes in the POS. |
| externalCardScan.cardBlocked | boolean (optional) | When set to true the POS will indicate on screen that the card is blocked. |
| externalCardScan.displayTime | int (optional) | You can use this to influence the time until the card details should be hidden again. This overrides the setting in the POS itself. Set to 0 to keep the details on screen until the next receipt. |
| externalCardScan.isNewBalance | boolean (optional) | When set to true the POS will interpret the balance card as being the balance after the transaction and display accordingly. |
| Even though all properties are optional, nothing will be displayed on the POS if you omit them all. | ||
displayTime is clamped to 0–60 seconds. Card balances are rounded to two decimals. Invalid expiration text produces INVALID_DATA; this path uses a legacy ISO 8601 parser, so do not infer the timezone guarantees of annotation timestamps from this field.
prepayTable
{
"prepayTable": {
"table": {
"number": 20,
"subNumber": 1
},
"sessionId": "367ef280-1b67-11ea-978f-2e728ce88125",
"payments": [
{
"paymentId": "af282ee3-c516-4805-96c1-fd9aed75f330",
"amount": 14.99,
"method": "MY_PAYMENT_METHOD"
}
]
}
}
| Property | Type | Explanation |
|---|---|---|
| prepayTable.table.number | int | Designate the table’s number that the payments are meant for. |
| prepayTable.table.subNumber | int (optional) | Designate the table’s subnumber that the payments are meant for. |
| prepayTable.sessionId | uuid | Provide the session ID of the table. |
| prepayTable.payments[].paymentId | uuid | Provide a unique ID, the POS will use to make sure this payment is not registered more than once. |
| prepayTable.payments[].amount | number | The amount that was paid. |
| prepayTable.payments[].method | string | Required nonempty payment-method reference. It must be valid for this webhook consumer. |
payments accepts an array or one payment object. Every parsed payment requires a non-null paymentId, a nonempty method, and a nonzero amount. There is no omitted-method fallback in the current parser.
requestCustomAction
{
"requestCustomAction": {
"customActionId": "A_CUSTOM_ACTION_ID"
}
}
| Property | Type | Explanation |
|---|---|---|
| requestCustomAction.customActionId | text | The manually configured ID of the customAction button that you would like to trigger. |
| It is important to realize that this is a request to trigger the custom action, not a guarantee that it will. Reasons why the custom action may not trigger are: (1) the POS is not running, (2) the POS is currently in an interrupted state (like processing an electronic payment), (3) the POS currently has no logged in user or (4) the POS is currently in a blocked state (like displaying a dialog). | ||
version
{
"version": "2.4"
}
| Property | Type | Explanation |
|---|---|---|
| version | text | A string representing the version of your software (or the version of the Webhook middleware you created). |
| This version number will be added to the communication log and can help with debugging version-related problems. | ||
The recorded string is truncated to 255 characters. externalVersion is an accepted alias.
externalPayment
Influence the currently running external payment.
{
"externalPayment": {
"externalPaymentId": "7a4d4fe3-1234-4567-89ab-5fc2fd596b26",
"started": false,
"confirmed": false,
"cancelled": false,
"finalAmount": 20,
"externalTransactionReference": "KQUA6JcQ7sW5qgTXpCYXx4Lr",
"receiptTexts": [
{
"type": "cardholder",
"text": "TRANSACTION DETAILS\nTO PRINT\nON THE RECEIPT"
},
{
"type": "merchant",
"text": "COPY FOR THE MERCHANT\nNEEDS CARDHOLDER SIGNATURE",
"requiresSignature": true
}
],
"cardType": "Maestro",
"terminalId": "87420312",
"method": "My Payment Platform",
"requiresReceiptPrinter": true,
"messages": [
{
"message": "Payment ready to be started",
"customerMessage": "Please insert EUR 11.25",
"hideTimestamp": false,
"monospacedFont": false,
"clearScreen": false,
"clearCustomerScreen": false,
"messageDisplayTime": 3,
"customerMessageDisplayTime": 3,
"backgroundColor": "#ff0000"
}
]
}
}
| Property | Type | Explanation |
|---|---|---|
| externalPaymentId | uuid | The external payment ID as received from the POS in the first place. So the POS can verify you are talking about the same payment. |
| started | boolean (optional) | Has the external payment process been started? The external payment flow won’t progress from the start, to poll stage until you respond TRUE. |
| confirmed | boolean (optional) | Has the external payment process been successfully completed? The payment flow will end and the payment will be registered after you respond TRUE to this. |
| cancelled | boolean (optional) | Has the external payment process been cancelled/aborted/failed? The payment flow will end and the payment will be not be registered after you respond TRUE to this. |
| finalAmount | number (optional) | When the external payment succeeds, but with a differing amount than requested, you can specify the actual final amount through this variable. This requires activation of the software setting Webhooks > Algemeen > Webhooks mogen het via hen betaalde bedrag aanpassen. |
| externalTransactionReference | string (optional) | Use this to assign a reference to the external transaction, which will be stored with the POS payment. |
| receiptTexts[].type | string (optional) | cardholder (default), merchant. Use this to tell the POS for whom the receipt is intended. |
| receiptTexts[].text | string | The actual text to print on the receipt. |
| receiptTexts[].requiresSignature | boolean (optional) | When this is true, the POS will prompt the merchant to have the cardholder sign this receipt. |
| cardType | string (optional) | Use this to store the used card type with the payment, e.g. Maestro or VPAY. This may be used by the POS to group payments. |
| terminalId | string (optional) | Use this to store a terminal ID with the payment, which may be used by the POS to group payments. |
| method | string (optional) | Use this to store which payment method was used externally. |
| requiresReceiptPrinter | boolean (optional) | Use this in the startExternalPayment response to let us know a configured printer is a requirement for a successful transaction. Available by MplusKASSA v50.0.2. |
| For an explanation of all the remaining message-related properties, please see message. | ||
| Property | Type | Explanation |
|---|---|---|
| externalPayment.receiptFooters | object or array (optional) | Receipt footers to retain with an external payment, using the receiptFooter structure. Supply them with the final confirmed: true or cancelled: true response. Available by MplusKASSA v61.0.0. |
| externalPayment.messages | object or array (optional) | Shared message object(s). A nested message object/array replaces messages parsed directly from the payment object. |
receiptFooter, footer and footers are aliases for receiptFooters. Null external-payment properties are skipped. Empty receipt texts are omitted; receipt type defaults to cardholder and requiresSignature defaults to false. Final amounts are rounded to two decimals. Whether an adjusted amount may be lower or higher is checked separately by the payment flow. Send a valid body for startExternalPayment and echo the matching externalPaymentId.
entityAnnotations
Sets annotations for one or more entities. This response accepts a single object or an array of objects. Each item replaces the complete annotation list owned by the responding webhook consumer for that exact entity; it does not merge by annotation ID. Other consumers’ annotation sets are retained. Send annotations: [] to remove your set. Omitting annotations also produces an empty list, so always include it explicitly.
{
"entityAnnotations": [
{
"entity": {
"type": "TABLE",
"branchNumber": 1,
"tableNumber": 20,
"tableSubNumber": 0
},
"annotations": [
{
"id": "reservation-123",
"text": "Reservation for Alice, party of four",
"badge": "18:30",
"customActionId": "OPEN_RESERVATION",
"scheduledAt": "2026-09-22T18:30:00+02:00",
"expiresAt": "2026-09-22T22:00:00+02:00"
}
]
}
]
}
| Property | Type | Explanation |
|---|---|---|
| entity | object | Required entity identifier; shapes below. |
| annotations | array | Complete replacement list for this entity and consumer. A non-array value is rejected. |
| annotations[].id | string | Nonempty identifier. Entries without it are ignored when displayed. |
| annotations[].text | string | Nonempty display text. Entries without it are ignored when displayed. |
| annotations[].badge | string (optional) | Short badge text. |
| annotations[].icon | string (optional) | Icon name in the POS icon collection, not an arbitrary URL. Displayed only if that icon exists. |
| annotations[].customActionId | string (optional) | Custom action associated with the annotation. Activation can send customAction.annotationId containing this annotation’s id. |
| annotations[].scheduledAt | datetime (optional) | ISO 8601 datetime with timezone offset, parsed with the timezone-aware helper. Used for scheduling/order indication; it is not a delayed webhook trigger. |
| annotations[].expiresAt | datetime (optional) | ISO 8601 datetime with timezone offset. Expired annotations are excluded when read for display. |
The consumer ID is taken from the current webhook configuration; do not supply a different webhookConsumerId to select an owner. The store accepts the JSON array, while the display reader skips non-object entries and entries lacking string id or text. Invalid or non-string timestamps are treated as absent, so validate them before sending. The table UI displays table annotations; accepting another entity type does not imply every screen displays its annotations.
Entity identifiers
entity.type is a case-sensitive enum string. Entity property names may use lower camel case as below; the parser uppercases their first character before passing them to the entity decoder.
| entity.type | Required identifier properties |
|---|---|
| TABLE | branchNumber (positive integer), tableNumber and tableSubNumber (integers identifying a valid table). |
| ORDER, INVOICE | uuid plus version (positive integer or -1 for the latest-version sentinel). |
| RECEIPT, PROPOSAL, CONTRACT, PACKING_SLIP | uuid. |
| PURCHASE_ORDER, PURCHASE_DELIVERY, INTERBRANCH_ORDER, INTERBRANCH_SHIPMENT | yearNumber string in the administration’s year/number representation. |
| INTERBRANCH_DELIVERY | yearSubNumber string in the administration’s year/number/subnumber representation. |
Supply exactly the identifier shape matching the type. A reference string fallback exists in the decoder but does not satisfy validation for the entity types above. The latest-version sentinel is accepted as an identifier; annotation storage uses the serialized identifier as the key and does not resolve it to a concrete document version.
Accepted response aliases
Use the property names shown in the main reference for new integrations. The parser also accepts the spellings below in their corresponding object context. Aliases are case-sensitive and are not global substitutions. For example, id means different things inside a dialog, line or payment. Supply one spelling per property; conflicting aliases have parser-order-dependent behavior. These aliases apply to responses, not to the request fields emitted by the POS.
| Property/context | Accepted spellings |
|---|---|
| line changes | lineChanges, changes |
| line additions | lineAdditions, additions |
| line deletions | lineDeletions, deletions |
| lock session | lockSession, lock |
| lock session for additions | lockSessionForAdditions, lockForAdditions, lockAdditions |
| messages | messages, message |
| relation number | relationNumber, relation |
| receipt footer | receiptFooter, receiptFooters, footer, footers |
| bill footer | billFooter, billFooters, receiptFooter, receiptFooters, footer, footers |
| session id | sessionId, id |
| line id | lineId, id |
| discount id | discountId, id |
| article number | articleNumber, article, number |
| line text | lineText, text, lineDescription, description |
| price incl | priceIncl, price |
| plu number | pluNumber, plu |
| ext article id | extArticleId, externalArticleId |
| ext line id | extLineId, externalLineId |
| apply to quantity | applyToQuantity, quantity |
| discount percentage | discountPercentage, percentage |
| discount amount | discountAmount, amount |
| discount description | discountDescription, description, text |
| table number | tableNumber, number |
| table sub number | tableSubNumber, subNumber, sub |
| payments | payments, payment |
| barcode type | barcodeType, codeType, type |
| payment id | paymentId, id |
| payment amount | paymentAmount, amount |
| payment method | paymentMethod, method |
| external payment id | externalPaymentId, id |
| started | started, start |
| confirmed | confirmed, confirm |
| cancelled | cancelled, canceled, cancel |
| final amount | finalAmount, final |
| external transaction reference | externalTransactionReference, extTransactionRef, transactionReference, transactionRef, externalTransaction, extTransaction, externalTransactionId, extTransactionId |
| receipt texts | receiptTexts, receiptText, receipt, texts |
| card type | cardType, card |
| terminal id | terminalId, extTerminalId |
| external method | externalMethod, extMethod, method |
| requires signature | requiresSignature, signatureRequired |
| allow multiple options | allowMultipleOptions, allowMultiple, multiple |
| require confirmation | requireConfirmation, confirmationRequired, confirm |
| columns | columns, cols |
| dialog id | dialogId, id |
| form id | formId, id |
| enable reset | enableReset, reset, enableClear, clear |
| cancel text | cancelText, cancel |
| submit text | submitText, submit |
| dialog or form title | dialogTitle, title, dialogName, name, dialogText, text, formTitle |
| dialog options | dialogOptions, options |
| form fields | formFields, fields |
| option id | optionId, id |
| dialog option name or form option label | optionName, name, optionText, text, optionTitle, title, optionLabel, label |
| field id | fieldId, id |
| field type | fieldType, type |
| field required | fieldRequired, required |
| field label | fieldLabel, label |
| field hint | fieldHint, hint |
| field value | fieldValue, value |
| field minimum length | fieldMinimumLength, minimumLength |
| field maximum length | fieldMaximumLength, maximumLength |
| field regex | fieldRegex, regex |
| field prefix | fieldPrefix, prefix |
| field suffix | fieldSuffix, suffix |
| field decimals | fieldDecimals, decimals |
| field minimum value | fieldMinimumValue, minimumValue, minValue |
| field maximum value | fieldMaximumValue, maximumValue, maxValue |
| field allow negative | fieldAllowNegative, allowNegative, negative |
| field future only | fieldFutureOnly, futureOnly |
| field past only | fieldPastOnly, pastOnly |
| field earliest date | fieldEarliestDate, earliestDate |
| field latest date | fieldLatestDate, latestDate |
| field sunday | sunday, sun, zondag, zo |
| field monday | monday, mon, maandag, ma |
| field tuesday | tuesday, tue, dinsdag, di |
| field wednesday | wednesday, wed, woensdag, wo |
| field thursday | thursday, thu, donderdag, do |
| field friday | friday, fri, vrijdag, vr |
| field saturday | saturday, sat, zaterdag, za |
| field multiple | fieldMultiple, multiple |
| field columns | fieldColumns, columns |
| field options | fieldOptions, options |
| option selected | optionSelected, selected |
| option article number | optionArticleNumber, articleNumber |
| option barcode | optionBarcode, barcode |
| option plu number | optionPluNumber, pluNumber, plu |
| option supplier article number | optionSupplierArticleNumber, supplierArticleNumber |
| option ext article id | optionExtArticleId, extArticleId |
| form field or form option color | fieldColor, fieldColour, color, colour |
| dialog option color | optionColor, optionColour, color, colour |
| request id | requestId, id |
| request title | requestTitle, title |
| custom action id | customActionId, id |
| button caption | buttonCaption, caption |
| card identifier | cardIdentifier, identifier, id |
| card balance | cardBalance, balance |
| card description | cardDescription, description, desc |
| card expiration | cardExpiration, expiration |
| card blocked | cardBlocked, blocked |
| new balance | isNewBalance, isNewCardBalance, newBalance, newCardBalance, isNew, new |
| hide timestamp | hideTimestamp, noTimestamp |
| monospaced font | monospaced, monospacedFont |
| clear screen | clear, clearScreen, clearMessage, clearMessages |
| clear customer screen | clearCustomer, clearCustomerMessage, clearCustomerMessages, clearCustomerScreen |
| message | message, text, textBefore |
| message after | messageAfter, textAfter |
| customer message | customerMessage, customerText |
| display time | displayTime, time |
| background color | backgroundColor, backgroundColour |
| barcode | barcode, qrcode, code |
| print separate | printSeparate, separate |
| external version | version, externalVersion |
| auto open | autoOpen, auto |
| url title | urlTitle, title |
| minimum width | minimumWidth, minWidth |
| minimum height | minimumHeight, minHeight |
The exact root aliases displayQrcode and hideQrcode are accepted for displayBarcode and hideBarcode. enabled is the inverse of disabled in dialog and form options. error.message also accepts text. annotations and entity have no alternate spelling at the annotation-item level; entity identifier properties have the first-character normalization described above.
Error code reference
The following codes are defined in this checkout. Some identify local transport or validation failures and are not necessarily delivered as an error webhook. Inspect error.message for the specific cause. Consumer-returned error.code is a string and is not restricted to this list.
| Code | Meaning |
|---|---|
| INVALID_SIGNATURE | The supplied request signature is invalid. |
| NO_SIGNATURE | Required signature is absent. |
| INVALID_JSON | The response body cannot be parsed as JSON. |
| INVALID_DATA | A response value has an invalid type or value. |
| INVALID_SUBSCRIPTION_ID | The subscription identifier is invalid. |
| NO_SUBSCRIPTION_ID | Required subscription identifier is absent. |
| NO_CONTENT_TYPE | Required content type is absent. |
| INVALID_CONTENT_TYPE | The content type is unsupported. |
| NO_EVENT_DETAILS | Required event metadata is absent. |
| NO_SCANNED_CODE | Required scanned code is absent. |
| LINE_ALREADY_HAS_DISCOUNT | A conflicting existing discount prevents the requested change. |
| LINE_ALREADY_HAS_DISCOUNT_FROM_OTHER_WEBHOOK | The existing discount belongs to a different webhook consumer. |
| INVALID_LINE_ID | The line reference is invalid for the session. |
| LINE_ID_ALREADY_EXISTS | The proposed line identifier is already in use. |
| INVALID_RELATION_NUMBER | The relation reference is invalid. |
| INVALID_ARTICLE | The supplied article references cannot be resolved. |
| INVALID_DISCOUNT_PERCENTAGE | The discount percentage is outside the permitted range. |
| INVALID_RECEIPT_FOOTER_TEXT | The receipt footer text fails validation. |
| INVALID_RECEIPT_FOOTER_CODE | The barcode contents fail validation. |
| INVALID_RECEIPT_FOOTER_CODE_TYPE | The receipt barcode type is unsupported. |
| LINE_CHANGE_NOT_ALLOWED | The event, document or consumer permissions prohibit this line change. |
| LINE_ADDITION_NOT_ALLOWED | The event or document does not allow line additions. |
| LINE_DELETION_NOT_ALLOWED | The event, document or consumer permissions prohibit this deletion. |
| INVALID_EXTERNAL_PAYMENT_ID | The external payment identifier is invalid or does not match the active payment. |
| EXTERNAL_PAYMENT_ID_ALREADY_USED | The external payment identifier has already been used. |
| MISSING_REQUIRED_BODY | This event requires a nonempty response body. |
| MISSING_REQUIRED_FIELD | A required response property is missing or unusable. |
| FINAL_AMOUNT_ADJUSTMENT_NOT_ALLOWED | Changing the external payment amount is disabled. |
| LOWER_FINAL_AMOUNT_NOT_ALLOWED | A lower final amount is not allowed in this payment flow. |
| HIGHER_FINAL_AMOUNT_NOT_ALLOWED | A higher final amount is not allowed in this payment flow. |
| HTTP_PARSING_ERROR | The HTTP response could not be parsed. |
| WEBHOOK_CANCELLED_BY_USER | The user cancelled the webhook interaction. |
| RESPONSE_NOT_ALLOWED_HERE | This response action is not allowed for the current event or context. |
| UNEXPECTED_FIELD | An unexpected response field was reported. General root-field rejection is disabled in this checkout. |
| WEBHOOK_TIMED_OUT | The webhook request timed out. |
| INVALID_PAYMENT_METHOD | The requested payment method is not permitted for this consumer. |
| ACTIVE_SESSION_CHANGED | The active session changed during webhook handling. |
| JWT_AUTHENTICATION | Authentication-token acquisition failed. |
| INVALID_APPLY_TO_QUANTITY | Discount quantity has the wrong sign or exceeds the available quantity. |
| PREPAY_TABLE_FAILED | The table prepayment could not be registered. |
Timeouts and JWT authentication failures are not sent back as error webhooks. User cancellation during start/poll external payment is handled through the cancellation flow instead of a redundant error callback.