Mergeport Ordering is a channel manager for online ordering and delivery services. With a single interface we can forward all incoming orders from multiple service providers in a standardized format.
If not already done, contact us for a developer account. You will receive a unique siteId and apiKey.
Typically, once you register with a service provider, they will provide you with some access details for their services, e.g. restaurantId or apiKey and apiSecret.
You will need to forward each of those access details to Mergeport and we are ready to go.
Integrate Mergeport with a minimal setup:
GET /pos/orders?filter=activePATCH /pos/orders/{id} with body:{
"state": "acceptedByPOS"
}
Minimum requirement:
acceptedByPOS The connected online ordering services will synchronize orders with our platform.
You can download all "active" orders [ status=receivedByProvider or status=canceledByProvider ] by calling /pos/orders?filter=active.
If you are using polling, we recommend an interval of 1-2 minutes.
Should anything go wrong during the download of the orders (aborted or missing connectivity), simply repeat the request until you have stored them, and then mark them as downloaded/read by calling /pos/orders/{id} and setting [ status=fetchedByPOS ] to avoid duplicates.
From that moment on, the order won't be active anymore.
To accept the order, you need to update the status to confirm the processing [ status=acceptedByPOS ]. Upon confirmation, we will forward the information to the provider (if supported) and set the status to acceptedByPOS. This action confirms the processing. You can also accept the order right away and skip the fetchedByPOS state.
Each order contains:
"possibleStateChanges": [...]
Only these states can be sent.
Required:
acceptedByPOSRule:
Only send states listed in possibleStateChanges
If the provider cancels an already processed order, it is being added again to the active orders with the state canceledByProvider. This requests the POS to process the cancelation internally and set the order to canceledByPOS.
Please be aware that our interface can only forward and support as much information/features as the corresponding service provider provides. We do the best to standardize the information, but some data may be missing in the different cases.
In the following, we use different terms to explain the workflow/functionality of the API. Let us give you a quick briefing on how we use the mentioned terms:
All prices are expressed as a structured object, with the currency code, e.g. "EUR" and the value in the atomic part of that currency, typically "cent". 3€ will be represented as 300.
Deposit:
We forward the deposit fees we receive from providers to the POS systems. These fees are usually transmitted on an item-specific basis in the deposit field and are already included in the item price. However, not all providers send information about deposits (e.g., Just Eat Takeaway), and some providers (e.g., foodora) only send the total deposit for the entire order. In such cases, this total is included in the order.deposit field.
We use a flat list of order items items within the order object which, paired with the parentId, offers the flexibility to represent any hierarchical order data structure. Please note: the order item quantity is absolute, we also provide the relativeQuantity. If the customer has ordered three pizzas, all of them with 2 x cheese as modifier, this will result in two order items:
id quantity relativeQuantity description singlePrice rowTotal parentId
9a1 3 3 pizza 700 2100 null
3fc 6 2 cheese 200 1200 9a1
total 3300The absolut quantity makes sum checks easier, without having to reconstruct the whole order first. This is very helpful when analyzing data and logs for support cases.
Items can either be synced from the POS to the ordering platform (if supported) or managed directly on the platform side.
If items are managed on the platform, the POS item ID can be configured there. In this case, orders will include a posItemId, which serves as the primary identifier for items. As a fallback, orderItemId can be used as a secondary identifier.
A POS must be able to handle items without a posItemId.
In these cases, recommended approaches include:
Important: Do not reject the order.
additionalCosts is a free-text field.
Examples:
Important:
Date-time fields and parameters must be formatted as UTC ISO 8601 strings, e.g. '2000-01-01T10:10:10.123Z'.
All requests will be validated. The following cases will lead to a validation error:
Typically, our responses are being returned with the HTTP status codes 200 OK, 400 Bad Request, 401 Unauthorized, 403 Forbidden. We have three response types, you can easily check the response for the following fields:
[data] - for read operations. The response contains an object or array of the requested datasuccess - for generic operations. The success property contains a message describing the operation result.error - for minor errors. The error property contains a code and a messageapiKey in the "Authorization" header. Mergeport provides it during registration. Use a valid Site apiKey in the "Authorization" header. Standard-signed webhook integrations may alternatively authenticate the selected POS write calls described in POS webhook integration. Do not combine both authentication modes. Other calls, including order retrieval, continue to use the Site API key.
Mergeport supports three integration patterns:
Webhooks are recommended for cloud POS systems. During the initial joint setup with MERGEPORT, agree which of the following optional features your connection uses. They are per-Site POS settings, not mandatory requirements for every partner.
| Setting | Purpose |
|---|---|
webhookSigningMode: "standard-webhooks" |
Sign full-order webhooks with HMAC instead of transmitting webhookSecret. Also permits the selected signed POS API calls described below; regular Site API keys remain supported. |
onlyAcceptedOrders |
Forward orders after acceptance rather than at initial receipt. Suitable for an additional downstream receiver; another POS or the platform must provide acceptance where required. This setting does not accept orders itself. |
forwardAllStatusChanges |
Forward full-order updates for additional lifecycle states instead of just the usual order/cancellation delivery. This is separate from the minimal order-event subscription. |
disableAutoRejection |
For active POS delivery with scheduled retries, suppress the terminal MERGEPORT rejection/status update after retry exhaustion. Retries still stop; provider timeouts/cancellations, separate expiry checks and other POS connections remain possible. Arrange manual fulfilment when needed. |
orderEventsUrl, orderEventTypes, orderEventsSecret |
Subscribe separately to selected status, courier, fleet or terminal POS-delivery-failure notifications. Use a dedicated event signing secret; messages identify the affected order rather than sending it in full. See Order events. |
Confirm the chosen settings with MERGEPORT before enabling them. Available
Controller controls depend on the installed POS definition. In particular,
the subscription is optional. With an event URL, supply orderEventTypes as an
array, not a comma-separated string; an empty array unsubscribes. Without a
subscription the fields can be omitted. Do not preselect events through defaults.
onlyAcceptedOrders and forwardAllStatusChanges currently control the
notification-only webhook connection (dummyPOS); they do not change every active
POS adapter's injection rules. With both enabled, additional status notifications
remain enabled. Conversely, disableAutoRejection applies to the active POS retry
flow, not this notification-only connection. Confirm the intended connection type
during setup rather than copying all switches to every adapter.
Receive full normalized orders and acknowledge delivery separately from accepting/processing an order via PATCH /pos/orders/{id}. Order events are short change notifications, not complete orders. Events have no retries, replay or guaranteed delivery: avoid continuous polling as the primary mechanism, but retrieve current orders for reconciliation when needed. See POS webhook integration for setup, payloads, signing and delivery behavior, and Order events for subscription details.
Simple and universal fallback.
GET /pos/orders?filter=active
Recommendation:
Use for simple setups or as fallback.
Optional order-event subscriptions: after WebSocket login, send {"action":"subscribeOrderEvents","data":{"orderEventTypes":["order.statusChanged","order.deliveryUpdated","order.deliveryFleetUpdated","order.posDeliveryFailed"]}}. Notifications have action: orderEvent. An empty list unsubscribes; reconnect requires subscribing again. No replay; existing clients receive no new message types without opt-in. See Order events.
Use WebSocket for systems with a persistent connection (for example local servers, terminals, or always-on tablets).
wss://socket.ordering.mergeport.com/v4apiKey via Sec-WebSocket-Protocol or accesstokenGotNewOrder events in real-timePATCH /pos/orders/{id}Recommendation:
Use for distributed or local systems without a public webhook endpoint.
WebSocket-URL: wss://socket.ordering.mergeport.com/v4
This API can give you push notifications of arriving orders or deliver the entire order upon arrival. All REST API functions can be used directly.
Use WebSocket for persistent or local systems, or as an alternative to webhooks when no public webhook endpoint is available.
To establish a connection with the WebSocket, you need to set a valid apiKey in the Sec-WebSocket-Protocol header. For example "'Sec-WebSocket-Protocol': '1f3a2007-8674-4496-9ccb-f1e9a8bebae5'".
// WebSocket Client endpoint to open the connection
let exampleSocket = new WebSocket(url, apiKey);
//Sample connect: let exampleSocket = new WebSocket("wss://socket.ordering.mergeport.com/v4", "1f3a2007-8674-4496-9ccb-f1e9a8bebae5");
// you need to replace the sample key "1f3a2007-8674-4496-9ccb-f1e9a8bebae5" with your own provided **apiKey**
// Event handler for the WebSocket connection opening
exampleSocket.onopen = function (event) {
exampleSocket.send("Here's some text that the server is urgently awaiting!");
};
// Event handler for receiving text messages
exampleSocket.onmessage = function (event) {
console.log(event.data);
}
// Event handler for errors in the WebSocket object
exampleSocket.onerror = function (event) {
console.log("Error ",event.data);
}
// Event handler for the close connection event
exampleSocket.onclose = function(event) {
console.log("WebSocket is closed now.");
};
// Function for sending commands to the server
function sendAction(action, data = null) {
// Construct a msg object containing the data the server needs to process the message from the client.
var msg = {
action: action,
data: data,
date: Date.now()
};
// Send the msg object as a JSON-formatted string.
exampleSocket.send(JSON.stringify(msg));
}
// Send a test command for example get the version
sendAction("version");
// Finally close the connection
exampleSocket.close();apiKey as an url parameter accesstokenlet exampleSocket = new WebSocket("wss://socket.ordering.mergeport.com/v4?accesstoken=1f3a2007-8674-4496-9ccb-f1e9a8bebae5"); gotNewOrder Upon arrival of new orders, the Websocket sends an GotNewOrder-Action with the order
{
"action": "GotNewOrder",
"data": {
"orderId": "123456789",
"providerId": "c933b71f-8efc-48ce-bd8c-630eb153ce10",
"order": { **have_a_look_at_the_order_schema** }
}
} GetTable Upon arrival of provider request for table data, the Websocket sends an GetTable-Action with the table request
{
"action": "GetTable",
"data": {
"siteId": "c933b71f-8efc-48ce-bd8c-630eb153ce10",
"tableId": "15",
"providerId": "e5ec3c9a-325a-897e-a6b3-23a1953a6eee"
}
}The WebSocket supports the whole set of functionalities. Hence why you will find a "WebSocket" action in the description of every REST-endpoint. Just pass the WebSocket action as the "action" parameter in the WebSocket request (for example "GetOrders"):
{
"action": "GetOrders"
}If you has to pas an url parameter {id} in the REST call you can pass them in the Socket-call as id:
{
"action": "GetOrder",
"id": "8702f7e0-b2a7-452f-95db-ee69fd0aa3b6"
}To serialize a requestBodyData inside the WebSocket-request, just add a data parameter:
{
"action": "SetOrderState",
"id": "8702f7e0-b2a7-452f-95db-ee69fd0aa3b6",
"data": {
"state": "receivedByProvider"
}
} PutTable Upon arrival of GetTable-Action, you should respond with an PutTable-Action with the table data
{
"action": "PutTable",
"data": {
"siteId": "c933b71f-8efc-48ce-bd8c-630eb153ce10",
"tableId": "15",
"providerId": "e5ec3c9a-325a-897e-a6b3-23a1953a6eee",
"table": { **have_a_look_at_the_table_schema** }
}
}In order to keep the WebSocket connection alive, the client is supposed to ping periodically. We recommend a period of 60s.
{
"action": "ka",
"data": "ping"
}The maximum connection duration of the WebSocket API is 2h and cannot be increased. Hence why the client needs to implement a reconnect upon the closing signal.
Each connection authenticates with the Site API key and reloads the current Site. Saving a disabled Site closes its ordinary POS connections; the existing Controller exception remains. Rotating the Site API key invalidates connections using the old key, including Controller connections. Reconnect with the current key; disabled or expired Sites cannot establish ordinary POS connections. Failed authentication returns HTTP 401 during the handshake. User-role changes do not revoke these independent Site-key connections. The existing message protocol is unchanged.
Both API documents share one product version. The version describes the code and documentation snapshot, not its production deployment status. The /beta documentation can preview changes while /v4 continues to serve a pinned production snapshot. Lambda versions identify the exact deployed function builds. Existing API paths do not change when the product version changes.
Prepared release snapshot; production promotion is tracked separately.
Menu channels: shared optional menuTypes override per provider activation, otherwise POS-menu types and provider fallback. Wolt item fulfillment, separate Uber delivery/pickup variants with matching incremental updates and independent comparison state, JET delivery/collection menus and foodora catalog variants. Deliveroo remains a shared catalog. Existing channel configurations require a reviewed compatibility setup before rollout; incoming orders and POS item identities are unchanged. Uber requires delivery and a common catalog; distinct fulfillment assortments use item availability while categories, options and menu hours remain shared. Item/category menu membership is preserved for JET and foodora and Wolt methods are resolved per item. No automatic provider service activation or old-menu deletion.
Wolt menu channel: item availability updates also update matching option values, including nested choices, through the existing updateMenuItems flow. Choice lists and prices remain unchanged; partial provider failures are reported through the existing channel status and retry policy.
Internal diagnostics: technical notification attempts gain structured operation/error-code grouping while preserving existing error and administrative Site emails. No POS/provider API contract changes. Deployment and monitoring-rule configuration are required to use the new events.
Prepared release snapshot; production promotion is tracked separately.
POS acceptance: a missing receipt no longer blocks acceptedByPOS. requireReceipt remains a request to supply a receipt; submitted receipts are still validated.
Foodora: direct restaurant deliveries send the existing order_picked_up callback on delivered; customer pickup remains supported and logistics deliveries do not send this callback on delivered.
Foodora cash orders: a valid collectFromCustomer above grandTotal determines the payment amount and amountToPay. Paid/card orders and equal or lower collection amounts remain unchanged; item prices are preserved and no fee position is invented.
Compatibility change: discount position allocations are now returned exclusively as discounts[].orderItems instead of discounts[].items. Consumers of the previous field must update their access. Historical allocations are translated on reads without a database migration; order items, prices and payment totals are unchanged.
Internal notifications: user creation no longer sends userCreate to Make; SES password-setup emails remain unchanged. Retained Site/user-update notifications await one bounded Make delivery attempt with safe correlated diagnostics. Delivery failure does not roll back saved changes; no automatic retries are introduced.
POS menu allergens: additive A1-A6 cereal and H1-H8 nut subcodes in the existing allergens string. Uber/Wolt export localized specific names; JET Connect exports existing detailed enums. Existing codes remain compatible. Configure the allergen mapping and perform a full menu upload; no stored-item migration or price/order changes.
Menu channels: JET, foodora and Deliveroo V3 retain automatic menu changes received during an unresolved upload and submit the latest menu after confirmed success. Availability follows the new menu; manual conflicts and uncertain-result safeguards remain unchanged.
JET Connect: explicitly identified platform deliveries no longer produce full-address validation warnings when the provider omits address fields. Merchant delivery and unknown delivery ownership retain existing checks; supplied address data is preserved.
Order reads: removed the internal five-second item-hydration cutoff from POS/provider order retrieval; complete, strongly consistent pagination is retained. Webhook/background hydration keeps its existing bound; infrastructure timeouts still apply.
WebSocket: connection lookup uses one Promise-based AWS request instead of mixing callback and Promise execution. Current Site authorization and message contracts remain unchanged.
Prepared release snapshot; production promotion is tracked separately.
Authentication: password setup/reset sessions correctly recognize the Gateway-routed user PATCH method. Restricted access remains limited to setting the authenticated user's password; normal login and existing account permissions are unchanged.
Menu channels: Wolt/JET preserve every known allergen group in mixed code strings such as AF,G. JET adds optional explicit vegan/vegetarian label mapping for products and modifiers; existing channels require enabling the field and a menu upload. Prices and order processing are unchanged.
Uber menu channel: optional allergens and dietary-label mappings expand POS allergen codes to menu-language names and export vegan/vegetarian declarations. Existing channels require explicit field links and a full menu upload; additives, prices and incoming orders are unchanged.
Uber orders: removed zero-quantity options retain their removal instructions without adding their former unit prices to item totals, in both supported payload formats. Selected options, order/payment totals and existing stored orders are unchanged.
Uber menu channel: full uploads apply the selected activation's allowSpecialInstructions setting to item-level instructions. False/missing disables them; true enables them. Existing menus require a full upload; incoming order notes and price/availability-only updates are unchanged.
Uber menu channel: honor explicit option multiselect using group-scoped quantity limits, preserving box totals, prices and defaults. Missing flags retain existing behavior; existing menus require a subsequent full upload.
Order item reads: full-order reads, status updates and POS retry payloads load every item page consistently; missing embedded webhook items are loaded before sending. Item-read failures no longer return successful partial orders. Already completed status/provider actions are not rolled back. Incoming order writes, subscription, retry and webhook ordering policies are unchanged.
Uber menu channel: automatic changes are coalesced by the scheduler with cooldown and Retry-After handling. The optional updateMenuItems function supports mapped price and availability updates and defaults to off. Automatic choice requires both functions explicitly onChange with matching mappings; item-only mode never implicitly uploads a full menu. Automatic synchronization is deferred rather than sent inside the item request.
Uber menu channel: disabled products and modifiers are correctly marked sold out; explicitly enabled items clear prior suspension. Existing remote menus require a successful subsequent upload. No price, identifier or option-relationship changes.
Channels: track provider processing separately from HTTP acceptance. Correlated JET/foodora callbacks and Deliveroo V3 job checks update the latest upload result; dependent availability changes wait for confirmed success. Wolt and uncorrelated Deliveroo V1 responses do not claim publication confirmation. No automatic upload retry or online configuration migration.
POS order-state responses and history: optional successful providerResults distinguish acknowledged, asynchronously accepted and explicitly already-applied actions. Errors and warnings retain their existing behavior. Main status-webhook success enriches the original history entry after local persistence, without extra events or callback retries. No configuration change or migration required.
JET Connect: optional per-country previous order key supports coordinated inbound webhook credential rotation. Outgoing requests continue to use only the current key; HMAC and restaurant checks remain unchanged. Remove the temporary previous key after the sender has switched. No automatic configuration changes.
POS/provider API: optional DB-configured delivery, takeaway and inHouse lifecycles expose effective providerTransmission flags and fixed-English descriptions. Local time changes remain independent of transmission. Existing definitions retain legacy fallback; complete stateTransitions replace the Main timeChangeStates list while preserving order restrictions. Definitions are activated manually; no automatic migration.
JET Connect: after required POS acceptance, local progress follows legacy Lieferando, independently of the ETA switch. With allowDeliveryTimeChange enabled, merchant deliveries also receive legacy-compatible time-change flags for preparing, inDelivery and inDelivery to delivered, in addition to acceptance. Later time changes use the separate JET ETA endpoint, never repeat acceptance, and preserve the previous state/time on failure. No same-state updates or ETA for JET courier delivery/collection. JET-side pilot enablement remains required; acceptance logic and other providers are unchanged.
Admin API: PATCH /admin/site/{id}/providers/{providerInstanceId} updates one existing provider activation without replacing the entire provider list. Omitted settings are preserved, accessDetails merges by immediate key, and supplied nested objects/lists replace their field. Existing validation, permissions, Restaurant ownership and channel lifecycle apply; concurrent edits of submitted fields return a conflict. Existing Site PATCH/add/remove behavior is unchanged. No migration or new configuration required.
Deliveroo V3 menu upload: accept upload-URL responses containing upload_url and version without an echoed menu ID. Publication retains the requested menu; contradictory echoed IDs remain rejected. No configuration or data migration required.
Deliveroo availability: incremental updates and explicit maintenance use the menu-scoped V1 endpoint with the configured menuId (default main), matching API-uploaded menus. Payloads and item status semantics are unchanged; no new setting or migration is required.
Deliveroo menu bundles: component prices now use parent-item ITEM overrides with the bundle ID and section context_id, without a competing MODIFIER override. Standalone prices, PLUs, ordinary options and POS inputs remain unchanged; no data migration or new setting is required.
POS catalog: optional bundle object with optional partySize, using existing optionsList sections and explicit choice prices. Deliveroo exports bundles and standalone component products with context-specific prices; ordinary items and other providers retain their behavior.
POS catalog: optional hidden boolean, currently interpreted only by Deliveroo availability synchronization. True takes precedence over enabled; false clears hiding while preserving any stock restriction. POST replacement and PATCH partial semantics remain unchanged. Ordinary stock synchronization remains incremental POST.
Deliveroo menu uploads: optional menuApiVersion "3" uses the same menu through S3 upload and a version-specific publication job. Missing configuration retains V1; item availability and order flows are unchanged. Initial upload acceptance does not establish completed publication; the correlated processing result is tracked separately. No automatic upload retries, fallback or definition import.
Deliveroo menu schedules: resolve existing PosAvailability menu assignments, with channel-specific overrides. Convert exclusive POS period ends to inclusive Deliveroo minute boundaries; reject overlapping or incomplete scheduled mealtimes unless a single fallback menu covers the gaps. No automatic channel configuration changes.
Deliveroo menu channels: optionally export existing POS menu names, descriptions and cover images, plus explicit item dietary labels. Existing saved channel links require opting into the new mappings; the default mealtime remains when no menus are mapped. POS option groups accept an optional localized description. No new required fields or automatic configuration migration.
JET configuration: set Provider.accessConfig.apiUrl and orderStatusApiUrl before rollout. Existing menu, availability and status services retain their hosts but now read the central configuration; no runtime URL fallback. Acceptance with ETA uses the status service, separate ETA updates use apiUrl. Add the optional allowDeliveryTimeChange descriptor to Provider.accessDetails and enable it per Site activation; countryCredentials owns country-specific brandSlug values.
JET Connect: optional per-activation customer delivery ETA on acceptedByPOS for merchant deliveries. Requires JET pilot enablement and central country-specific configuration. ETA transmission remains disabled by default and uses the existing acceptance flow; autoAccept ETA failures retain acceptance and the previous time with an HTTP 200 warning.
POS signed requests: correct Beta REST stage detection; production signatures and regular Site API-key authentication remain unchanged.
POS order status documentation: describe existing optional rejection reason/notes and tablet-based Deliveroo synchronization failures; normal missing-PLU handling is unchanged.
Provider/POS configuration metadata: dependsOn and dependsOnAll additionally support explicit isSet/equals conditions; existing boolean-name conditions remain supported. optional fields can be omitted without defaults. Event subscription fields can be conditionally required by their URL. No automatic subscription or definition migration.
POS documentation: expanded webhook setup and optional order-event subscriptions, moved the webhook guide next to Orders, and separated developer test-order and manual channel-sync documentation without changing endpoint behavior.
Admin Site reactivation: safely releases interrupted read-only cleanup checkpoints; provider/payment changes report explicit cleanup errors instead of misleading reload conflicts. Possible partial deletion remains blocked for support review. No automatic restoration or migration. Nightly cleanup compares eligibility marker values independently of DynamoDB field ordering, allowing eligible unblocked runs to proceed; existing blocked checkpoints remain stopped.
Uber Eats orders: aggregated total_fee is displayed as Zusätzliche Gebühren (DE), Additional Fees (EN), or Costi aggiuntivi (IT), using the Site language. Applies to both incoming order formats and newly processed orders only; amounts, taxes, tips and totals are unchanged.
Main SP API: generic providers configure timeChange support per target state via Provider accessConfig.timeChangeStates. Missing/empty disables time changes; the hardcoded allowlist is removed. Existing enabled definitions must be updated before rollout. Dedicated adapters keep their rules; preorders and explicit restrictions take precedence. Target-state semantics also apply to delivered after preparing.
POS webhooks: additive Site/POS/provider routing headers and optional signed authentication for POST /pos/items and PATCH /pos/orders/{id}. Existing standard-webhooks mode and webhookSecret enable these incoming calls too; no additional setting is needed. Existing API-key and outgoing signing behavior remain unchanged. Promote the POS handler before the authorizer; reverse that order for rollback. Documentation includes WebSocket order-event opt-in.
Main SP API: customer.mobilePhone is optional for all order types (inHouse, pickup and delivery). Supplied phone numbers remain strings; no configuration or migration is required.
Foodora customer pickup: pickedUp remains the completion state; inDelivery/delivered are no longer offered or accepted (STATUS_CHANGE_NOT_ALLOWED), including orders with older stored transition lists. No new ready prerequisite, callback change or data migration. Compatibility restriction: notify affected POS partners before rollout. Foodora deliveries and other providers are unchanged.
Uber Eats older V2 orders: nested selected and removed modifiers are now included using the existing V1 flat item/quantity convention. Existing direct items, order/payment totals and acknowledgements remain unchanged; newly visible nested modifiers may need POS mappings. No historical order migration.
Fix: order retention loads correctly in the Lambda/Webpack bundle, restoring affected order writes. Six-month deadlines and cleanup rules are unchanged; no automatic historical backfill is started.
POS orders: optional parentGroupId identifies the immediate Uber Eats modifier group or Wolt POS option group. Existing item IDs, mapping, prices and quantities are unchanged, including Wolt posItemId whitespace. Missing identifiers remain omitted; identifiers are provider/menu-scoped, not globally unique. No configuration or migration required.
Administration: optional emailed initial password setup (48 hours) and public password reset (30 minutes), with one-time restricted access and automatic normal login after saving. Normal password login remains supported. Requires the PasswordAccess table, SES template/sending permissions and Controller integration. Password changes revoke previous User sessions; Site/POS API keys are unchanged.
POS developer test orders: add split-payments, additional-costs, discount and fully populated self-delivery examples. Existing samples stay unchanged; self-delivery can trigger configured fleet automation after acceptance and requires the same explicit frontend risk confirmation.
POS API: optional one-shot order-event webhooks and per-connection WebSocket subscriptions for status, platform courier, fleet and terminal POS injection failures. No retries or guaranteed delivery; old sockets and order delivery stay unchanged. Requires POS definition/configuration updates. Internal terminal-failure notifications reuse the existing internal notification receiver. Optional courierInfo separates pickup ETA from customer delivery time; Wolt pickup ETA no longer overwrites deliveryInfo.deliveryTime.
POS API: GET /pos/restaurant adds credential-free providerDetails summaries with provider and activation IDs, stored names and existing pending/verified connection status. Reads do not trigger verification; existing response fields and configuration writes are unchanged.
Main SP order ingress: optional payments array accepts split payments using the existing payment entry structure. A nonempty array wins; missing/null/empty falls back to deprecated payment. Each array amount is used independently without changing the order total; legacy single-payment amount behavior is preserved. Receipt and cash-tender metadata follow the selected payments. Native provider adapters and Site billing are unchanged.
Order retention: StandardOrders, their line items, raw provider orders and order-owned delivery jobs expire after six calendar months. Cleanup is asynchronous and sends no provider/POS cancellation. Old order retrieval, raw callback lookup and duplicate detection are no longer guaranteed beyond retention. Shared mappings and catalogs remain; delivery offers retain their short expiry. Requires native table TTL and a separately approved metadata backfill for existing records; older pinned writers do not assign the new deadlines.
Wolt Drive scheduled bookings repeat the quoted delivery timestamp in the delivery request. ASAP booking behavior is unchanged; no configuration or data migration is required.
POS order discounts: optional merchant campaign externalId and possibly incomplete position allocations (internalId, discounted quantity and total position discount). Existing amounts, payments and discount rows are unchanged; ambiguous details are omitted. Supported data varies by provider and API format. Main SP order ingress accepts the optional external campaign ID. No migration required.
Additive configuration release and Controller integration fix; production promotion is tracked separately.
Controller integration: siteUpdate notifications after Site PATCH, payment PATCH and Wolt authorization now carry the complete saved Site snapshot in data.after, subject to the existing Controller filtering, rather than only changed fields. Payment API responses remain reduced; database writes still update only their owned fields. No data migration or API-path change.
Uber Eats configuration: optional per-activation allowSpecialInstructions (default false) controls the provider special-instruction request setting at activation and on configuration changes. Incoming instructions and item-level menu settings are unchanged. Add the field to the stored Provider definition manually; failed external updates return the existing post-save provider warning.
Prepared release snapshot; production promotion is tracked separately. Includes the 4.3.1 maintenance fixes below.
Internal Admin API: optional Dealer userSpecs.manageSameLevelRole (default false) delegates management of sibling Dealers, their POS children and Sites under the same parent. New Dealer creation uses the shared parent; only superior management can grant/revoke delegation. Parent-user and cross-hierarchy management remain excluded. Existing onlyOwn/shared-Site rights and authorized impersonation responses remain unchanged; impersonation inherits target permissions. No data migration or POS/order-flow changes.
User-management hardening: Site WebSocket contexts cannot act as User logins, even with matching email metadata. User scopes and existing hierarchy checks remain required; authorized User responses and internal self-registration stay compatible. Authorization diagnostics use credential/user fingerprints, safe concrete IDs, operation/method and rejection reason without raw tokens or email addresses.
Site WebSockets: saving a disabled Site revokes ordinary POS connections, preserving the Controller exception. API-key changes revoke old-key connections including Controllers. Reconnect and every business message check the freshly loaded Site and current key, including expiry for ordinary POS connections; rejected authentication returns 401. Existing message formats and independent user-role behavior remain unchanged.
Internal user management: explicit editable fields, parent scope/role/cycle validation, admin-only licensing and preserved SDK inheritance. Profile/password/company updates remain available to self and authorized management; self privilege expansion and self activation changes are rejected. Technical/unknown fields are ignored. Concurrent target changes return 409 and require reload. Self onboarding cannot choose parent, expanded access or licensing. Independent POS WebSocket connections remain unchanged.
Breaking internal Admin API cleanup: removed legacy Dealer REST/WebSocket operations and the obsolete importV3Sites/migrateSiteUserDetails commands. Dealer/dealeradmin user roles and parent-based permissions remain. dealerId is retired from User/Site inputs and schemas; existing stored attributes are not migrated or deleted. New-Site internal notifications identify the owner, direct parent and creator instead. Dealer tables remain retained infrastructure pending separately authorized cleanup.
Internal administration: strengthen Site ownership and inherited read-only checks. User PATCH accepts an omitted role without changing it and ignores echoed server-managed token fields; invalid bodies/roles return 400. No credential rotation or hierarchy migration.
JET Connect: percentage-discount and free-item promotion names follow Site standardLanguage (German, English, Italian), retaining product names and amounts. Applies to newly processed orders without additional database reads.
Wolt Drive cash collection and recipient delivery-fee share now require a positive outstanding CASH payment. Fully prepaid/zero-cash orders omit cash in quotes and bookings. Existing cash quotes for these orders must be requested again.
Wolt Drive: safe request diagnostics identify provider HTTP errors, known error codes, validation fields and cash quote calculation step. Existing error envelope and retry/booking behavior remain unchanged; no configuration migration.
Provider cancellations: document existing terminal canceled output consistently for REST orders, active POS webhooks and WebSocket notifications. It does not require POS acknowledgement or create new polling work; canceledByProvider retains its actionable meaning. Direct cancellations clear hasWork only after a bounded consistent check with concurrent-work guards. Repeated terminal cancellations remain canceled. Internal work revisions require coordinated handler promotion; no manual Site migration.
Foodora: four-/five-digit postcodes with locality suffixes normalize to zip plus city (e.g. Salzburg (Aigen)), preserving address information without duplicating the city. Blank postcode uses deliveryAreaPostcode as fallback; unknown formats and comments remain unchanged. No configuration or stored-order migration required.
JET Connect: star/whitespace-only last names normalize to null. Masked-only names are excluded from the formatted address; the required firstName value and real/partially masked names are preserved. Existing orders are not rewritten.
Lieferando and JET Connect: labelled address supplements populate floor, apartment and entrance regardless of label case or whitespace. Compatibility change for JET: successfully assigned unambiguous address labels are removed from comment (null when empty); POS clients must display floor, apt and entrance. Unassigned text, the full formatted address and notes remain intact. Lieferando retains its original comment. No stored orders are rewritten.
Channel configuration: concurrent removal or switch-off cannot be undone by a late channel setup; configuration writes check the current activation and preserve unrelated Site fields.
JET Connect mapping catalogs: explicit and initial imports use the public Lieferando menu via shopUrl, scoped to the JET activation. Imports update catalog information without replacing assigned POS targets; they do not reconcile menu identifiers with supplied order PLUs.
Speedy / JET activation: one-time transfer of existing Lieferando POS mapping targets, copied in resumable conditional batches before activating the new connection. Existing JET connections and Speedy receipt behavior remain unchanged. Ambiguous legacy ownership or conflicting targets block activation; bounded catalog reads and copy deadlines require separate handling for larger catalogs. No new provider definition setting required.
Internal Admin API: targeted provider/add and provider/remove operations preserve other activations. Shared Site PATCH commits Site, Restaurant mappings and removed channels atomically; concurrent changes return a conflict. External disconnection is best effort with explicit warnings. Repeated removal is a no-op; uncertain adds must be checked before retrying. No automatic migration.
Internal Admin API: reduced Site payment list/detail and field-scoped PATCH for commercials, enabled and expirationDate. Admin may write all three payment fields on either Site PATCH; dealer/dealeradmin only enabled; POS none. Role-excluded fields are silently ignored. Site write permission remains required. Admin full-object saves can still overwrite payments. Omitted existing ownership is preserved. No migration required.
Wolt Drive: optional localized customer SMS and dependent handshake PIN, driver-visible orderReference, and scheduled preorder quotes using the customer delivery time. Stored fleet definitions require optional sms/handshakePin metadata. POS createTestOrder adds fleet-preorder (four hours ahead) and delivery instructions. Main SP address.comment now takes precedence over the legacy formatted-address comment fallback.
Foodora Logistics Delivery: dynamic preparation-time adjustment on existing acceptedByPOS/preparing/ready transitions when supplied by the provider. Successful state changes can return an optional time-change warning; rejected adjustments preserve the previous ETA and record the attempt. Rider waiting events use provider-neutral platformUpdates fields. Incoming delivery times no longer require an address; missing delivery time can use pickup plus configured drivingTime. No new POS endpoint or same-state updates. The SetOrderState success text typo is corrected to successful; clients should use HTTP status, not exact message matching.
Fleet definition metadata documents optional min/max/unit for numeric configuration inputs. The Wolt recipientDeliveryFeePercent template supplies 0–100 and %. Add these descriptors to existing stored definitions manually; runtime validation remains unchanged.
Neutral delivery fleets: optional signed quote/confirmed-booking workflow selected by activation bookingMode (default direct). parcelCount is optional; dispatches include main items and outstanding CASH collection details. Quotes are bound to delivery data and expire via TTL. Automatic quote bookings require maxPrice; direct automation retains explicit unpriced consent. Enable quotes in the stored definition only when its webhook implements the contract. Existing activations and delivery identities remain unchanged.
POS createTestOrder: fleet-cash and fleet-cash-insufficient samples exercise cashToExpect and Wolt cash collection. Existing prepaid samples remain unchanged. These persisted merchant-delivery orders can trigger configured automation on acceptance; use a sandbox fleet.
Wolt Drive: opt-in cash collection per Site fleet activation with recipientDeliveryFeePercent (0–100). Only outstanding CASH payments plus the recipient delivery-fee share are collected; existing payments remain unchanged. Quotes and deliveries expose cashCollection. Add the two configuration descriptors to the stored Wolt fleet definition manually and confirm Wolt cash contract support. Default remains prepaid-only.
POS/Main SP orders: optional paymentInfo.cashToExpect preserves explicitly announced cash tender from Lieferando POS API, Wolt and Main SP payment.cashToExpect in cents and currency. Existing payment amounts, totals and notes are unchanged; no migration or configuration required.
Wolt Drive: derive parcels from main order items and their quantities, names and available unit prices; omit bag_count. Wolt Drive no longer requires parcelCount and ignores it when supplied; neutral webhook fleets accept it optionally. Item changes invalidate quotes; quotes obtained before this change must be refreshed. Existing deliveries and prepaid-only behavior remain unchanged.
Prepared maintenance release; deployment and production promotion are tracked separately.
Prepared release snapshot; production promotion is tracked separately.
acceptedByPOS, with provider/instance filters, Wolt price limits, pickup-time rules and parcel-count policies. Neutral automatic booking requires explicit consent to unpriced dispatch.deliveryAutomation order status/history for queued work and cases requiring attention. Delivery state remains separate from order state.Neutral fleet callbacks default to https://ordering.mergeport.com/v4 when the callback-base environment variable is missing or empty; Beta requires an explicit override. Dev remains separately configured. Existing delivery callback snapshots and Wolt webhook registration are unchanged.
Neutral fleets accept readySoon for booking and retry. Automatic delivery observation continues when automatic cancellation is disabled, without resending bookings. Single-item reads preserve optional taxRate, including zero.
Lieferando pin_at_doorstep is normalized as a card payment, preserving the provider method as its brand and the incoming paid status. Unsupported payment methods now fail transformation instead of producing an invalid paymentInfo value.
Fleet APIs are exposed through the POS API; their appearance in this shared history does not add fleet booking operations to the ordering-provider API. Existing integrations remain manual unless automation is explicitly configured. Preserve activation IDs and revision-based configuration updates. An existing delivery reservation, including an uncertain booking outcome, must not trigger a second booking.
Setup requires fleet definitions, Site activation credentials and the relevant callback configuration. Automation additionally requires the StandardOrder queue index and scheduled worker; retaining database tables alone does not keep automation running when deploying older code. No automatic definition import or existing-Site migration is performed.
POS mapping catalog now always reads stored activation-scoped ProviderMappingItems, with Site-wide, provider and activation filters, consistent activeOnly and full filtered counts. Legacy rows are no longer read or migrated by catalog requests; restart old cursors. GET /pos/mappings behavior is unchanged but its documentation is internal-only; POST remains public.
JET Connect: identical item rows now combine into one position with summed quantity. Complete item content, including modifiers and notes, must match; regular and promotional items remain separate. POS clients may receive fewer positions with larger quantities; amounts and article IDs are unchanged. Existing orders are not rewritten.
JET Connect: address fields containing only asterisks or whitespace are treated as unavailable in newly normalized orders, including formatted addresses. Real and partially masked content is preserved.
Provider verification: compact internal state after confirmation; diagnostic details are logged instead of retained per target. Success-webhook entries are removed on delivery or final failure, with exhausted failures logged. Existing verbose records are cleaned gradually; public pending/verified status, retry timing and configuration-change verification remain unchanged.
JET Connect display-name fallback: missing/blank or technical JET Connect channel names no longer replace the legacy Lieferando name. A recognized shop URL or concrete channel takes precedence over country (DE/AT: Lieferando; NL: thuisbezorgd). Existing stored orders and item mappings remain unchanged.
JET Connect payment compatibility: paymentType/brand now match legacy Lieferando (CARD/credit, CASH/cashier, doorstep CARD/pin_at_doorstep). Existing paid status and amounts remain unchanged. Original payment_method/tender_type are retained in additionalInternalInfo as jetConnectPayment JSON. Clients matching the former composite JET brand must adapt.
Disabled Sites: server-managed disabledSince tracks continuous deactivation (unknown legacy dates start at first observation). From 72 hours until before 144 hours, one-time bounded maintenance marks pending orders timedOut locally and clears hasWork after a completed scan; only unfinished work retries within this window, without provider/POS/fleet notifications. Reactivation resets the period. After twelve months of continuous deactivation, bounded nightly maintenance permanently removes owned data and the Site; an explicitly reviewed historical cohort has a one-time eligibility exception. No external cancellation is sent. Disabled/expired POS authorization now stops before activity writes. The existing Controller exception is unchanged.
WIX: optional per-activation splitGroupedModifiers expands clear grouped xN option descriptions into individually mappable toppings. Default off; normal modifiers, prices and totals remain unchanged. New stable group/name IDs do not inherit old grouped mappings. Add the optional field to the stored WIX definition before configuring the Site.
Neutral delivery fleets can report optional WGS84 courier positions independently of status updates. The latest position is exposed to the POS and removed at delivery completion; Wolt Drive remains unchanged.
Legacy Lieferando courier deliveries no longer offer POS time changes. Confirmations retain the original provider timestamp instead of applying a new ETA; JET Connect is unchanged.
POS and Main SP item APIs: options is deprecated in favor of optionsList. Empty/missing lists fall back to legacy options without removing the old field; populated lists win. POST normalizes submitted data; PATCH preserves existing lists and requires clearing both fields to remove all groups. Item outputs, update webhooks and menu channels use the same selection. Foodora development-channel fix: addPrice is relative to the modifier base price, not an absolute price; recheck/resync existing test menus.
Active POS connections: optional disableAutoRejection (default false) removes exhausted injection retries without changing order status or notifying the provider. Retry timing/counts are unchanged. Separate expiry/cancellation flows and other POS connections remain independent; stored POS definitions need the optional setting metadata.
POS catalog: PATCH /pos/items updates only explicitly supplied fields of existing items, with per-item bulk results and complete stored items for synchronization. POST remains replacement/upsert. Nested objects replace the field; nullable null and empty values have explicit clearing semantics. No migration or provider configuration change required.
POS order-state errors: additive machine-readable origin/type and actual upstream HTTP status, preserving existing messages, HTTP codes and receipt validation shapes. No new receipt requirement. Before JET production rollout, its HTTP 410 expiry error now uses error.message instead of a bare error string (same text and status).
Lieferando POS API: pizza-half labels supplied as side-dish IDs are preserved in order-item names. Existing mapping IDs, prices and quantities are unchanged.
POS catalog: optional numeric taxRate (0–100 percent, including zero) in item uploads, individual updates and responses. Optional menu-channel mappings for Wolt, JET, Uber Eats and Deliveroo; existing saved channels require enabling the new field link. Gross prices are unchanged; no default tax rate is inferred.
POS API: createTestOrder creates pickup, on-premises, delivery and fleet samples via the normal order pipeline. Requires a configured Development provider on the authenticated test Site. Fleet samples distinguish automation eligibility; acceptance can trigger paid deliveries. No automatic acceptance.
Main SP: optional deliveryInfo.selfDelivery now preserves explicit delivery ownership in normalized orders, including fleet test orders. Missing values retain the vendorDelivery fallback; explicit false is not overridden.
Documentation: restored Main SP order cancellation under Orders and added the neutral delivery-fleet dispatch/signature/status-callback contract to the provider documentation; no runtime behavior change.
Beta clients: fleet definitions require an existing Site and its API key via GET /pos/delivery-fleet-definitions. The redundant GET /admin/delivery-fleets endpoint has been removed; admin login tokens are not accepted by the POS endpoint.
JET Connect preserves the legacy Lieferando display-name spelling for the matching shop platform. Optional deliveryInfo.phonePin/pickupInfo.phonePin expose masked-phone codes; localized PIN notes preserve compatibility with existing POS clients.
Provider-login success events include the Site standardLanguage when present, frozen across delivery retries.
Baseline before the delivery-fleet release. Earlier changes were not recorded systematically under distinct product versions; no retrospective release dates or complete change lists are asserted here.
Ordering operations allow the POS to synchronize orders and articles with ordering platforms. Ordering platforms include delivery services, Dine-In/Dine-Out apps & websites, table ordering services and discovery pages as well as websites. The Ordering API enables connected services to query the articles and menu items of the connected POS system and inject orders into the POS. As a feedback, the platforms receive status updates and preparation time changes.
Typically, the workflow is as following:
WebSocket action: GetOrders
This endpoint returns all orders for the requesting site with the possibility to filter by state, date and pagination-block. As part of the POS integration, this endpoint should only be included with the active filter to gather new orders.
Reminder:
Websocket: data: {filter: 'active'}
REST: ?filter=active
Without a filter, the response will be paginated with the "startKey" if the return value is too large. To fetch the complete data, please iterate this request with the updated startKey until it is null again.
| filter | string Value: "active" filter to provide a subset of the orders ( example: active) |
| dateFrom | string <date-time> date to start with the subset of the orders |
| dateTo | string <date-time> date to end with the subset of the orders |
| startKey | string <uuid> id to continue with the subset of the orders |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "orders": [
- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "restaurantId": "string",
- "providerName": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "string",
- "orderReference": "string",
- "creationDate": "2019-08-24T14:15:22Z",
- "lastModifyDate": "2019-08-24T14:15:22Z",
- "expiryDate": "2019-08-24T14:15:22Z",
- "status": "receivedByProvider",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "paymentInfo": [
- {
- "cashToExpect": {
- "amount": 0,
- "currency": "string"
}, - "referenceId": "string",
- "amount": {
- "amount": 0,
- "currency": "string"
}, - "multipleOrderPayment": true,
- "brand": "string",
- "paymentType": "CASH",
- "payOnDelivery": true
}
], - "receiptInfo": [
- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "pickupNumber": "1-2345",
- "creationDate": "2019-08-24T14:15:22Z",
- "data": {
- "cashRegisterId": "POS12345",
- "signatureValue": "_R1-AT1_POS12345_R1234567_2022-01-06T14:56:00_3,30_8,80_0,00_0,00_0,00_ZMBRGX0=_2CBFF973_sE/BuW3BYUk=_03AVHF9FDN884X63kGWNEkbNm9raufVc7DMZr3JmaOEnHEC7z7lj2dkJDGy6jKkhKwgN6JTCldBRxAPZ3aUENQ==",
- "vatId": "ATU12345678",
- "number": "R1234567",
- "type": "Rechnung",
- "header": [
- "YX Gastro Gmbh",
- "1010 Wien, Am Hof 3",
- "Phone 1233456789"
]
}, - "items": [
- {
- "quantity": "2",
- "name": "Minestrone",
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}, - "taxId": "B",
- "sortIndex": "1"
}
], - "taxes": [
- {
- "id": "B",
- "name": "20 % Ust.",
- "rate": "20",
- "netAmount": {
- "amount": "275",
- "currency": "EUR"
}, - "taxAmount": {
- "amount": "55",
- "currency": "EUR"
}, - "grossAmount": {
- "amount": "330",
- "currency": "EUR"
}
}
], - "totalAmount": {
- "amount": "1210",
- "currency": "EUR"
}
}
], - "requireReceipt": true,
- "deliveryInfo": {
- "deliveryTime": "2019-08-24T14:15:22Z",
- "formatted": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "title": "string",
- "salutation": "string",
- "street": "string",
- "number": "string",
- "apt": "string",
- "floor": "string",
- "entrance": "string",
- "comment": "string",
- "city": "string",
- "zip": "string",
- "country": "string",
- "company": "string",
- "destinationLongitude": "string",
- "destinationLatitude": "string",
- "driverLongitude": "string",
- "driverLatitude": "string",
- "selfDelivery": true
}, - "pickupInfo": {
- "pickupTime": "2019-08-24T14:15:22Z",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "comment": "string"
}, - "inHouseOrderingInfo": {
- "inHouseOrderingTime": "2019-08-24T14:15:22Z",
- "tableId": "string",
- "tableDescription": "string",
- "serviceAreaId": "string",
- "serviceAreaDescription": "string",
- "roomId": "string",
- "roomDescription": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phone": "string",
- "email": "string"
}, - "notes": "string",
- "discounts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "externalId": "string",
- "orderItems": [
- {
- "internalId": "string",
- "quantity": 0,
- "value": {
- "amount": 0,
- "currency": "string"
}
}
]
}
], - "amountToPay": {
- "amount": 0,
- "currency": "string"
}, - "additionalCosts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "tip": true,
- "taxRate": 0
}
], - "items": [
- {
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "internalId": "6868d0ce-34a2-4e78-b137-31229ba3e81a",
- "orderItemId": "string",
- "orderItemName": "string",
- "menuId": "string",
- "parentId": "70850378-7d3c-4f45-91b7-942d4dfbbd43",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "quantity": 0,
- "relativeQuantity": 0,
- "singlePrice": {
- "amount": 0,
- "currency": "string"
}, - "rowTotal": {
- "amount": 0,
- "currency": "string"
}, - "sortIndex": 0,
- "relativeRowTotal": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabels": "string",
- "providerItemId": "string",
- "isNote": true,
- "course": 0,
- "deposit": 0,
- "taxRate": 0,
- "parentGroupId": "dein_extra_dip"
}
], - "possibleActions": [
- "ready",
- "pickedUp",
- "inDelivery",
- "delivered"
], - "possibleStateChanges": [
- {
- "state": "ready",
- "timeChange": true
}, - {
- "state": "pickedUp",
- "timeChange": false
}, - {
- "state": "inDelivery",
- "timeChange": false
}, - {
- "state": "delivered",
- "timeChange": false
}
], - "preOrder": true,
- "platformUpdates": [
- {
- "status": "string",
- "updatedAt": "string",
- "data": {
- "driverName": "string",
- "driverTripId": "string",
- "deliveryTime": "string",
- "pickupTime": "string",
- "driverStatus": "string",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
], - "deposit": 0,
- "additionalInfo": {
- "containsSingleUseItems": true,
- "containsAlcoholicItems": true,
- "containsTobacco": true
}, - "courierInfo": {
- "status": "scheduled",
- "estimatedArrivalAtPickup": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
], - "startKey": "f2c499b1-ac1a-481d-98e2-77b3a197a97a"
}WebSocket action: GetOrdersOld
Caution: As default the Websocket action will get all orders to get only the recently changed and new ones specify an active filter:
data: {filter: 'active'}
| filter | string Value: "active" filter to provide a subset of the orders ( example: active) |
| dateFrom | string <date-time> date to start with the subset of the orders |
| dateTo | string <date-time> date to end with the subset of the orders |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
[- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "restaurantId": "string",
- "providerName": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "string",
- "orderReference": "string",
- "creationDate": "2019-08-24T14:15:22Z",
- "lastModifyDate": "2019-08-24T14:15:22Z",
- "expiryDate": "2019-08-24T14:15:22Z",
- "status": "receivedByProvider",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "paymentInfo": [
- {
- "cashToExpect": {
- "amount": 0,
- "currency": "string"
}, - "referenceId": "string",
- "amount": {
- "amount": 0,
- "currency": "string"
}, - "multipleOrderPayment": true,
- "brand": "string",
- "paymentType": "CASH",
- "payOnDelivery": true
}
], - "receiptInfo": [
- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "pickupNumber": "1-2345",
- "creationDate": "2019-08-24T14:15:22Z",
- "data": {
- "cashRegisterId": "POS12345",
- "signatureValue": "_R1-AT1_POS12345_R1234567_2022-01-06T14:56:00_3,30_8,80_0,00_0,00_0,00_ZMBRGX0=_2CBFF973_sE/BuW3BYUk=_03AVHF9FDN884X63kGWNEkbNm9raufVc7DMZr3JmaOEnHEC7z7lj2dkJDGy6jKkhKwgN6JTCldBRxAPZ3aUENQ==",
- "vatId": "ATU12345678",
- "number": "R1234567",
- "type": "Rechnung",
- "header": [
- "YX Gastro Gmbh",
- "1010 Wien, Am Hof 3",
- "Phone 1233456789"
]
}, - "items": [
- {
- "quantity": "2",
- "name": "Minestrone",
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}, - "taxId": "B",
- "sortIndex": "1"
}
], - "taxes": [
- {
- "id": "B",
- "name": "20 % Ust.",
- "rate": "20",
- "netAmount": {
- "amount": "275",
- "currency": "EUR"
}, - "taxAmount": {
- "amount": "55",
- "currency": "EUR"
}, - "grossAmount": {
- "amount": "330",
- "currency": "EUR"
}
}
], - "totalAmount": {
- "amount": "1210",
- "currency": "EUR"
}
}
], - "requireReceipt": true,
- "deliveryInfo": {
- "deliveryTime": "2019-08-24T14:15:22Z",
- "formatted": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "title": "string",
- "salutation": "string",
- "street": "string",
- "number": "string",
- "apt": "string",
- "floor": "string",
- "entrance": "string",
- "comment": "string",
- "city": "string",
- "zip": "string",
- "country": "string",
- "company": "string",
- "destinationLongitude": "string",
- "destinationLatitude": "string",
- "driverLongitude": "string",
- "driverLatitude": "string",
- "selfDelivery": true
}, - "pickupInfo": {
- "pickupTime": "2019-08-24T14:15:22Z",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "comment": "string"
}, - "inHouseOrderingInfo": {
- "inHouseOrderingTime": "2019-08-24T14:15:22Z",
- "tableId": "string",
- "tableDescription": "string",
- "serviceAreaId": "string",
- "serviceAreaDescription": "string",
- "roomId": "string",
- "roomDescription": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phone": "string",
- "email": "string"
}, - "notes": "string",
- "discounts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "externalId": "string",
- "orderItems": [
- {
- "internalId": "string",
- "quantity": 0,
- "value": {
- "amount": 0,
- "currency": "string"
}
}
]
}
], - "amountToPay": {
- "amount": 0,
- "currency": "string"
}, - "additionalCosts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "tip": true,
- "taxRate": 0
}
], - "items": [
- {
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "internalId": "6868d0ce-34a2-4e78-b137-31229ba3e81a",
- "orderItemId": "string",
- "orderItemName": "string",
- "menuId": "string",
- "parentId": "70850378-7d3c-4f45-91b7-942d4dfbbd43",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "quantity": 0,
- "relativeQuantity": 0,
- "singlePrice": {
- "amount": 0,
- "currency": "string"
}, - "rowTotal": {
- "amount": 0,
- "currency": "string"
}, - "sortIndex": 0,
- "relativeRowTotal": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabels": "string",
- "providerItemId": "string",
- "isNote": true,
- "course": 0,
- "deposit": 0,
- "taxRate": 0,
- "parentGroupId": "dein_extra_dip"
}
], - "possibleActions": [
- "ready",
- "pickedUp",
- "inDelivery",
- "delivered"
], - "possibleStateChanges": [
- {
- "state": "ready",
- "timeChange": true
}, - {
- "state": "pickedUp",
- "timeChange": false
}, - {
- "state": "inDelivery",
- "timeChange": false
}, - {
- "state": "delivered",
- "timeChange": false
}
], - "preOrder": true,
- "platformUpdates": [
- {
- "status": "string",
- "updatedAt": "string",
- "data": {
- "driverName": "string",
- "driverTripId": "string",
- "deliveryTime": "string",
- "pickupTime": "string",
- "driverStatus": "string",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
], - "deposit": 0,
- "additionalInfo": {
- "containsSingleUseItems": true,
- "containsAlcoholicItems": true,
- "containsTobacco": true
}, - "courierInfo": {
- "status": "scheduled",
- "estimatedArrivalAtPickup": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
]WebSocket action: GetOrders
Caution: As default the Websocket action will get all orders to get only the recently changed and new ones specify an active filter:
data: {filter: 'active'}
| Authorization required | string <uuid> static apiKey provided by Mergeport |
[- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "restaurantId": "string",
- "providerName": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "string",
- "orderReference": "string",
- "creationDate": "2019-08-24T14:15:22Z",
- "lastModifyDate": "2019-08-24T14:15:22Z",
- "expiryDate": "2019-08-24T14:15:22Z",
- "status": "receivedByProvider",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "paymentInfo": [
- {
- "cashToExpect": {
- "amount": 0,
- "currency": "string"
}, - "referenceId": "string",
- "amount": {
- "amount": 0,
- "currency": "string"
}, - "multipleOrderPayment": true,
- "brand": "string",
- "paymentType": "CASH",
- "payOnDelivery": true
}
], - "receiptInfo": [
- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "pickupNumber": "1-2345",
- "creationDate": "2019-08-24T14:15:22Z",
- "data": {
- "cashRegisterId": "POS12345",
- "signatureValue": "_R1-AT1_POS12345_R1234567_2022-01-06T14:56:00_3,30_8,80_0,00_0,00_0,00_ZMBRGX0=_2CBFF973_sE/BuW3BYUk=_03AVHF9FDN884X63kGWNEkbNm9raufVc7DMZr3JmaOEnHEC7z7lj2dkJDGy6jKkhKwgN6JTCldBRxAPZ3aUENQ==",
- "vatId": "ATU12345678",
- "number": "R1234567",
- "type": "Rechnung",
- "header": [
- "YX Gastro Gmbh",
- "1010 Wien, Am Hof 3",
- "Phone 1233456789"
]
}, - "items": [
- {
- "quantity": "2",
- "name": "Minestrone",
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}, - "taxId": "B",
- "sortIndex": "1"
}
], - "taxes": [
- {
- "id": "B",
- "name": "20 % Ust.",
- "rate": "20",
- "netAmount": {
- "amount": "275",
- "currency": "EUR"
}, - "taxAmount": {
- "amount": "55",
- "currency": "EUR"
}, - "grossAmount": {
- "amount": "330",
- "currency": "EUR"
}
}
], - "totalAmount": {
- "amount": "1210",
- "currency": "EUR"
}
}
], - "requireReceipt": true,
- "deliveryInfo": {
- "deliveryTime": "2019-08-24T14:15:22Z",
- "formatted": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "title": "string",
- "salutation": "string",
- "street": "string",
- "number": "string",
- "apt": "string",
- "floor": "string",
- "entrance": "string",
- "comment": "string",
- "city": "string",
- "zip": "string",
- "country": "string",
- "company": "string",
- "destinationLongitude": "string",
- "destinationLatitude": "string",
- "driverLongitude": "string",
- "driverLatitude": "string",
- "selfDelivery": true
}, - "pickupInfo": {
- "pickupTime": "2019-08-24T14:15:22Z",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "comment": "string"
}, - "inHouseOrderingInfo": {
- "inHouseOrderingTime": "2019-08-24T14:15:22Z",
- "tableId": "string",
- "tableDescription": "string",
- "serviceAreaId": "string",
- "serviceAreaDescription": "string",
- "roomId": "string",
- "roomDescription": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phone": "string",
- "email": "string"
}, - "notes": "string",
- "discounts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "externalId": "string",
- "orderItems": [
- {
- "internalId": "string",
- "quantity": 0,
- "value": {
- "amount": 0,
- "currency": "string"
}
}
]
}
], - "amountToPay": {
- "amount": 0,
- "currency": "string"
}, - "additionalCosts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "tip": true,
- "taxRate": 0
}
], - "items": [
- {
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "internalId": "6868d0ce-34a2-4e78-b137-31229ba3e81a",
- "orderItemId": "string",
- "orderItemName": "string",
- "menuId": "string",
- "parentId": "70850378-7d3c-4f45-91b7-942d4dfbbd43",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "quantity": 0,
- "relativeQuantity": 0,
- "singlePrice": {
- "amount": 0,
- "currency": "string"
}, - "rowTotal": {
- "amount": 0,
- "currency": "string"
}, - "sortIndex": 0,
- "relativeRowTotal": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabels": "string",
- "providerItemId": "string",
- "isNote": true,
- "course": 0,
- "deposit": 0,
- "taxRate": 0,
- "parentGroupId": "dein_extra_dip"
}
], - "possibleActions": [
- "ready",
- "pickedUp",
- "inDelivery",
- "delivered"
], - "possibleStateChanges": [
- {
- "state": "ready",
- "timeChange": true
}, - {
- "state": "pickedUp",
- "timeChange": false
}, - {
- "state": "inDelivery",
- "timeChange": false
}, - {
- "state": "delivered",
- "timeChange": false
}
], - "preOrder": true,
- "platformUpdates": [
- {
- "status": "string",
- "updatedAt": "string",
- "data": {
- "driverName": "string",
- "driverTripId": "string",
- "deliveryTime": "string",
- "pickupTime": "string",
- "driverStatus": "string",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
], - "deposit": 0,
- "additionalInfo": {
- "containsSingleUseItems": true,
- "containsAlcoholicItems": true,
- "containsTobacco": true
}, - "courierInfo": {
- "status": "scheduled",
- "estimatedArrivalAtPickup": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
]WebSocket action: GetOrder
| id required | string <uuid> internal ID of the order |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "restaurantId": "string",
- "providerName": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "string",
- "orderReference": "string",
- "creationDate": "2019-08-24T14:15:22Z",
- "lastModifyDate": "2019-08-24T14:15:22Z",
- "expiryDate": "2019-08-24T14:15:22Z",
- "status": "receivedByProvider",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "paymentInfo": [
- {
- "cashToExpect": {
- "amount": 0,
- "currency": "string"
}, - "referenceId": "string",
- "amount": {
- "amount": 0,
- "currency": "string"
}, - "multipleOrderPayment": true,
- "brand": "string",
- "paymentType": "CASH",
- "payOnDelivery": true
}
], - "receiptInfo": [
- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "pickupNumber": "1-2345",
- "creationDate": "2019-08-24T14:15:22Z",
- "data": {
- "cashRegisterId": "POS12345",
- "signatureValue": "_R1-AT1_POS12345_R1234567_2022-01-06T14:56:00_3,30_8,80_0,00_0,00_0,00_ZMBRGX0=_2CBFF973_sE/BuW3BYUk=_03AVHF9FDN884X63kGWNEkbNm9raufVc7DMZr3JmaOEnHEC7z7lj2dkJDGy6jKkhKwgN6JTCldBRxAPZ3aUENQ==",
- "vatId": "ATU12345678",
- "number": "R1234567",
- "type": "Rechnung",
- "header": [
- "YX Gastro Gmbh",
- "1010 Wien, Am Hof 3",
- "Phone 1233456789"
]
}, - "items": [
- {
- "quantity": "2",
- "name": "Minestrone",
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}, - "taxId": "B",
- "sortIndex": "1"
}
], - "taxes": [
- {
- "id": "B",
- "name": "20 % Ust.",
- "rate": "20",
- "netAmount": {
- "amount": "275",
- "currency": "EUR"
}, - "taxAmount": {
- "amount": "55",
- "currency": "EUR"
}, - "grossAmount": {
- "amount": "330",
- "currency": "EUR"
}
}
], - "totalAmount": {
- "amount": "1210",
- "currency": "EUR"
}
}
], - "requireReceipt": true,
- "deliveryInfo": {
- "deliveryTime": "2019-08-24T14:15:22Z",
- "formatted": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "title": "string",
- "salutation": "string",
- "street": "string",
- "number": "string",
- "apt": "string",
- "floor": "string",
- "entrance": "string",
- "comment": "string",
- "city": "string",
- "zip": "string",
- "country": "string",
- "company": "string",
- "destinationLongitude": "string",
- "destinationLatitude": "string",
- "driverLongitude": "string",
- "driverLatitude": "string",
- "selfDelivery": true
}, - "pickupInfo": {
- "pickupTime": "2019-08-24T14:15:22Z",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "comment": "string"
}, - "inHouseOrderingInfo": {
- "inHouseOrderingTime": "2019-08-24T14:15:22Z",
- "tableId": "string",
- "tableDescription": "string",
- "serviceAreaId": "string",
- "serviceAreaDescription": "string",
- "roomId": "string",
- "roomDescription": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phone": "string",
- "email": "string"
}, - "notes": "string",
- "discounts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "externalId": "string",
- "orderItems": [
- {
- "internalId": "string",
- "quantity": 0,
- "value": {
- "amount": 0,
- "currency": "string"
}
}
]
}
], - "amountToPay": {
- "amount": 0,
- "currency": "string"
}, - "additionalCosts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "tip": true,
- "taxRate": 0
}
], - "items": [
- {
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "internalId": "6868d0ce-34a2-4e78-b137-31229ba3e81a",
- "orderItemId": "string",
- "orderItemName": "string",
- "menuId": "string",
- "parentId": "70850378-7d3c-4f45-91b7-942d4dfbbd43",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "quantity": 0,
- "relativeQuantity": 0,
- "singlePrice": {
- "amount": 0,
- "currency": "string"
}, - "rowTotal": {
- "amount": 0,
- "currency": "string"
}, - "sortIndex": 0,
- "relativeRowTotal": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabels": "string",
- "providerItemId": "string",
- "isNote": true,
- "course": 0,
- "deposit": 0,
- "taxRate": 0,
- "parentGroupId": "dein_extra_dip"
}
], - "possibleActions": [
- "ready",
- "pickedUp",
- "inDelivery",
- "delivered"
], - "possibleStateChanges": [
- {
- "state": "ready",
- "timeChange": true
}, - {
- "state": "pickedUp",
- "timeChange": false
}, - {
- "state": "inDelivery",
- "timeChange": false
}, - {
- "state": "delivered",
- "timeChange": false
}
], - "preOrder": true,
- "platformUpdates": [
- {
- "status": "string",
- "updatedAt": "string",
- "data": {
- "driverName": "string",
- "driverTripId": "string",
- "deliveryTime": "string",
- "pickupTime": "string",
- "driverStatus": "string",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
], - "deposit": 0,
- "additionalInfo": {
- "containsSingleUseItems": true,
- "containsAlcoholicItems": true,
- "containsTobacco": true
}, - "courierInfo": {
- "status": "scheduled",
- "estimatedArrivalAtPickup": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}WebSocket action: SetOrderState
For Deliveroo tablet-less orders, an explicit acceptedByPOS request also succeeds when the provider returns HTTP 400 with the exact message invalid status update: the order is already in status accepted. Other provider failures remain errors. Provider acceptance alone does not set acceptedByPOS.
Normalized errors add optional error.source (provider or mergeport), error.type and actual upstream error.providerStatus. Existing messages and HTTP codes remain unchanged; network failures omit providerStatus. No new receipt requirement is introduced. Legacy receipt validation arrays remain unchanged and use X-Mergeport-Error-Source / X-Mergeport-Error-Type response headers. JET HTTP 410 now uses the common error object (message/source/type) instead of its former error string, before production rollout; the text and HTTP status are unchanged.
| id required | string <uuid> internal ID of the order |
| x-mergeport-site-id | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-pos-id | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-timestamp | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-content-sha256 | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-signature | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| Authorization | string <uuid> Site API key, required unless signed POS authentication is used. See POS webhook integration. |
| state required | string Enum: "receivedByProvider" "fetchedByPOS" "canceledByProvider" "canceledByPOS" "rejectedByPOS" "acceptedByPOS" "preparing" "ready" "pickedUp" "inDelivery" "delivered" Desired "status" of the order. |
| reason | string Optional provider-supported reason for rejection. For tablet-based Deliveroo rejectedByPOS reports failed POS synchronization: use pos_item_id_not_found for an unknown PLU, or pos_item_id_mismatched for a known PLU assigned to the wrong item. Submit before fetchedByPOS/acceptedByPOS has reported sync success. This does not cancel the already accepted tablet-based Deliveroo order. Other providers retain their own reason handling. |
| notes | string Optional explanatory text forwarded where the provider supports it. For a POS synchronization failure, provide a brief technical explanation without customer data or credentials. |
| timeChange | string Nullable Eventual new date-time if there is a change in delivery or pickup time (ISO 8601). In case the platform has not set a pickup or delivery time, also consider sending a timeChange in the "acceptedByPOS" status update to inform the service provider about the expected delivery/pickup time. |
Array of objects Nullable Contains information about the created invoice (by POS) such as signature, item and taxes. Used for service providers to print the receipt for example. Also supports multiple receipts for one order (e.g. split payment) |
{- "state": "receivedByProvider",
- "reason": "string",
- "notes": "string",
- "timeChange": "string",
- "receipts": [
- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "pickupNumber": "1-2345",
- "creationDate": "2019-08-24T14:15:22Z",
- "data": {
- "cashRegisterId": "POS12345",
- "signatureValue": "_R1-AT1_POS12345_R1234567_2022-01-06T14:56:00_3,30_8,80_0,00_0,00_0,00_ZMBRGX0=_2CBFF973_sE/BuW3BYUk=_03AVHF9FDN884X63kGWNEkbNm9raufVc7DMZr3JmaOEnHEC7z7lj2dkJDGy6jKkhKwgN6JTCldBRxAPZ3aUENQ==",
- "vatId": "ATU12345678",
- "number": "R1234567",
- "type": "Rechnung",
- "header": [
- "YX Gastro Gmbh",
- "1010 Wien, Am Hof 3",
- "Phone 1233456789"
]
}, - "items": [
- {
- "quantity": "2",
- "name": "Minestrone",
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}, - "taxId": "B",
- "sortIndex": "1"
}
], - "taxes": [
- {
- "id": "B",
- "name": "20 % Ust.",
- "rate": "20",
- "netAmount": {
- "amount": "275",
- "currency": "EUR"
}, - "taxAmount": {
- "amount": "55",
- "currency": "EUR"
}, - "grossAmount": {
- "amount": "330",
- "currency": "EUR"
}
}
], - "totalAmount": {
- "amount": "1210",
- "currency": "EUR"
}
}
]
}{- "success": "order set status successful",
- "warning": {
- "type": "TIME_CHANGE_NOT_ACCEPTED",
- "source": "provider",
- "message": "string",
- "providerStatus": 0,
- "providerCode": "PREPARATION_TIME_EXCEEDS_ALLOWED_MAX_TIME"
}, - "providerResults": [
- {
- "operation": "statusChange",
- "outcome": "confirmed",
- "providerStatus": 100
}
], - "order": {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "restaurantId": "string",
- "providerName": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "string",
- "orderReference": "string",
- "creationDate": "2019-08-24T14:15:22Z",
- "lastModifyDate": "2019-08-24T14:15:22Z",
- "expiryDate": "2019-08-24T14:15:22Z",
- "status": "receivedByProvider",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "paymentInfo": [
- {
- "cashToExpect": {
- "amount": 0,
- "currency": "string"
}, - "referenceId": "string",
- "amount": {
- "amount": 0,
- "currency": "string"
}, - "multipleOrderPayment": true,
- "brand": "string",
- "paymentType": "CASH",
- "payOnDelivery": true
}
], - "receiptInfo": [
- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "pickupNumber": "1-2345",
- "creationDate": "2019-08-24T14:15:22Z",
- "data": {
- "cashRegisterId": "POS12345",
- "signatureValue": "_R1-AT1_POS12345_R1234567_2022-01-06T14:56:00_3,30_8,80_0,00_0,00_0,00_ZMBRGX0=_2CBFF973_sE/BuW3BYUk=_03AVHF9FDN884X63kGWNEkbNm9raufVc7DMZr3JmaOEnHEC7z7lj2dkJDGy6jKkhKwgN6JTCldBRxAPZ3aUENQ==",
- "vatId": "ATU12345678",
- "number": "R1234567",
- "type": "Rechnung",
- "header": [
- "YX Gastro Gmbh",
- "1010 Wien, Am Hof 3",
- "Phone 1233456789"
]
}, - "items": [
- {
- "quantity": "2",
- "name": "Minestrone",
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}, - "taxId": "B",
- "sortIndex": "1"
}
], - "taxes": [
- {
- "id": "B",
- "name": "20 % Ust.",
- "rate": "20",
- "netAmount": {
- "amount": "275",
- "currency": "EUR"
}, - "taxAmount": {
- "amount": "55",
- "currency": "EUR"
}, - "grossAmount": {
- "amount": "330",
- "currency": "EUR"
}
}
], - "totalAmount": {
- "amount": "1210",
- "currency": "EUR"
}
}
], - "requireReceipt": true,
- "deliveryInfo": {
- "deliveryTime": "2019-08-24T14:15:22Z",
- "formatted": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "title": "string",
- "salutation": "string",
- "street": "string",
- "number": "string",
- "apt": "string",
- "floor": "string",
- "entrance": "string",
- "comment": "string",
- "city": "string",
- "zip": "string",
- "country": "string",
- "company": "string",
- "destinationLongitude": "string",
- "destinationLatitude": "string",
- "driverLongitude": "string",
- "driverLatitude": "string",
- "selfDelivery": true
}, - "pickupInfo": {
- "pickupTime": "2019-08-24T14:15:22Z",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phonePin": "string",
- "phone": "string",
- "email": "string",
- "comment": "string"
}, - "inHouseOrderingInfo": {
- "inHouseOrderingTime": "2019-08-24T14:15:22Z",
- "tableId": "string",
- "tableDescription": "string",
- "serviceAreaId": "string",
- "serviceAreaDescription": "string",
- "roomId": "string",
- "roomDescription": "string",
- "firstName": "string",
- "lastName": "string",
- "middleName": "string",
- "phone": "string",
- "email": "string"
}, - "notes": "string",
- "discounts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "externalId": "string",
- "orderItems": [
- {
- "internalId": "string",
- "quantity": 0,
- "value": {
- "amount": 0,
- "currency": "string"
}
}
]
}
], - "amountToPay": {
- "amount": 0,
- "currency": "string"
}, - "additionalCosts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "tip": true,
- "taxRate": 0
}
], - "items": [
- {
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "internalId": "6868d0ce-34a2-4e78-b137-31229ba3e81a",
- "orderItemId": "string",
- "orderItemName": "string",
- "menuId": "string",
- "parentId": "70850378-7d3c-4f45-91b7-942d4dfbbd43",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "quantity": 0,
- "relativeQuantity": 0,
- "singlePrice": {
- "amount": 0,
- "currency": "string"
}, - "rowTotal": {
- "amount": 0,
- "currency": "string"
}, - "sortIndex": 0,
- "relativeRowTotal": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabels": "string",
- "providerItemId": "string",
- "isNote": true,
- "course": 0,
- "deposit": 0,
- "taxRate": 0,
- "parentGroupId": "dein_extra_dip"
}
], - "possibleActions": [
- "ready",
- "pickedUp",
- "inDelivery",
- "delivered"
], - "possibleStateChanges": [
- {
- "state": "ready",
- "timeChange": true
}, - {
- "state": "pickedUp",
- "timeChange": false
}, - {
- "state": "inDelivery",
- "timeChange": false
}, - {
- "state": "delivered",
- "timeChange": false
}
], - "preOrder": true,
- "platformUpdates": [
- {
- "status": "string",
- "updatedAt": "string",
- "data": {
- "driverName": "string",
- "driverTripId": "string",
- "deliveryTime": "string",
- "pickupTime": "string",
- "driverStatus": "string",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
], - "deposit": 0,
- "additionalInfo": {
- "containsSingleUseItems": true,
- "containsAlcoholicItems": true,
- "containsTobacco": true
}, - "courierInfo": {
- "status": "scheduled",
- "estimatedArrivalAtPickup": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "waitingStartsAt": "2019-08-24T14:15:22Z",
- "waitingFeeAppliesAt": "2019-08-24T14:15:22Z"
}
}
}POST /pos/execute/createTestOrder?example=pickup with the site API key; no body. Requires an active Site with exactly one Development activation and one restaurant ID assigned to that Site. Examples: pickup (default), inhouse (on-premises), delivery (selfDelivery false), fleet (selfDelivery true), fleet-no-automation (selfDelivery false), fleet-preorder (merchant delivery scheduled four hours ahead), fleet-cash (EUR 15.90 cash due; customer announces EUR 50), fleet-cash-insufficient (EUR 15.90 cash due; customer announces EUR 10), split-payments (EUR 10 prepaid CARD plus EUR 5.90 CASH due on delivery), additional-costs (Delivery Fee EUR 2.50 and Service Fee EUR 1.00; total EUR 19.40), discount (one EUR 2 discount; total EUR 13.90), self-delivery (full synthetic delivery/contact details, selfDelivery true). split-payments, additional-costs and discount are platform deliveries. The frontend must require the same explicit automation-risk checkbox for self-delivery as for other fleet-eligible samples; no new backend confirmation parameter is introduced. Creates one persisted order via the shared MainPlaceOrder processing, with stable test article IDs and a fresh order token. Does not fetch or accept the order. HTTP 202 returns remoteResponse.remoteOrderId for GET /pos/orders/{orderId}. Do not automatically retry timeouts.
WARNING: Not a dry-run. Normal mapping, POS delivery and notifications apply. Accepting fleet, fleet-preorder, fleet-cash, fleet-cash-insufficient or self-delivery may trigger configured automation and a paid delivery. Use a dedicated test Site and sandbox fleet. fleet-no-automation is a negative eligibility test: platform delivery blocks automation and normal manual fleet booking. Sample recipient data is not a real customer. WebSocket: {"action":"doPosCommand","command":"createTestOrder","data":{"example":"pickup"}}. Missing/ambiguous Development configuration returns 400 with error.code and error.message; inactive Sites return 403. Provider configuration is not created automatically.
| example | string Default: "pickup" Enum: "pickup" "delivery" "inhouse" "fleet" "fleet-no-automation" "fleet-cash" "fleet-cash-insufficient" "fleet-preorder" "split-payments" "additional-costs" "discount" "self-delivery" For createTestOrder only. Delivery examples include Berlin destination coordinates. Development orders permit time changes unless explicitly disabled by the POS configuration. fleet, fleet-cash and fleet-cash-insufficient permit automation after acceptance; fleet-no-automation blocks both automatic and normal manual fleet booking. Cash samples owe EUR 15.90 and announce EUR 50 or EUR 10 respectively via payment.cashToExpect; Wolt collection requires fleet cash configuration. Existing samples remain prepaid. Persisted test orders, not dry runs. |
| siteId | string <uuid> Normally omit: inferred from the authenticated site API key. If supplied it must match that Site. |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "remoteResponse": {
- "remoteOrderId": "1dc2ee79-e1bf-481a-807f-53ff3fd67b0e"
}
}Webhooks are recommended for cloud POS systems. During the initial joint setup with MERGEPORT, agree which of the following optional features your connection uses. They are per-Site POS settings, not mandatory requirements for every partner.
| Setting | Purpose |
|---|---|
webhookSigningMode: "standard-webhooks" |
Sign full-order webhooks with HMAC instead of transmitting webhookSecret. Also permits the selected signed POS API calls described below; regular Site API keys remain supported. |
onlyAcceptedOrders |
Forward orders after acceptance rather than at initial receipt. Suitable for an additional downstream receiver; another POS or the platform must provide acceptance where required. This setting does not accept orders itself. |
forwardAllStatusChanges |
Forward full-order updates for additional lifecycle states instead of just the usual order/cancellation delivery. This is separate from the minimal order-event subscription. |
disableAutoRejection |
For active POS delivery with scheduled retries, suppress the terminal MERGEPORT rejection/status update after retry exhaustion. Retries still stop; provider timeouts/cancellations, separate expiry checks and other POS connections remain possible. Arrange manual fulfilment when needed. |
orderEventsUrl, orderEventTypes, orderEventsSecret |
Subscribe separately to selected status, courier, fleet or terminal POS-delivery-failure notifications. Use a dedicated event signing secret; messages identify the affected order rather than sending it in full. See Order events. |
Confirm the chosen settings with MERGEPORT before enabling them. Available
Controller controls depend on the installed POS definition. In particular,
the subscription is optional. With an event URL, supply orderEventTypes as an
array, not a comma-separated string; an empty array unsubscribes. Without a
subscription the fields can be omitted. Do not preselect events through defaults.
onlyAcceptedOrders and forwardAllStatusChanges currently control the
notification-only webhook connection (dummyPOS); they do not change every active
POS adapter's injection rules. With both enabled, additional status notifications
remain enabled. Conversely, disableAutoRejection applies to the active POS retry
flow, not this notification-only connection. Confirm the intended connection type
during setup rather than copying all switches to every adapter.
In Controller, select the Site, open Configuration and edit its active POS
connection. Set webhookUrl and webhookSecret to receive full normalized orders.
Existing onlyAcceptedOrders / forwardAllStatusChanges settings determine which
order states are forwarded. Store the order before acknowledging with HTTP 200,
201, 202 or 204. This acknowledges technical receipt, not restaurant acceptance:
send acceptedByPOS through the order-state API when appropriate. The existing
delivery path permits an initial attempt and up to three scheduled retries;
timeouts/failed delivery can cause duplicates. Deduplicate by the order ID and
update already known orders when their content changes.
For additional compact change notifications, configure orderEventsUrl,
orderEventsSecret, and orderEventTypes; see Order events.
These messages contain event/site/order/source identifiers, not a complete order.
They have one delivery attempt, no retries or replay. Subscribe only to needed
types. HTTP 2xx does not accept the order. Fetching an order still requires the
normal Site API key; signed GET calls are not part of this feature.
Full-order POS webhooks and POS order-event webhooks include:
x-mergeport-site-id: owning Site.x-mergeport-pos-id: recipient POS connection, not the event source.x-mergeport-provider-id: MERGEPORT provider ID when available (not a name/slug).Provider-specific APIs and fleet dispatch protocols are not changed. Routing headers are not authentication and are not part of the existing outgoing signature. Verify the body and cross-check its Site/provider identifiers where present; associate the receiving endpoint/secret with the expected POS. Do not trust an unsigned routing header to select arbitrary privileges.
Outgoing authentication remains unchanged: legacy order delivery transmits the
configured secret in Authorization; optional webhookSigningMode: standard-webhooks
uses the existing HMAC signature instead. Order-event notifications always use
their separate orderEventsSecret with that signature format. Do not confuse
these outgoing signatures with the following incoming POS authentication.
Example outgoing order-event request (signature placeholder):
POST /mergeport/events HTTP/1.1
Host: pos.example.com
Content-Type: application/json
x-mergeport-site-id: site-example
x-mergeport-pos-id: pos-example
x-mergeport-provider-id: provider-example
webhook-id: msg_example
webhook-timestamp: 1790683200
webhook-signature: v1,<computed-base64-hmac>
{"eventId":"msg_example","type":"order.statusChanged","occurredAt":"2026-09-29T12:00:00.000Z","siteId":"site-example","orderId":"order-example","source":{"type":"provider","providerId":"provider-example"}}
Capture the raw body before JSON parsing, verify the existing outgoing signature
with the matching recipient secret, validate the timestamp, and deduplicate by
webhook-id. Then route/process the verified message and acknowledge it. A
previously processed delivery should be acknowledged without repeating its side
effects. Order-event notifications have no retry; do not apply full-order retry
assumptions to them. Legacy order deliveries have no webhook-id; use their order
identity/state instead. Standard-signed full-order retries retain their original
ID and timestamp, so choose their timestamp tolerance to accommodate the agreed
retry window rather than silently rejecting delayed retries.
Use the existing webhookSigningMode: "standard-webhooks" on the Site's POS
accessDetails, with a nonempty webhookSecret and an active POS definition.
This mode enables signatures in both directions; the secret is not transmitted.
No additional switch or dependency metadata is required. Existing connections
already using this mode also gain the ability to authenticate the two calls below.
Without using that ability, their existing request and delivery behavior stays
unchanged. Missing, null or legacy mode does not permit signed API calls; normal
Site API-key authentication remains supported in every mode. The mode is never
changed automatically. Disabled connections and disabled/expired Sites are
rejected, with no Controller exception. Configuration example:
{"webhookSigningMode":"standard-webhooks","webhookSecret":"<securely-shared-secret>"}
This alternative is available ONLY for POST /pos/items and
PATCH /pos/orders/{id}, at /v4 or /beta. POST still replaces/upserts items;
it does not become a partial update. Other endpoints, WebSocket authentication,
menu/channel authentication and existing Site API-key calls remain unchanged.
Use either API-key authentication or signed authentication, never both together.
No new public endpoint is introduced. Do not send Authorization or X-Api-Key with
signed requests. orderEventsSecret cannot authenticate these calls.
Headers (all five required):
| Header | Value |
|---|---|
x-mergeport-site-id |
Site ID from the received order/webhook |
x-mergeport-pos-id |
Your configured POS ID |
x-mergeport-timestamp |
Unix seconds, decimal integer |
x-mergeport-content-sha256 |
Lowercase hex SHA-256 of the exact UTF-8 body bytes |
x-mergeport-signature |
v1, followed by base64 HMAC-SHA256 |
The host, method and public path below are obtained from the request itself. Sign these eight lines with LF separators and NO final LF:
mergeport-pos-v1
{siteId}
{posId}
{timestamp}
{lowercase-host}
{uppercase-method}
{public-path}
{lowercase-body-sha256}
Use the literal UTF-8 webhookSecret as the HMAC key, not a base64-decoded value.
The public path includes /beta or /v4, for example /beta/pos/items.
No query strings, trailing slashes or encoded path variants are supported for this
authentication mode. Use ordering.mergeport.com; direct execute-api URLs and
other stage mappings are not supported. Internally REST Gateway stage beta means public
/beta, and Gateway stage prod means public /v4; never infer the public path
from the Serverless stack name. The host and environment are signed to prevent
cross-environment reuse.
The authorizer verifies the signature, current connection and a timestamp window of ±300 seconds. Only this operation is authorized; the handler then verifies the actual body hash before activity writes or business processing. Changed bodies, revoked settings and rotated secrets fail closed. Keep clocks synchronized. A timestamp window alone does NOT prevent identical replays inside the window; no nonce store or exactly-once guarantee is provided. The existing operation's idempotency/state semantics remain in effect.
const crypto = require('crypto');
const https = require('https');
const siteId = process.env.MERGEPORT_SITE_ID;
const posId = process.env.MERGEPORT_POS_ID;
const secret = process.env.MERGEPORT_WEBHOOK_SECRET;
const host = 'ordering.mergeport.com';
const path = '/beta/pos/orders/497f6eca-6276-4993-bfeb-53cbbbba6f08';
const method = 'PATCH';
const body = JSON.stringify({state:'acceptedByPOS'});
const timestamp = String(Math.floor(Date.now()/1000));
const hash = crypto.createHash('sha256').update(body,'utf8').digest('hex');
const input = ['mergeport-pos-v1',siteId,posId,timestamp,host,method,path,hash].join('\n');
const signature = 'v1,'+crypto.createHmac('sha256',secret).update(input,'utf8').digest('base64');
const request = https.request({hostname:host,path,method,headers:{
'Content-Type':'application/json',
'x-mergeport-site-id':siteId,
'x-mergeport-pos-id':posId,
'x-mergeport-timestamp':timestamp,
'x-mergeport-content-sha256':hash,
'x-mergeport-signature':signature
}}, response => { /* Handle the normal endpoint response. */ });
request.on('error', error => { /* Handle transport uncertainty; do not blindly retry. */ });
request.end(body); // Send exactly the serialized bytes that were hashed.
An authorizer rejection returns HTTP 401. A handler proof/body rejection returns
HTTP 401 with error.code: INVALID_SIGNED_REQUEST. Normal validation/status errors
retain their existing response contracts. Do not log secrets or signatures.
Requesting a state change still follows possibleStateChanges and does not bypass
provider validation. The secret is not transmitted by these incoming signed calls;
legacy OUTGOING webhook mode still transmits it as described above and therefore
cannot be combined with enabled signed API access.
Optional order-event subscriptions are the recommended way to notice changes to known orders without continuously polling them. They do not replace new-order delivery or the POS acceptance call. A webhook HTTP acknowledgement never accepts an order or changes its lifecycle.
In https://controller.mergeport.com select the Site, open Configuration, edit the relevant POS connection and set:
orderEventsUrl: public HTTPS endpoint, port 443, no redirects.orderEventsSecret: nonempty signing secret, never included in events.orderEventTypes: array of selected event names below, required with an event URL in the conditional field definition. Empty means unsubscribed.Save the connection. To change the subscription, edit these same fields. To stop
events, save orderEventTypes: [] or remove the URL. The fields require the stored
POS definition metadata and matching Controller controls; there is no automatic
definition import. UI labels may differ until those controls are released.
| Type | Meaning |
|---|---|
order.statusChanged |
A persisted order lifecycle status actually changed. |
order.deliveryUpdated |
Stored ordering-platform courier information or existing driver-update data changed, independently of the current order status. |
order.deliveryFleetUpdated |
A booked fleet delivery changed meaningfully (status, tracking, estimate, price or cancellation), not an offer or pure GPS update. |
order.posDeliveryFailed |
The final technical delivery attempt to an active webhook POS failed. Not a restaurant rejection or failed driver delivery. |
Example (no order body and no changes object):
{"eventId":"msg_01EXAMPLE","type":"order.deliveryUpdated","occurredAt":"2026-09-28T14:30:00.000Z","siteId":"site-id","orderId":"mergeport-order-id","source":{"type":"provider","providerId":"provider-id","providerInstanceId":"activation-id","providerName":"Wolt"}}
orderId is the MERGEPORT ID. occurredAt is the known source occurrence time,
otherwise the processing time. eventId is transient, used for correlation and
signing; it is not a persistent event log. Source types are provider, pos,
controller, deliveryFleet, mergeport. The source describes the initiator,
not the transport or recipient, and is not an authorization assertion. Provider
identifiers come from the order; unavailable legacy instance identifiers remain
absent. POS source may include a known posId. Fleet callbacks include
deliveryFleetId and fleetId, plus top-level deliveryId. Locally initiated
fleet actions without a reliable caller identity use mergeport.
On receipt, validate the signature, promptly return HTTP 2xx, then retrieve the
current order with GET /pos/orders/{id} if needed. For fleet events, retrieve
the delivery with GET /pos/deliveries/{deliveryId}. The current record can already
be newer than the triggering event. Do not infer business acceptance from 2xx.
HTTP notifications also carry x-mergeport-site-id and, for POS recipients,
x-mergeport-pos-id. x-mergeport-provider-id is included when the event source
provides it. These are routing hints, not signed identity assertions; verify the
body and its identifiers. See POS webhook integration
for optional signed REST actions. Incoming signed calls use webhookSecret, NOT
this subscription's separate orderEventsSecret.
The existing Standard Webhooks format is reused: webhook-id (eventId),
webhook-timestamp (Unix seconds), webhook-signature (v1,<base64 HMAC>).
Compute HMAC-SHA256 with the configured secret over
webhook-id + "." + webhook-timestamp + "." + rawRequestBody, without reparsing or
reserializing the body. Compare signatures in constant time and enforce a short
timestamp tolerance (for example five minutes). The configured secret is used
literally, not base64-decoded. Never expose it in logs.
Exactly one attempt per selected recipient is intended: no notification retries, outbox, replay, guaranteed delivery, ordering guarantee or exactly-once guarantee. A process failure after the data write can lose an event. Each HTTP/socket attempt has at most 2.5 seconds; recipient selection and sends share a five-second budget. Slow/failed recipients do not roll back the saved order. Recipients are independent. Legacy order webhooks remain unchanged and may still carry the complete order; subscribing to both deliberately enables two different message contracts. Identical driver data or a processing timestamp alone does not trigger an event.
Existing authenticated Site sockets receive no new messages unless they subscribe:
{"action":"subscribeOrderEvents","data":{"orderEventTypes":["order.statusChanged","order.deliveryUpdated","order.deliveryFleetUpdated","order.posDeliveryFailed"]}}
The acknowledgement has action: "subscribeOrderEvents", code: 200 and the
selected orderEventTypes. Pushes use {"action":"orderEvent","data":{...event}}.
An empty array unsubscribes; a new subscription replaces the old selection.
Reconnect requires subscribing again. There is no replay. All four types are
available within the authenticated Site, including failures of any POS connection
on that Site. No new POS identity or privileged Controller login is introduced.
HTTP failure-event filtering remains limited to the affected POS connection.
Existing delivery attempts and retry timing remain unchanged: currently an initial
attempt and up to three scheduled retries. Only terminal technical exhaustion
produces order.posDeliveryFailed, after completing the existing terminal path and
removing the matching retry entry. Additional fields are posId, attemptCount
(including the initial attempt) and sanitized failureReason, e.g. timeout or
HTTP 503. Source is mergeport: the POS did not report this event.
This includes the existing local timedOut outcome or suppressed rejection under
disableAutoRejection: true. It does not change that setting's no-order-write
behavior. Intermediate failures, a successful injection, order expiry alone and
restaurant rejection do not produce this failure event. Later provider events and
cancellations continue normally. There is no multi-POS acceptance arbitration.
MERGEPORT independently notifies its existing internal notification receiver, even with no POS subscription. It receives the same technical failure facts in the existing internal notification envelope; this does not change the signed POS event contract or require extra POS settings. There are no recursive failure events. Removing the retry entry is the existing completion claim; a crash after that claim can lose the notification.
courierInfo is optional on stored orders and POS order responses regardless of
subscriptions. status is a courier status, not order acceptance/preparation.
estimatedArrivalAtPickup is an ISO timestamp for arrival/pickup at the restaurant,
never food-readiness time or delivery time at the customer. updatedAt retains the
last meaningful provider snapshot time (source time where available). Missing
fields are unknown or no longer current. Status completion removes obsolete ETA
and waiting fields without inventing a courier status. The POS calculates minutes.
courier.notification means approaching the restaurant; use
courier_details.courier_pickup_eta. pickup_completed.notification requires
details.is_pickup_completed: true. Pickup ETA no longer overwrites customer
deliveryInfo.deliveryTime; legacy platformUpdates.data.pickupTime is used.deliveries fields,
independently of whether the original order arrived through newer V1 or legacy
V2. Match the trip, or use the sole delivery when no trip is known; never select
an arbitrary delivery. No readiness-to-ETA conversion. Failed enrichment leaves
existing status processing working. Warm-worker coalescing is ten seconds per
order, not a distributed provider rate limit; cold workers can make another read.driverAtRestaurant maps to courierAtPickup. Other unconfirmed codes stay
in existing platformUpdates; no ETA/GPS is invented.waitingAtPickup and
waitingAtPickupEnded, with optional waitingStartsAt/waitingFeeAppliesAt.
Ending a warning does not confirm pickup. No inferred waiting charge.Known stale timestamps are ignored. Repeated semantic data is not re-notified. Incomplete updates preserve still-valid fields; a known trip change, completed pickup or terminal order removes obsolete pickup ETA. Without source timestamps, perfect ordering cannot be established. No GPS, transportation-mode inference, fixed update frequency or additional provider data availability is promised.
Check the current order and the event ID when investigating a missed update. Absence of a delivered notification does not prove successful POS injection.
Provider references: Wolt webhooks, Uber V2 courier fields.
WebSocket action: GetPosItems
| Authorization required | string <uuid> static apiKey provided by Mergeport |
[- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "category": {
- "en": "Category",
- "de": "Kategorie",
- "it": "Categoria"
}, - "subCategory": {
- "en": "Subcategory",
- "de": "Unterkategorie",
- "it": "categoria suplementare"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "allergens": "AELO",
- "additives": "E102,E250,CAFFEINE_HIGH_CAFFEINE",
- "foodWarnings": "coloursHyperactivity,sweetenersPhenylalanine",
- "reference": "string",
- "parentId": "string",
- "parentIds": [
- "string"
], - "imgUrl": "string",
- "enabled": true,
- "stock": 0,
- "categoryIds": [
- "string"
], - "menuIds": [
- "string"
], - "labels": [
- "vegan"
], - "ean": "8501110082969",
- "type": "product",
- "sort": 0,
- "options": {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}, - "optionsList": [
- {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}
], - "lastUpdated": "2019-08-24T14:15:22Z",
- "deposit": 0,
- "taxRate": 19,
- "hidden": true,
- "bundle": {
- "partySize": 1
}
}
]WebSocket action: SetPosItems
This action performs an upload of the items in the payload of the request. The items will be stored and saved on our end and can be curated in the MERGEPORT controller as well as queried by the services providers. Existing submitted items are replaced, not merged: omitted attributes are removed subject to established defaults (including enabled=true). Unknown IDs are created. Items absent from the submitted list are untouched. Use PATCH /pos/items for partial updates that preserve omitted fields.
If the options "availableChoices" are set, they are the preferred source for service providers and ordering platforms to build their menu upon. "availableChoices" provide more flexibility and possibilities for a dynamic configuration. If empty, the ordering platforms usually fall back to the parentIds structure.
Please note that you need to use "set specifications of the specified POS item" endpoint to upload an image.
Optional taxRate is a numeric percentage included in the gross price (0 through 100, for example 19 or 8.1). Zero is preserved; omit unknown rates. It is saved and returned without recalculating prices. Supported menu channels forward it when the taxRate field link is enabled; existing channels are not silently changed. Individual item updates preserve an omitted rate and accept an explicit zero.
| x-mergeport-site-id | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-pos-id | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-timestamp | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-content-sha256 | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| x-mergeport-signature | string Required for optional signed POS authentication. See POS webhook integration for standard-webhooks mode and signing rules. |
| Authorization | string <uuid> Site API key, required unless signed POS authentication is used. See POS webhook integration. |
Array of Pos Items
| id required | string item id in the pos system |
object | |
object Nullable associative array of different names for ISO-639-1-Codes | |
object Nullable Deprecated associative array of different categories for ISO-639-1-Codes | |
object Nullable Deprecated associative array of different subCategories for ISO-639-1-Codes | |
object Nullable associative array of different descriptions for ISO-639-1-Codes | |
| allergens | string Nullable here you can specify the allergens Codes:
|
| additives | string Nullable ^(?:(?:E[-_]?[0-9]{3,4}[A-Za-z]?|UNSPECIFIED|... Comma-, semicolon- or space-separated additive codes. Supports E-numbers (for example E102 or E250) and canonical declarations such as CAFFEINE_HIGH_CAFFEINE. Channel adapters translate these values into the provider-specific format. |
| foodWarnings | string Nullable ^(?:(?:coloursHyperactivity|sweetenersPhenyla... Comma-separated canonical food warning codes used for legally or contextually required notices. Supported codes are coloursHyperactivity, sweetenersPhenylalanine, sweetenersLaxativeEffects, caffeineHighContentBeverage, caffeineNonBeverage, liquoriceHypertension, packagingGasesProtectiveAtmosphere and plantSterolsStanols. |
| reference | string Nullable extra unique reference of the item (PLU) |
| parentId | string Nullable Deprecated item id of the parent item in the pos system |
| parentIds | Array of strings Nullable list of item ids of the parent items in the pos system |
| imgUrl | string Nullable url to the image of the product |
| enabled | boolean Nullable on/off switch for the product |
| stock | number Nullable items currently in stock |
| categoryIds | Array of strings Nullable list of category ids of the parent categories in the pos system |
| menuIds | Array of strings Nullable list of menu ids of the parent menus in the pos system |
| labels | Array of strings Nullable list of extra labels for the product |
| ean | string Nullable extra unique reference of the item (European Article Number) |
| type | string Nullable Enum: "product" "topping" extra type definition of the product |
| sort | number Nullable number to sort items |
object Nullable Deprecated Deprecated: use optionsList. Kept for legacy clients. A nonempty options object is used as [options] only when optionsList is missing, null or empty. A populated optionsList wins. Clear both options (null or {}) and optionsList ([]) to remove all groups. | |
Array of objects Canonical option groups. A populated list wins over legacy options. Empty lists fall back to legacy options when present. | |
| lastUpdated | string <date-time> Nullable time item was changed (filled automatically) |
| deposit | number Nullable Price of deposit in cents |
| taxRate | number [ 0 .. 100 ] Optional tax percentage included in the gross item price, like order.items.taxRate (for example 7, 19 or 8.1). Zero is a supplied rate; omit when unknown. MERGEPORT does not determine the legally applicable rate or recalculate prices. Forwarded by configured channel links where supported. |
| hidden | boolean Optional catalog visibility flag. Currently supported by Deliveroo availability synchronization: true sends hidden regardless of enabled; false or omission uses enabled (false = unavailable, otherwise available). Other provider adapters do not interpret this flag. PATCH omission preserves it; PATCH false clears hiding, not an enabled=false stock restriction. POST replacement omission removes it. Null is not accepted. |
object Nullable Explicit bundle marker on the main product; {} marks a bundle without a serving count. Its existing optionsList defines the sections and referenced products. Currently interpreted by Deliveroo menu export only. Omission preserves the field on PATCH and removes it on replacement POST; null clears the marker. A supplied object replaces the complete bundle field. |
[- {
- "id": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "category": {
- "en": "Category",
- "de": "Kategorie",
- "it": "Categoria"
}, - "subCategory": {
- "en": "Subcategory",
- "de": "Unterkategorie",
- "it": "categoria suplementare"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "allergens": "AELO",
- "additives": "E102,E250,CAFFEINE_HIGH_CAFFEINE",
- "foodWarnings": "coloursHyperactivity,sweetenersPhenylalanine",
- "reference": "string",
- "parentId": "string",
- "parentIds": [
- "string"
], - "imgUrl": "string",
- "enabled": true,
- "stock": 0,
- "categoryIds": [
- "string"
], - "menuIds": [
- "string"
], - "labels": [
- "milk-free"
], - "ean": "8501110082969",
- "type": "product",
- "sort": 0,
- "options": {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}, - "optionsList": [
- {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}
], - "lastUpdated": "2019-08-24T14:15:22Z",
- "deposit": 0,
- "taxRate": 19,
- "hidden": true,
- "bundle": {
- "partySize": 1
}
}
][- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "category": {
- "en": "Category",
- "de": "Kategorie",
- "it": "Categoria"
}, - "subCategory": {
- "en": "Subcategory",
- "de": "Unterkategorie",
- "it": "categoria suplementare"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "allergens": "AELO",
- "additives": "E102,E250,CAFFEINE_HIGH_CAFFEINE",
- "foodWarnings": "coloursHyperactivity,sweetenersPhenylalanine",
- "reference": "string",
- "parentId": "string",
- "parentIds": [
- "string"
], - "imgUrl": "string",
- "enabled": true,
- "stock": 0,
- "categoryIds": [
- "string"
], - "menuIds": [
- "string"
], - "labels": [
- "vegan"
], - "ean": "8501110082969",
- "type": "product",
- "sort": 0,
- "options": {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}, - "optionsList": [
- {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}
], - "lastUpdated": "2019-08-24T14:15:22Z",
- "deposit": 0,
- "taxRate": 19,
- "hidden": true,
- "bundle": {
- "partySize": 1
}
}
]WebSocket action: PatchPosItems
Unlike POST replacement/upsert, PATCH updates only supplied top-level fields of existing items. Send 1–100 partial item objects. siteId comes from authentication; lastUpdated is server-generated. Duplicate IDs reject the whole request before writes. Other per-item failures do not roll back successful items; inspect results even on HTTP 207.
Nested objects replace the complete field, not a deep merge: send both amount and currency when replacing price. Omitted fields are preserved with no defaults. Explicit false/0 are stored; null is stored only for nullable fields, never treated as removal. Empty strings, arrays and objects are stored where the item schema permits them. taxRate:null is invalid; categoryIds:[] empties the list. There is no attribute-removal operation. Unknown top-level fields/plural aliases fail that item.
Successful updates return complete stored items and invoke the existing item/channel sync mechanism. synchronization.triggered is not proof of provider acceptance. A sync trigger failure leaves item writes intact. ITEM_UPDATE_UNCONFIRMED requires a read before retry. No upsert, no bulk transaction. Concurrent writes to distinct top-level fields are preserved; the same field is last-writer-wins.
| Authorization required | string <uuid> static apiKey provided by Mergeport |
| id required | string item id in the pos system |
object | |
object Nullable associative array of different names for ISO-639-1-Codes | |
object Nullable Deprecated associative array of different categories for ISO-639-1-Codes | |
object Nullable Deprecated associative array of different subCategories for ISO-639-1-Codes | |
object Nullable associative array of different descriptions for ISO-639-1-Codes | |
| allergens | string Nullable here you can specify the allergens Codes:
|
| additives | string Nullable ^(?:(?:E[-_]?[0-9]{3,4}[A-Za-z]?|UNSPECIFIED|... Comma-, semicolon- or space-separated additive codes. Supports E-numbers (for example E102 or E250) and canonical declarations such as CAFFEINE_HIGH_CAFFEINE. Channel adapters translate these values into the provider-specific format. |
| foodWarnings | string Nullable ^(?:(?:coloursHyperactivity|sweetenersPhenyla... Comma-separated canonical food warning codes used for legally or contextually required notices. Supported codes are coloursHyperactivity, sweetenersPhenylalanine, sweetenersLaxativeEffects, caffeineHighContentBeverage, caffeineNonBeverage, liquoriceHypertension, packagingGasesProtectiveAtmosphere and plantSterolsStanols. |
| reference | string Nullable extra unique reference of the item (PLU) |
| parentId | string Nullable Deprecated item id of the parent item in the pos system |
| parentIds | Array of strings Nullable list of item ids of the parent items in the pos system |
| imgUrl | string Nullable url to the image of the product |
| enabled | boolean Nullable on/off switch for the product |
| stock | number Nullable items currently in stock |
| categoryIds | Array of strings Nullable list of category ids of the parent categories in the pos system |
| menuIds | Array of strings Nullable list of menu ids of the parent menus in the pos system |
| labels | Array of strings Nullable list of extra labels for the product |
| ean | string Nullable extra unique reference of the item (European Article Number) |
| type | string Nullable Enum: "product" "topping" extra type definition of the product |
| sort | number Nullable number to sort items |
object Nullable Deprecated Deprecated: use optionsList. Kept for legacy clients. A nonempty options object is used as [options] only when optionsList is missing, null or empty. A populated optionsList wins. Clear both options (null or {}) and optionsList ([]) to remove all groups. | |
Array of objects Canonical option groups. A populated list wins over legacy options. Empty lists fall back to legacy options when present. | |
| lastUpdated | string <date-time> Nullable time item was changed (filled automatically) |
| deposit | number Nullable Price of deposit in cents |
| taxRate | number [ 0 .. 100 ] Optional tax percentage included in the gross item price, like order.items.taxRate (for example 7, 19 or 8.1). Zero is a supplied rate; omit when unknown. MERGEPORT does not determine the legally applicable rate or recalculate prices. Forwarded by configured channel links where supported. |
| hidden | boolean Optional catalog visibility flag. Currently supported by Deliveroo availability synchronization: true sends hidden regardless of enabled; false or omission uses enabled (false = unavailable, otherwise available). Other provider adapters do not interpret this flag. PATCH omission preserves it; PATCH false clears hiding, not an enabled=false stock restriction. POST replacement omission removes it. Null is not accepted. |
object Nullable Explicit bundle marker on the main product; {} marks a bundle without a serving count. Its existing optionsList defines the sections and referenced products. Currently interpreted by Deliveroo menu export only. Omission preserves the field on PATCH and removes it on replacement POST; null clears the marker. A supplied object replaces the complete bundle field. |
[- {
- "id": "123",
- "enabled": false
}
]{- "results": [
- {
- "index": 0,
- "id": "123",
- "status": 404,
- "error": {
- "type": "ITEM_NOT_FOUND",
- "message": "The item does not exist for this site."
}
}
], - "synchronization": {
- "status": "notRequired"
}
}WebSocket action: GetItem. Returns the stored optional taxRate, including zero; an unknown rate is omitted.
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "category": {
- "en": "Category",
- "de": "Kategorie",
- "it": "Categoria"
}, - "subCategory": {
- "en": "Subcategory",
- "de": "Unterkategorie",
- "it": "categoria suplementare"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "allergens": "AELO",
- "additives": "E102,E250,CAFFEINE_HIGH_CAFFEINE",
- "foodWarnings": "coloursHyperactivity,sweetenersPhenylalanine",
- "reference": "string",
- "parentId": "string",
- "parentIds": [
- "string"
], - "imgUrl": "string",
- "enabled": true,
- "stock": 0,
- "categoryIds": [
- "string"
], - "menuIds": [
- "string"
], - "labels": [
- "vegan"
], - "ean": "8501110082969",
- "type": "product",
- "sort": 0,
- "options": {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}, - "optionsList": [
- {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}
], - "lastUpdated": "2019-08-24T14:15:22Z",
- "deposit": 0,
- "taxRate": 19,
- "hidden": true,
- "bundle": {
- "partySize": 1
}
}WebSocket action: SetPosItemSpecs
This action allows to update/set specifications for an already existing POS item. Mainly used for the image at the moment.
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Specs Object for Pos Items
| img required | string <byte> the base64 encoded image for the item |
{- "img": "string"
}{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "category": {
- "en": "Category",
- "de": "Kategorie",
- "it": "Categoria"
}, - "subCategory": {
- "en": "Subcategory",
- "de": "Unterkategorie",
- "it": "categoria suplementare"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "allergens": "AELO",
- "additives": "E102,E250,CAFFEINE_HIGH_CAFFEINE",
- "foodWarnings": "coloursHyperactivity,sweetenersPhenylalanine",
- "reference": "string",
- "parentId": "string",
- "parentIds": [
- "string"
], - "imgUrl": "string",
- "enabled": true,
- "stock": 0,
- "categoryIds": [
- "string"
], - "menuIds": [
- "string"
], - "labels": [
- "vegan"
], - "ean": "8501110082969",
- "type": "product",
- "sort": 0,
- "options": {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}, - "optionsList": [
- {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}
], - "lastUpdated": "2019-08-24T14:15:22Z",
- "deposit": 0,
- "taxRate": 19,
- "hidden": true,
- "bundle": {
- "partySize": 1
}
}WebSocket action: DeletePosItem
This action allows to delete a POS item.
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "category": {
- "en": "Category",
- "de": "Kategorie",
- "it": "Categoria"
}, - "subCategory": {
- "en": "Subcategory",
- "de": "Unterkategorie",
- "it": "categoria suplementare"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "allergens": "AELO",
- "additives": "E102,E250,CAFFEINE_HIGH_CAFFEINE",
- "foodWarnings": "coloursHyperactivity,sweetenersPhenylalanine",
- "reference": "string",
- "parentId": "string",
- "parentIds": [
- "string"
], - "imgUrl": "string",
- "enabled": true,
- "stock": 0,
- "categoryIds": [
- "string"
], - "menuIds": [
- "string"
], - "labels": [
- "vegan"
], - "ean": "8501110082969",
- "type": "product",
- "sort": 0,
- "options": {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}, - "optionsList": [
- {
- "description": {
- "property1": "string",
- "property2": "string"
}, - "groupName": {
- "en": "Cooking level",
- "de": "Garstufe",
- "it": "Livello di cottura"
}, - "defaultChoices": [
- "1000123"
], - "minChoices": 0,
- "maxChoices": 3,
- "availableChoices": [
- {
- "id": "1000123",
- "price": 300,
- "addPrice": -100,
- "multiselect": false,
- "canBeUnselected": true
}
]
}
], - "lastUpdated": "2019-08-24T14:15:22Z",
- "deposit": 0,
- "taxRate": 19,
- "hidden": true,
- "bundle": {
- "partySize": 1
}
}WebSocket action: GetPosCategories
| Authorization required | string <uuid> static apiKey provided by Mergeport |
[- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "parentIds": [
- "string"
], - "availabilityIds": [
- "string"
], - "enabled": true
}
]WebSocket action: SetPosCategories
This action performs an upload of the categories in the payload of the request. The categories will be stored and saved on our end and can be curated in the MERGEPORT controller as well as queried by the services providers. Already existing categories will be updated.
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Array of Pos Categories
| id required | string category id in the pos system |
object Nullable associative array of different names for ISO-639-1-Codes | |
object Nullable associative array of different descriptions for ISO-639-1-Codes | |
| imgUrl | string Nullable url to the image of the menu |
| parentIds | Array of strings Nullable list of category ids of the parent categories in the pos system |
| availabilityIds | Array of strings Nullable IDs of reusable PosAvailability schedules. Multiple IDs are combined as a union. Explicit category references take precedence over parent-category and menu schedules; missing or empty IDs inherit the next applicable schedule. |
| enabled | boolean Nullable on/off switch for the menu |
[- {
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "parentIds": [
- "string"
], - "availabilityIds": [
- "string"
], - "enabled": true
}
][- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "parentIds": [
- "string"
], - "availabilityIds": [
- "string"
], - "enabled": true
}
]WebSocket action: GetCategory
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "parentIds": [
- "string"
], - "availabilityIds": [
- "string"
], - "enabled": true
}WebSocket action: SetPosCategorySpecs
This action allows to update/set specifications for an already existing POS category. Mainly used for the image at the moment.
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Specs Object for Pos Categories
| img required | string <byte> the base64 encoded image for the item |
{- "img": "string"
}{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "parentIds": [
- "string"
], - "availabilityIds": [
- "string"
], - "enabled": true
}WebSocket action: DeletePosCategory
This action allows to delete a POS category.
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "parentIds": [
- "string"
], - "availabilityIds": [
- "string"
], - "enabled": true
}WebSocket action: GetPosMenus
| Authorization required | string <uuid> static apiKey provided by Mergeport |
[- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "menuType": [
- "pickup"
], - "availabilityIds": [
- "string"
], - "enabled": true
}
]WebSocket action: SetPosMenus
This action performs an upload of the menus in the payload of the request. The menus will be stored and saved on our end and can be curated in the MERGEPORT controller as well as queried by the services providers. Already existing menus will be updated.
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Array of Pos Menus
| id required | string menu id in the pos system |
object Nullable associative array of different names for ISO-639-1-Codes | |
object Nullable associative array of different descriptions for ISO-639-1-Codes | |
| imgUrl | string Nullable url to the image of the menu |
| menuType | Array of strings Nullable Items Enum: "pickup" "delivery" "inHouse" list of expeditionTypes the product should be available for |
| availabilityIds | Array of strings Nullable IDs of reusable PosAvailability schedules. Multiple IDs are combined as a union. Categories without their own or inherited parent-category schedule inherit this menu schedule; missing or empty IDs mean unrestricted availability. |
| enabled | boolean Nullable on/off switch for the menu |
[- {
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "menuType": [
- "pickup"
], - "availabilityIds": [
- "string"
], - "enabled": true
}
][- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "menuType": [
- "pickup"
], - "availabilityIds": [
- "string"
], - "enabled": true
}
]WebSocket action: GetMenu
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "menuType": [
- "pickup"
], - "availabilityIds": [
- "string"
], - "enabled": true
}WebSocket action: SetPosMenuSpecs
This action allows to update/set specifications for an already existing POS menu. Mainly used for the image upload at the moment.
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Specs Object for Pos Menus
| img required | string <byte> the base64 encoded image for the item |
{- "img": "string"
}{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "menuType": [
- "pickup"
], - "availabilityIds": [
- "string"
], - "enabled": true
}WebSocket action: DeletePosMenu
This action allows to delete a POS menu item.
| id required | string id of the item |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "imgUrl": "string",
- "menuType": [
- "pickup"
], - "availabilityIds": [
- "string"
], - "enabled": true
}Assigns POS item IDs to imported ordering-platform items. After a mapping item is populated with a posItemId, future orders for that item include the assigned POS item ID. The operation updates POS-owned mapping fields and may initialize legacy identity/display fields only when they do not exist yet. Omitted or submitted provider-owned fields, lifecycle metadata, relationships and raw never delete or overwrite stored provider catalog data.
WebSocket action: SetMappingItems
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Array of Mapping Items
| providerItemId required | string item id for the shop |
| providerId | string Nullable provider id for the shop if extra |
object | |
| posItemId | string Nullable id of the item in the pos system |
| posItemLabelsIdConcat | string Nullable itemLabelsAndIdConcat from the mapped pos item, or null |
| itemName | string Nullable the name for the item |
| itemCategory | string Nullable the category for the item |
| itemSubCategory | string Nullable the subCategory for the item |
| itemDescription | string Nullable the description for an item |
| itemReference | string Nullable extra unique reference of the item (PLU) |
| providerInstanceId | string <uuid> Nullable provider activation owning this mapping; omit for the legacy provider-wide mapping |
[- {
- "providerItemId": "string",
- "providerId": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabelsIdConcat": "string",
- "itemName": "string",
- "itemCategory": "string",
- "itemSubCategory": "string",
- "itemDescription": "string",
- "itemReference": "string",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86"
}
][- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "providerItemId": "string",
- "providerId": "string",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabelsIdConcat": "string",
- "itemName": "string",
- "itemCategory": "string",
- "itemSubCategory": "string",
- "itemDescription": "string",
- "itemReference": "string"
}
]Returns stored activation-scoped ProviderMappingItems for the authenticated Site. Without provider filters, includes all activations. providerId filters across all activations of that provider; providerInstanceId selects one activation. Both filters intersect when supplied. Queries never merge or migrate legacy MappingItem records. GET /pos/mappings remains unchanged. Old legacy-backed cursors must be restarted without a cursor. This endpoint includes relationships, lifecycle metadata and item-level raw provider data.
raw is provider-specific and may change without notice. It contains only the item-relevant provider entity, never provider credentials or the complete unrelated menu response.
Disabled records are included by default so clients can update local caches. Use activeOnly=true to return records whose disabledAt is absent or null. The derived enabled property follows the same rule. Because limit bounds evaluated DynamoDB records before filters are applied, filtered pages may contain fewer items than the requested limit; continue while nextCursor is present. Every page includes itemCount, the total number of ProviderMappingItems matching the current filters across all cursor pages.
WebSocket action: GetMappingItemCatalog
| limit | integer [ 1 .. 100 ] Default: 50 Maximum number of evaluated MappingItems. Values are clamped to 1 through 100. |
| cursor | string Opaque nextCursor from the previous response. |
| providerId | string <uuid> Optional provider filter. |
| providerInstanceId | string <uuid> Optional provider activation filter. Omit to include all matching activations of the authenticated Site. |
| activeOnly | boolean Default: false When true, exclude MappingItems whose disabledAt contains a timestamp. Missing and null disabledAt values are active. |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "items": [
- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "providerInstanceId_providerItemId": "string",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "providerItemId": "string",
- "providerId": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabelsIdConcat": "string",
- "itemName": "string",
- "itemCategory": "string",
- "itemSubCategory": "string",
- "itemDescription": "string",
- "itemReference": "string",
- "categoryId": "string",
- "available": true,
- "type": "product",
- "sku": "string",
- "plu": "string",
- "allergens": [
- "string"
], - "labels": [
- "string"
], - "sortIndex": 0,
- "relationships": [
- {
- "relationType": "category",
- "relatedItemId": "string",
- "relatedItemName": "string",
- "providerRelationId": "string",
- "minSelections": 0,
- "maxSelections": 0,
- "defaultSelected": true,
- "quantity": 0,
- "priceDelta": {
- "amount": 0,
- "currency": "string"
}, - "sortIndex": 0
}
], - "raw": { },
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "providerCreatedAt": "2019-08-24T14:15:22Z",
- "providerUpdatedAt": "2019-08-24T14:15:22Z",
- "lastImportedAt": "2019-08-24T14:15:22Z",
- "lastSeenAt": "2019-08-24T14:15:22Z",
- "disabledAt": "2019-08-24T14:15:22Z",
- "enabled": true
}
], - "itemCount": 0,
- "nextCursor": "string"
}A complete successful synchronization updates lastSeenAt, disables missing records and reactivates returned records. Failed, interrupted, pending, timed-out or otherwise incomplete imports never disable records.
WebSocket action: ImportMappingItems
| providerId required | string <uuid> internal ID of the provider |
| providerInstanceId | string <uuid> Provider activation to import. Required when the provider is configured more than once. |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
[- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "providerItemId": "string",
- "providerId": "string",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "posItemId": "string",
- "posItemLabelsIdConcat": "string",
- "itemName": "string",
- "itemCategory": "string",
- "itemSubCategory": "string",
- "itemDescription": "string",
- "itemReference": "string"
}
]Returns the configured preparation time and ordering activation state for the authenticated POS restaurant, plus a read-only providerDetails list of configured provider instances and their stored connection verification status. No provider check is triggered and no credentials are returned.
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "defaultPreparationTime": {
- "preparationTime": 0,
- "drivingTime": 0,
- "deliverTime": 0
}, - "orderingActivated": true,
- "orderingDeactivatedUntil": "2019-08-24T14:15:22Z",
- "providerDetails": [
- {
- "providerId": "string",
- "providerInstanceId": "string",
- "providerName": "string",
- "status": "pending"
}
]
}WebSocket action: SetSiteSpecs
This action allows to update/set specifications for a POS restaurant.
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Object for Pos SiteSpecs
object Nullable keeps track of the default preparation times of the restaurant | |
| orderingActivated | boolean Nullable Default: true enables ordering for this restaurant |
| orderingDeactivatedUntil | string <date-time> Nullable timestamp until which ordering is paused; omitting the field while setting orderingActivated to false defaults to 24 hours, an explicit null pauses indefinitely, and existing records without the field are treated as active for backward compatibility |
{- "defaultPreparationTime": {
- "preparationTime": 0,
- "drivingTime": 0,
- "deliverTime": 0
}, - "orderingActivated": true,
- "orderingDeactivatedUntil": "2019-08-24T14:15:22Z"
}{- "success": "string",
- "venueStatus": {
- "success": true,
- "partial": true,
- "successful": 0,
- "failed": 0,
- "results": [
- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86",
- "restaurantId": "string",
- "operation": "status",
- "success": true,
- "error": {
- "message": "string",
- "statusCode": 0,
- "code": "string"
}
}
]
}
}Shared menu fulfillment is configured once per activation through menuTypes: a nonempty array overrides POS-menu types, [] inherits them and provider fallback, and omission on save preserves the current selection. Full uploads and item updates share this setting. Wolt/foodora support delivery, pickup and inHouse; JET supports delivery/pickup; Uber supports delivery or delivery+pickup with one common catalog; Deliveroo remains a shared catalog. This setting does not activate provider services or remove old remote menus. Note: When a provider is activated with menu synchronization enabled, Mergeport automatically creates a default channel configuration with provider-specific settings. In most cases, POS partners do not need to integrate with the channel endpoints. The configuration can also be adjusted directly in the Mergeport Controller.
Returns the editable channel configuration for supported ordering providers configured on the authenticated site, keyed by provider-instance UUID. The first activation of a provider keeps the provider ID as its instance ID for backward compatibility; additional activations receive their own IDs and therefore independent channel configurations. Entries without persisted settings are returned with virtual defaults such as syncMode: off. availableMethods describes the provider API functions and their selectable POS fields, currentSetup contains the persisted field mappings, currentOverrides contains optional per-record data overrides, overrideModes describes supported global transformations, and syncSpecs contains both configured triggers and operational status. Persisted ProviderChannel records are combined with the provider's current API setup so newly introduced optional fields can appear without discarding existing selections.
A channel maps canonical POS data such as PosItem, PosCategory and PosMenu fields to a provider request payload. Site-derived fields such as the standard language are applied automatically and are not presented as configurable mappings. Independent channel features are announced in availableMethods.<apiFunction>.features. Availability supports inherit, custom and disabled modes through syncSpecs.<apiFunction>.availabilitySet. Wolt receives effective category availability including nested subcategories, Uber Eats and JET Connect receive deterministic menu groups for categories with identical effective schedules, and Foodora receives menu-level catalog schedule entries. Supported assignment targets are announced per method; Foodora supports menus only.
Reading this endpoint does not perform a provider synchronization.
WebSocket action: GetProviderChannel
| Authorization required | string <uuid> static apiKey provided by Mergeport |
{- "d7ac9e8e-1176-4844-aa28-4f856c8b325b": {
- "availableMethods": {
- "createOrReplaceMenu": {
- "title": "Create or replace menu",
- "tableNames": [
- "PosCategory",
- "PosMenu",
- "PosItem"
], - "features": {
- "availabilitySet": {
- "resource": "PosAvailability",
- "targets": [
- "menus",
- "categories"
], - "modes": [
- "inherit",
- "custom",
- "disabled"
], - "defaultMode": "inherit"
}
}
}
}, - "currentSetup": {
- "createOrReplaceMenu": {
- "PosItem": [
- {
- "fieldPath": "id",
- "apiPath": "categories.items.external_data"
}
]
}
}, - "overrideModes": {
- "replace": {
- "default": true,
- "type": "any",
- "description": "replace any value with the same type"
}
}, - "syncSpecs": {
- "createOrReplaceMenu": {
- "syncMode": "manually",
- "syncTimes": [ ],
- "availabilitySet": {
- "mode": "custom",
- "menus": [
- {
- "id": "main",
- "availabilityIds": [
- "delivery-hours"
]
}
], - "categories": [
- {
- "id": "lunch",
- "availabilityIds": [
- "weekday-lunch"
]
}
]
}
}
}
}
}Shared menu fulfillment is configured once per activation through menuTypes: a nonempty array overrides POS-menu types, [] inherits them and provider fallback, and omission on save preserves the current selection. Full uploads and item updates share this setting. Wolt/foodora support delivery, pickup and inHouse; JET supports delivery/pickup; Uber supports delivery or delivery+pickup with one common catalog; Deliveroo remains a shared catalog. This setting does not activate provider services or remove old remote menus. Creates or updates channel configurations for supported ordering providers on the authenticated site. The request is keyed by provider-instance UUID; the first activation may use the provider ID for backward compatibility, while every additional activation is configured independently. For each selected provider API function, currentSetup chooses canonical POS source fields, while currentOverrides supplies optional per-record values and field mappings may contain a supported globalOverride. Site-derived fields such as the standard language are applied automatically. Mergeport persists one ProviderChannel record per provider instance and API function.
syncSpecs controls manual, scheduled and on-change synchronization. Its optional availabilitySet supports inherit, custom and disabled modes for that channel function only; it neither creates schedules nor changes canonical POS records. In custom mode, unlisted records retain their canonical availabilityIds, and unknown menu, category or availability IDs stop synchronization before the provider is contacted. There is no shop-specific dimension in this version. Wolt on-change synchronization is coalesced per venue and API function: POS changes are queued, and the scheduler sends the latest canonical state once the provider-specific request window opens. Further changes replace the pending revision instead of producing additional provider requests. After a failed Wolt attempt, the pending state is retained and the retry window increases from one to fifteen minutes; later POS changes are still merged without shortening that backoff.
Required provider fields use their documented defaults when available. Existing stored per-record overrides are preserved unless the submitted configuration replaces them. Providers not configured on the site and providers without channel support are ignored. Channel support is currently available for Wolt, JET Connect, Uber Eats and Foodora.
This operation stores mapping and synchronization configuration only; it does not upload menu data or contact the provider. Provider validation failures during an automatic synchronization can suspend that channel while preserving its previous scheduling settings. Operational fields returned in syncSpecs, such as lastError, syncStatus, pending and nextAttemptAt, should be treated as server-managed state.
POS option groups in optionsList.availableChoices are preferred when present. Legacy embedded options and parent-linked option items remain supported for backward compatibility. Images continue to come from the POS item's imgUrl; this endpoint does not upload image binaries.
WebSocket action: SetProviderChannel
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Provider channel mappings, sync settings and optional channel-specific availability assignments.
object |
{- "d7ac9e8e-1176-4844-aa28-4f856c8b325b": {
- "currentSetup": {
- "createOrReplaceMenu": {
- "PosMenu": [
- {
- "fieldPath": "id",
- "apiPath": "id"
}
], - "PosItem": [
- {
- "fieldPath": "id",
- "apiPath": "categories.items.external_data"
}
]
}, - "updateMenuItems": {
- "PosItem": [
- {
- "fieldPath": "id",
- "apiPath": "data.gtin"
}, - {
- "fieldPath": "price.amount",
- "globalOverride": {
- "mode": "addPercent",
- "value": 5
}
}
]
}
}, - "syncSpecs": {
- "createOrReplaceMenu": {
- "syncMode": "manually",
- "availabilitySet": {
- "mode": "custom",
- "menus": [
- {
- "id": "main",
- "availabilityIds": [
- "delivery-hours"
]
}
], - "categories": [
- {
- "id": "lunch",
- "availabilityIds": [
- "weekday-lunch"
]
}
]
}
}, - "updateMenuItems": {
- "syncMode": "onChange"
}
}
}
}"OK"Runs a POS command for the site identified by the submitted site API key. A submitted siteId must match the authenticated site.
POST /pos/execute/doChannelSync with Authorization:
This is a manual synchronization of the current POS catalog using the saved channel mappings, not creation of a channel. First configure the provider and its channels through /pos/channels. The optional apiFunction query parameter selects one configured channel function (for example updateMenuItems); omit it to run all configured functions within the selected provider scope. It is an explicit manual trigger, independent of scheduled/onChange timing. A successful response is not proof of asynchronous provider publication. Provider/configuration errors are returned as CHANNEL_PROVIDER_ERROR with phase, providerId, apiFunction and, when available, upstream data. A failed multi-method run can have already synchronized earlier methods: do not blindly repeat full-menu uploads.
The doProviderSync command attempts every configured provider and reports partial failures after all providers have been attempted.
WebSocket action: doPosCommand. Example: {"action":"doPosCommand","command":"doChannelSync","data":{"providerId":"953ac550-2653-48e3-8d04-34c1c3b27041"}}.
Developer test orders are documented separately under Orders.
| apiFunction | string non-empty Example: apiFunction=updateMenuItems For doChannelSync only: run one configured channel function, for example updateMenuItems for a Wolt item patch or createOrReplaceMenu for a full menu replacement. Omit to retain the existing all-functions behavior. The providerId and providerInstanceId filters still apply. An empty value or a function not configured within that scope returns 400. This manual request is immediate and does not enter the automatic on-change retry queue. |
| providerId | string <uuid> Optional provider-type filter for doChannelSync. |
| providerInstanceId | string <uuid> Optional activation filter for doChannelSync. Use the providerInstanceId returned by /pos/channels. |
| siteId | string <uuid> Normally omit: inferred from the authenticated site API key. If supplied it must match that Site. |
| Authorization required | string <uuid> static apiKey provided by Mergeport |
Returns all reusable weekly availability schedules stored for the authenticated site. Schedules are referenced through availabilityIds on POS menus and categories; item-level references are not supported in this version. Multiple referenced schedules are combined as a union. An absent or empty availabilityIds property means unrestricted availability.
Effective category availability follows this precedence: the category's own references, then references inherited from its parent category, then references on the containing menu. Wolt preserves this effective schedule on nested subcategories. Foodora represents menu assignments as catalog ScheduleEntry records and does not support category assignments through this integration.
WebSocket action: GetPosAvailabilities
| Authorization required | string <uuid> |
[- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "timezone": "string",
- "weeklyAvailability": [
- {
- "day": "monday",
- "periods": [
- {
- "start": "string",
- "end": "string"
}
]
}
]
}
]Creates or updates reusable weekly availability schedules for the authenticated site. The site ID is taken from the authorization context and must not be supplied by the client. Existing schedules with the same id are replaced; schedules omitted from the request are not deleted.
Each schedule requires a valid IANA timezone and at least one day with at least one period. Days must be unique within a schedule. Times use HH:mm; 24:00 is accepted only as an end time. Periods must have start < end, must not overlap and must be split across two days when they cross midnight. Adjacent periods and unions of multiple referenced schedules are normalized deterministically.
Saving a schedule does not start a provider-channel synchronization.
WebSocket action: SetPosAvailabilities
| Authorization required | string <uuid> |
Array of reusable POS availability schedules
| id required | string Stable POS-defined schedule ID referenced by PosMenu.availabilityIds and PosCategory.availabilityIds. |
object Nullable Optional localized display name used when Mergeport derives provider menu names for grouped schedules, represented as an associative array of names for ISO-639-1 language codes. | |
| timezone required | string Required IANA timezone used to interpret the local weekly periods, for example Europe/Vienna. |
required | Array of objects non-empty Available local-time periods grouped by weekday. A day may occur only once; omitted days are unavailable. |
[- {
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "timezone": "string",
- "weeklyAvailability": [
- {
- "day": "monday",
- "periods": [
- {
- "start": "string",
- "end": "string"
}
]
}
]
}
][- {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "timezone": "string",
- "weeklyAvailability": [
- {
- "day": "monday",
- "periods": [
- {
- "start": "string",
- "end": "string"
}
]
}
]
}
]Returns one reusable availability schedule belonging to the authenticated site. The id is the POS-defined stable reference used in PosMenu.availabilityIds and PosCategory.availabilityIds.
WebSocket action: GetAvailability
| id required | string |
| Authorization required | string <uuid> |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "timezone": "string",
- "weeklyAvailability": [
- {
- "day": "monday",
- "periods": [
- {
- "start": "string",
- "end": "string"
}
]
}
]
}Deletes one reusable availability schedule belonging to the authenticated site. This operation does not remove its ID from existing menus or categories. Any remaining reference becomes invalid and a later channel synchronization fails validation before contacting the provider until the reference is removed or the schedule is recreated.
WebSocket action: DeletePosAvailability
| id required | string |
| Authorization required | string <uuid> |
{- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "timezone": "string",
- "weeklyAvailability": [
- {
- "day": "monday",
- "periods": [
- {
- "start": "string",
- "end": "string"
}
]
}
]
}Site-scoped delivery jobs alongside the independent POS order flow. Wolt Drive supports quotes, booking and cancellation within its cancellation window; merchant webhook registration is manual. Optional automatic booking and cancellation monitoring require explicit Site fleet automation settings. Neutral HTTPS webhook fleets support direct dispatch: sign with the fleet dispatchSecret; callbacks use the per-delivery callback.signingSecret. In both directions use X-Mergeport-Timestamp (Unix seconds) and X-Mergeport-Signature (lowercase hex HMAC-SHA256 of timestamp + dot + exact UTF-8 JSON body); check a 300-second window. Transport acknowledgement is not business acceptance. Deduplicate using deliveryId and Idempotency-Key. Timeouts are ambiguous; never create a second job. Fleet status does not change POS/order status. REST only. The dedicated Delivery fleet providers section in the Main SP/provider documentation describes the neutral receiver and callback contract; POS configuration and booking APIs remain here.
Array of objects | |
object Outstanding CASH payments only, in cents/currency. No delivery fee is added. Absent when nothing is to be collected. cashToExpect is optional announced tender, not a second payment; only sent when unambiguous and at least amountToCollect. | |
| quoteId | string External offer ID; only in quoted bookings. |
object (DeliveryPrice) Amount in minor currency units. | |
| version required | string Value: "1" |
| type required | string Value: "delivery.requested" |
| deliveryId required | string <uuid> |
| siteId required | string <uuid> |
| fleetId required | string <uuid> |
| orderId required | string <uuid> |
| orderReference required | string |
required | object (DeliveryPoint) |
required | object (DeliveryPoint) |
| readyAt required | string <date-time> |
| parcelCount | integer |
required | object |
{- "items": [
- {
- "id": "string",
- "name": "string",
- "quantity": 0,
- "unitPrice": {
- "amount": 0,
- "currency": "string"
}
}
], - "cash": {
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "cashToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "quoteId": "string",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "version": "1",
- "type": "delivery.requested",
- "deliveryId": "73dc828d-801d-4d29-b7e4-e046662a5901",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "orderReference": "string",
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "dropoff": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 0,
}Enabled, implemented fleet definitions analogous to Provider/POS definitions. Credentials and pickup configuration belong to Site.deliveryFleetDetails.
| Authorization required | string |
{- "items": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "key": "webhook",
- "name": "string",
- "description": "string",
- "enabled": true,
- "capabilities": {
- "directBooking": true,
- "quotes": true,
- "cancellation": true,
- "tracking": true
}, - "accessDetails": [
- {
- "name": "string",
- "type": "string",
- "required": true,
- "min": 0,
- "max": 0,
- "unit": "string",
- "description": "string"
}
]
}
]
}List activations stored in Site.deliveryFleetDetails, without signing secrets. The list revision is required for replacing deliveryFleetDetails through PATCH /admin/site/{id}. REST only.
| Authorization required | string |
{- "items": [
- {
- "bookingMode": "direct",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "name": "string",
- "enabled": true,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "accessDetails": {
- "merchantId": "string",
- "venueId": "string",
- "apiKey": "string",
- "webhookSecret": "string",
- "inDevelopment": true,
- "collectOnDelivery": true,
- "recipientDeliveryFeePercent": 0,
- "dispatchSecret": "string"
}, - "revision": 1,
- "updatedAt": "2019-08-24T14:15:22Z",
- "automation": {
- "enabled": true,
- "trigger": "acceptedByPOS",
- "cancelOnOrderCancellation": true,
- "merchantDeliveryConfirmed": true,
- "allowUnpricedDirectBooking": true,
- "maxPrice": {
- "amount": 0,
- "currency": "string"
}, - "filter": {
- "mode": "all",
- "providers": [
- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86"
}
]
}, - "timing": {
- "fallbackPreparationMinutes": 1
}, - "parcelPolicy": {
- "mode": "fixed",
- "count": 1,
- "unitsPerParcel": 1,
- "minimum": 1,
- "maximum": 1
}
}
}
], - "revision": 0
}Create a Site.deliveryFleetDetails activation referencing a central deliveryFleetId. Settings and server-generated credentials belong to the Site; no site-specific DeliveryFleet table row is created. REST only.
| Authorization required | string |
| bookingMode | string Enum: "direct" "quote" Neutral webhook activation only. Missing means direct. Quote mode requires definition capabilities.quotes=true and an explicitly confirmed offer. Omission on update preserves the existing mode. |
object Wolt Drive credentials. Omitted credentials are preserved on update. webhookSecret is optional for configuration and quotes, required before booking; it is the merchant-wide HS256 client_secret registered with Wolt. Empty string clears it. No webhook is registered by saving a Site. | |
| name required | string [ 1 .. 200 ] characters \S |
| enabled required | boolean |
| webhookUrl | string <uri> <= 2000 characters |
required | object (DeliveryPoint) |
| revision | integer >= 1 |
| deliveryFleetId required | string <uuid> ID of the central DeliveryFleet definition. |
object (DeliveryAutomationConfig) Opt-in automatic booking after persisted acceptedByPOS. One automatic fleet per Site. Wolt and neutral quote mode require maxPrice; neutral direct mode requires explicit unpriced consent and no maxPrice. parcelPolicy is optional; omission sends no neutral parcelCount. |
{- "bookingMode": "direct",
- "accessDetails": {
- "merchantId": "string",
- "venueId": "string",
- "apiKey": "string",
- "webhookSecret": "string",
- "inDevelopment": true,
- "collectOnDelivery": true,
- "recipientDeliveryFeePercent": 0
}, - "name": "string",
- "enabled": true,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "revision": 1,
- "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "automation": {
- "enabled": true,
- "trigger": "acceptedByPOS",
- "cancelOnOrderCancellation": true,
- "merchantDeliveryConfirmed": true,
- "allowUnpricedDirectBooking": true,
- "maxPrice": {
- "amount": 0,
- "currency": "string"
}, - "filter": {
- "mode": "all",
- "providers": [
- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86"
}
]
}, - "timing": {
- "fallbackPreparationMinutes": 1
}, - "parcelPolicy": {
- "mode": "fixed",
- "count": 1,
- "unitsPerParcel": 1,
- "minimum": 1,
- "maximum": 1
}
}
}{- "bookingMode": "direct",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "name": "string",
- "enabled": true,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "accessDetails": {
- "merchantId": "string",
- "venueId": "string",
- "apiKey": "string",
- "webhookSecret": "string",
- "inDevelopment": true,
- "collectOnDelivery": true,
- "recipientDeliveryFeePercent": 0,
- "dispatchSecret": "string"
}, - "revision": 1,
- "updatedAt": "2019-08-24T14:15:22Z",
- "automation": {
- "enabled": true,
- "trigger": "acceptedByPOS",
- "cancelOnOrderCancellation": true,
- "merchantDeliveryConfirmed": true,
- "allowUnpricedDirectBooking": true,
- "maxPrice": {
- "amount": 0,
- "currency": "string"
}, - "filter": {
- "mode": "all",
- "providers": [
- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86"
}
]
}, - "timing": {
- "fallbackPreparationMinutes": 1
}, - "parcelPolicy": {
- "mode": "fixed",
- "count": 1,
- "unitsPerParcel": 1,
- "minimum": 1,
- "maximum": 1
}
}
}Manual delivery fleet API. REST only; site-scoped and independent of POS order status. See the Delivery Fleets guide.
| fleetId required | string <uuid> |
| Authorization required | string |
| bookingMode | string Enum: "direct" "quote" Neutral webhook activation only. Missing means direct. Quote mode requires definition capabilities.quotes=true and an explicitly confirmed offer. Omission on update preserves the existing mode. |
object Wolt Drive credentials. Omitted credentials are preserved on update. webhookSecret is optional for configuration and quotes, required before booking; it is the merchant-wide HS256 client_secret registered with Wolt. Empty string clears it. No webhook is registered by saving a Site. | |
| name required | string [ 1 .. 200 ] characters \S |
| enabled required | boolean |
| webhookUrl | string <uri> <= 2000 characters |
required | object (DeliveryPoint) |
| revision | integer >= 1 |
| deliveryFleetId required | string <uuid> ID of the central DeliveryFleet definition. |
object (DeliveryAutomationConfig) Opt-in automatic booking after persisted acceptedByPOS. One automatic fleet per Site. Wolt and neutral quote mode require maxPrice; neutral direct mode requires explicit unpriced consent and no maxPrice. parcelPolicy is optional; omission sends no neutral parcelCount. |
{- "bookingMode": "direct",
- "accessDetails": {
- "merchantId": "string",
- "venueId": "string",
- "apiKey": "string",
- "webhookSecret": "string",
- "inDevelopment": true,
- "collectOnDelivery": true,
- "recipientDeliveryFeePercent": 0
}, - "name": "string",
- "enabled": true,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "revision": 1,
- "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "automation": {
- "enabled": true,
- "trigger": "acceptedByPOS",
- "cancelOnOrderCancellation": true,
- "merchantDeliveryConfirmed": true,
- "allowUnpricedDirectBooking": true,
- "maxPrice": {
- "amount": 0,
- "currency": "string"
}, - "filter": {
- "mode": "all",
- "providers": [
- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86"
}
]
}, - "timing": {
- "fallbackPreparationMinutes": 1
}, - "parcelPolicy": {
- "mode": "fixed",
- "count": 1,
- "unitsPerParcel": 1,
- "minimum": 1,
- "maximum": 1
}
}
}{- "bookingMode": "direct",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "name": "string",
- "enabled": true,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "accessDetails": {
- "merchantId": "string",
- "venueId": "string",
- "apiKey": "string",
- "webhookSecret": "string",
- "inDevelopment": true,
- "collectOnDelivery": true,
- "recipientDeliveryFeePercent": 0,
- "dispatchSecret": "string"
}, - "revision": 1,
- "updatedAt": "2019-08-24T14:15:22Z",
- "automation": {
- "enabled": true,
- "trigger": "acceptedByPOS",
- "cancelOnOrderCancellation": true,
- "merchantDeliveryConfirmed": true,
- "allowUnpricedDirectBooking": true,
- "maxPrice": {
- "amount": 0,
- "currency": "string"
}, - "filter": {
- "mode": "all",
- "providers": [
- {
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "providerInstanceId": "8f22e268-6d7e-4c7b-ad52-4cbec898ef86"
}
]
}, - "timing": {
- "fallbackPreparationMinutes": 1
}, - "parcelPolicy": {
- "mode": "fixed",
- "count": 1,
- "unitsPerParcel": 1,
- "minimum": 1,
- "maximum": 1
}
}
}REST only. Neutral webhook fleets with bookingMode=quote and quotes capability send delivery.quote_requested; an offer reserves no delivery. Confirm its internal quoteId and priceConfirmed with unchanged data before expiry. Optional parcelCount must match the offer; cash contains outstanding CASH amounts without delivery fees. Wolt Drive: merchant-managed orders (prepaid by default; optional configured cash collection) ready within one hour. Returns a binding expiring offer; does not book. Parcels are derived from stored main OrderItems: quantity, name and optional unit price; child items and notes are excluded. No bag_count is sent. The subsequent CreateDelivery must include quoteId and priceConfirmed=true with unchanged order/main items/fleet/readyAt. parcelCount is optional and ignored for Wolt Drive. Missing or invalid main items return INVALID_ORDER_ITEMS. Quotes issued before item-based parcels require a new quote. Cash collection and the recipient delivery-fee percentage apply only to orders with a positive outstanding CASH payment. Prepaid/zero-cash orders omit cash in both quote and booking, even when collection is enabled. Re-request older cash quotes for those orders. cashCollection, when present, shows the recipient collection breakdown; confirm it along with the price. This request does not book or cancel a delivery. Wolt Drive request failures retain HTTP 502 and WOLT_DRIVE_REQUEST_FAILED. The message identifies quote/booking/cancellation, upstream HTTP status or timeout/network failure, a provider error code (including sanitized unknown codes), safe validation field paths and a diagnostic ID for support. Quote errors also identify the calculation step. Provider detail text is bounded and sanitized; known request values, recognizable contact details and credentials are redacted. Raw objects and HTML are omitted. No automatic retry is added.
| Authorization required | string |
| fleetId required | string <uuid> |
| orderId required | string <uuid> |
| readyAt required | string <date-time> |
| parcelCount | integer [ 1 .. 100 ] Optional neutral package count; use the same value or omission when confirming. Ignored by Wolt Drive. |
| merchantDeliveryConfirmed required | boolean Value: true |
{- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 1,
- "merchantDeliveryConfirmed": true
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "provider": "string",
- "expiresAt": "2019-08-24T14:15:22Z",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "cashCollection": {
- "orderAmount": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFee": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFeePercent": 0,
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "amountToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "cash": {
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "cashToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "pickupEtaMinutes": 0,
- "dropoffEtaMinutes": 0,
- "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 0
}REST only. Verify token as HS256 JWT with the snapshotted merchant webhook client_secret. Merchant and venue must match the delivery. merchant_order_reference_id contains siteId:deliveryId for lookup only; no updates occur before signature verification. Duplicate, reordered and unsupported authenticated events are acknowledged without status regression. No automatic webhook registration or StandardOrder changes.
| merchantId required | string |
| token required | string <= 32000 characters |
{- "token": "string"
}Manually request merchant-managed delivery for an existing order. Explicit confirmation is required. One delivery per order (deliveryId equals the internal orderId); identical requests return the existing delivery, conflicting requests return 409. No POS/order-state changes. REST only.
| Authorization required | string |
| quoteId | string <uuid> Required for Wolt Drive and neutral bookingMode quote. Use the internal ID returned by MERGEPORT, not the external fleet quote ID. Quote is bound to this order, fleet, addresses, items, collection amounts and readyAt. Changes require a new quote. |
| priceConfirmed | boolean Value: true Explicit approval of the returned quote price; required with quoteId. |
| fleetId required | string <uuid> |
| orderId required | string <uuid> |
| readyAt required | string <date-time> |
| parcelCount | integer [ 1 .. 100 ] Optional package count for neutral fleets. Omission does not infer a count; items are sent separately. Ignored for Wolt Drive, whose parcels use stored main-item quantities. |
| merchantDeliveryConfirmed required | boolean Value: true |
{- "quoteId": "826e5192-f8c6-4e24-aab3-3910e46c52b7",
- "priceConfirmed": true,
- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 1,
- "merchantDeliveryConfirmed": true
}{- "items": [
- {
- "id": "string",
- "name": "string",
- "quantity": 0,
- "unitPrice": {
- "amount": 0,
- "currency": "string"
}
}
], - "courierLocation": {
- "latitude": -90,
- "longitude": -180,
- "recordedAt": "2019-08-24T14:15:22Z"
}, - "canCancel": true,
- "cancellation": {
- "requestId": "string",
- "status": "requested",
- "reason": "string",
- "requestedAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "providerHttpStatus": 0
}, - "quoteId": "826e5192-f8c6-4e24-aab3-3910e46c52b7",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "cashCollection": {
- "orderAmount": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFee": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFeePercent": 0,
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "amountToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "cash": {
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "cashToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "providerStatus": "string",
- "pickupEta": "2019-08-24T14:15:22Z",
- "dropoffEta": "2019-08-24T14:15:22Z",
- "driveEventAt": "2019-08-24T14:15:22Z",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "provider": "webhook",
- "orderReference": "string",
- "status": "requested",
- "transportStatus": "sending",
- "attemptCount": 0,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "dropoff": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 0,
- "callbackUrl": "string",
- "revision": 0,
- "sequence": 0,
- "externalDeliveryId": "string",
- "trackingUrl": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "history": [
- {
- "eventType": "string",
- "eventId": "string",
- "sequence": 0,
- "status": "string",
- "occurredAt": "2019-08-24T14:15:22Z"
}
], - "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "bookingSource": "automation",
- "cancelOnOrderCancellation": true
}Manual delivery fleet API. REST only; site-scoped and independent of POS order status. See the Delivery Fleets guide.
| deliveryId required | string <uuid> |
| Authorization required | string |
{- "items": [
- {
- "id": "string",
- "name": "string",
- "quantity": 0,
- "unitPrice": {
- "amount": 0,
- "currency": "string"
}
}
], - "courierLocation": {
- "latitude": -90,
- "longitude": -180,
- "recordedAt": "2019-08-24T14:15:22Z"
}, - "canCancel": true,
- "cancellation": {
- "requestId": "string",
- "status": "requested",
- "reason": "string",
- "requestedAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "providerHttpStatus": 0
}, - "quoteId": "826e5192-f8c6-4e24-aab3-3910e46c52b7",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "cashCollection": {
- "orderAmount": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFee": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFeePercent": 0,
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "amountToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "cash": {
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "cashToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "providerStatus": "string",
- "pickupEta": "2019-08-24T14:15:22Z",
- "dropoffEta": "2019-08-24T14:15:22Z",
- "driveEventAt": "2019-08-24T14:15:22Z",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "provider": "webhook",
- "orderReference": "string",
- "status": "requested",
- "transportStatus": "sending",
- "attemptCount": 0,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "dropoff": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 0,
- "callbackUrl": "string",
- "revision": 0,
- "sequence": 0,
- "externalDeliveryId": "string",
- "trackingUrl": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "history": [
- {
- "eventType": "string",
- "eventId": "string",
- "sequence": 0,
- "status": "string",
- "occurredAt": "2019-08-24T14:15:22Z"
}
], - "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "bookingSource": "automation",
- "cancelOnOrderCancellation": true
}REST only. Requires explicit confirmation and reason. Does not change StandardOrder. Wolt reference and original account configuration are required. A timeout persists cancellation.status=unknown, blocks automatic retry and never permits rebooking. Inspect cancellation.status in the response: HTTP 200 alone is not proof of cancellation. Wolt refusals leave delivery status unchanged.
| deliveryId required | string <uuid> |
| Authorization required | string |
| reason required | string [ 1 .. 500 ] characters Reason sent to Wolt. Do not include sensitive customer details. |
| cancellationConfirmed required | boolean Value: true Explicit manual confirmation; never inferred from a StandardOrder cancellation. |
{- "reason": "string",
- "cancellationConfirmed": true
}{- "items": [
- {
- "id": "string",
- "name": "string",
- "quantity": 0,
- "unitPrice": {
- "amount": 0,
- "currency": "string"
}
}
], - "courierLocation": {
- "latitude": -90,
- "longitude": -180,
- "recordedAt": "2019-08-24T14:15:22Z"
}, - "canCancel": true,
- "cancellation": {
- "requestId": "string",
- "status": "requested",
- "reason": "string",
- "requestedAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "providerHttpStatus": 0
}, - "quoteId": "826e5192-f8c6-4e24-aab3-3910e46c52b7",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "cashCollection": {
- "orderAmount": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFee": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFeePercent": 0,
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "amountToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "cash": {
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "cashToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "providerStatus": "string",
- "pickupEta": "2019-08-24T14:15:22Z",
- "dropoffEta": "2019-08-24T14:15:22Z",
- "driveEventAt": "2019-08-24T14:15:22Z",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "provider": "webhook",
- "orderReference": "string",
- "status": "requested",
- "transportStatus": "sending",
- "attemptCount": 0,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "dropoff": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 0,
- "callbackUrl": "string",
- "revision": 0,
- "sequence": 0,
- "externalDeliveryId": "string",
- "trackingUrl": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "history": [
- {
- "eventType": "string",
- "eventId": "string",
- "sequence": 0,
- "status": "string",
- "occurredAt": "2019-08-24T14:15:22Z"
}
], - "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "bookingSource": "automation",
- "cancelOnOrderCancellation": true
}Manual delivery fleet API. REST only; site-scoped and independent of POS order status. See the Delivery Fleets guide.
| deliveryId required | string <uuid> |
| Authorization required | string |
{- "items": [
- {
- "id": "string",
- "name": "string",
- "quantity": 0,
- "unitPrice": {
- "amount": 0,
- "currency": "string"
}
}
], - "courierLocation": {
- "latitude": -90,
- "longitude": -180,
- "recordedAt": "2019-08-24T14:15:22Z"
}, - "canCancel": true,
- "cancellation": {
- "requestId": "string",
- "status": "requested",
- "reason": "string",
- "requestedAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "providerHttpStatus": 0
}, - "quoteId": "826e5192-f8c6-4e24-aab3-3910e46c52b7",
- "price": {
- "amount": 0,
- "currency": "string"
}, - "cashCollection": {
- "orderAmount": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFee": {
- "amount": 0,
- "currency": "string"
}, - "recipientDeliveryFeePercent": 0,
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "amountToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "cash": {
- "amountToCollect": {
- "amount": 0,
- "currency": "string"
}, - "cashToExpect": {
- "amount": 0,
- "currency": "string"
}
}, - "providerStatus": "string",
- "pickupEta": "2019-08-24T14:15:22Z",
- "dropoffEta": "2019-08-24T14:15:22Z",
- "driveEventAt": "2019-08-24T14:15:22Z",
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",
- "fleetId": "86b82934-5185-41da-b902-ab94a9638892",
- "provider": "webhook",
- "orderReference": "string",
- "status": "requested",
- "transportStatus": "sending",
- "attemptCount": 0,
- "pickup": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "dropoff": {
- "name": "string",
- "phone": "string",
- "address": "string",
- "instructions": "string"
}, - "readyAt": "2019-08-24T14:15:22Z",
- "parcelCount": 0,
- "callbackUrl": "string",
- "revision": 0,
- "sequence": 0,
- "externalDeliveryId": "string",
- "trackingUrl": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "history": [
- {
- "eventType": "string",
- "eventId": "string",
- "sequence": 0,
- "status": "string",
- "occurredAt": "2019-08-24T14:15:22Z"
}
], - "deliveryFleetId": "7d0b5df2-cedc-4b95-9529-7009070191ef",
- "bookingSource": "automation",
- "cancelOnOrderCancellation": true
}Verify X-Mergeport-Signature = lowercase hex HMAC-SHA256(callback.signingSecret, timestamp + '.' + raw JSON body). X-Mergeport-Timestamp is Unix seconds, maximum clock skew 300 seconds. Sequence must increase per delivery. Older/duplicate sequences return 200 stale=true; concurrent updates return 409 and should be retried unchanged. No POS/order-state changes. REST only.
| siteId required | string <uuid> |
| deliveryId required | string <uuid> |
| X-Mergeport-Timestamp required | string |
| X-Mergeport-Signature required | string |
object Optional latest courier position in WGS84 decimal degrees, not a route history. Removed when the delivery reaches a terminal status. Frontends must show recordedAt and treat old positions as stale. | |
| eventId required | string [ 1 .. 100 ] characters |
| sequence required | integer [ 1 .. 2147483647 ] |
| status required | string Enum: "accepted" "courierAssigned" "courierToPickup" "courierAtPickup" "pickedUp" "courierToDropoff" "courierAtDropoff" "delivered" "rejected" "cancelled" "failed" "returning" "returned" |
| externalDeliveryId required | string [ 1 .. 200 ] characters |
| occurredAt required | string <date-time> |
| trackingUrl | string <uri> <= 2000 characters |
{- "courierLocation": {
- "latitude": -90,
- "longitude": -180,
- "recordedAt": "2019-08-24T14:15:22Z"
}, - "eventId": "string",
- "sequence": 1,
- "status": "accepted",
- "externalDeliveryId": "string",
- "occurredAt": "2019-08-24T14:15:22Z",
}{- "received": true,
- "stale": true
}Payment operations enable the functionality “Self Payment”, which means that ordering platforms can pay for items on tables in restaurants, even if they have not been ordered by the same platform beforehand. The Payments API enables connected ordering platforms to query tables, view ordered items on tables and send payments to clear the whole/a fraction of the table. To support the optional Self Payment functionality, the POS system needs to send open positions on tables upon the request of an ordering platform, process payments of open positions (including split payments) and reply with receipt data. Typically, the workflow is as following:
In order to prevent consistency issues and high data traffic, the Self Payment functionality is only available via WebSocket and thus not documented in the HTTP REST statements underneath. The actions are only available for the ordering platforms if the POS has an active WebSocket connection.
The connected ordering platforms can query a specific table. The POS receives a “Get Table” action in the WebSocket.
| action | string action command to execute |
object data to send with the command |
{- "action": "GetTable",
- "data": {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "restaurantId": "1234567",
- "tableId": "12"
}
}Upon arrival of the GetTable-Action, the POS should answer with PutTable, containing information about the table as well as the open (= not paid yet) items.
| action required | string action command to execute |
required | object data to send with the command |
| requestId required | string unique request id generated by POS (Each reply message contains a correlation id, a unique identifier that indicates which request message this reply is for) |
{- "action": "PutTable",
- "data": {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "restaurantId": "1234567",
- "table": {
- "id": "string",
- "name": {
- "en": "name",
- "de": "Name",
- "it": "nome"
}, - "description": {
- "en": "description",
- "de": "beschreibung",
- "it": "descrizione"
}, - "isTemporary": true,
- "lastInteractionAt": "2019-08-24T14:15:22Z",
- "areaId": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "items": [
- {
- "id": "string",
- "quantity": 0,
- "singlePrice": {
- "amount": 1210,
- "currency": "EUR"
}, - "rowTotal": {
- "amount": 1210,
- "currency": "EUR"
}, - "toppings": [
- {
- "id": "string",
- "quantity": 0,
- "singlePrice": {
- "amount": 1210,
- "currency": "EUR"
}, - "rowTotal": {
- "amount": 1210,
- "currency": "EUR"
}
}
]
}
]
}
}, - "requestId": "string"
}| action | string the executed command |
| status | string status of the executed command ok ok failed error |
| statusCode | integer status code of the executed command |
| correlationId | string Each reply message contains a correlation id, a unique identifier that indicates which request message this reply is for (unique request id generated by POS) |
{- "action": "PutTable",
- "status": "ok",
- "statusCode": 200,
- "correlationId": "string"
}The ordering platform creates a “payment” once the enduser has paid for the selected items.
| action | string action command to execute |
object data to send with the command |
{- "action": "GotPaymentRequest",
- "data": {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "restaurantId": "1234567",
- "payment": {
- "id": "string",
- "tableId": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "amountPaid": {
- "amount": 0,
- "currency": "string"
}, - "items": [
- {
- "id": "string",
- "quantity": 0,
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}
}
], - "discounts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string"
}
], - "additionalCosts": [
- {
- "value": {
- "amount": 0,
- "currency": "string"
}, - "name": "string",
- "tip": true,
- "taxRate": 0
}
]
}
}
}To confirm the processing of the payment, the POS is supposed to send the receipt. If this confirmation is missing, the ordering platform will cancel the payment.
| action required | string action command to execute |
required | object data to send with the command |
| requestId required | string unique request id generated by POS (Each reply message contains a correlation id, a unique identifier that indicates which request message this reply is for) |
{- "action": "PutReceipt",
- "data": {
- "siteId": "60189e9c-7d12-438c-b9ca-6998d9c364b1",
- "providerId": "4834bcdc-4a64-444d-966b-1a6fe381da24",
- "restaurantId": "1234567",
- "receiptInfo": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "active",
- "pickupNumber": "1-2345",
- "creationDate": "2019-08-24T14:15:22Z",
- "data": {
- "cashRegisterId": "POS12345",
- "signatureValue": "_R1-AT1_POS12345_R1234567_2022-01-06T14:56:00_3,30_8,80_0,00_0,00_0,00_ZMBRGX0=_2CBFF973_sE/BuW3BYUk=_03AVHF9FDN884X63kGWNEkbNm9raufVc7DMZr3JmaOEnHEC7z7lj2dkJDGy6jKkhKwgN6JTCldBRxAPZ3aUENQ==",
- "vatId": "ATU12345678",
- "number": "R1234567",
- "type": "Rechnung",
- "header": [
- "YX Gastro Gmbh",
- "1010 Wien, Am Hof 3",
- "Phone 1233456789"
]
}, - "items": [
- {
- "quantity": "2",
- "name": "Minestrone",
- "singlePrice": {
- "amount": "1210",
- "currency": "EUR"
}, - "rowTotal": {
- "amount": "1210",
- "currency": "EUR"
}, - "taxId": "B",
- "sortIndex": "1"
}
], - "taxes": [
- {
- "id": "B",
- "name": "20 % Ust.",
- "rate": "20",
- "netAmount": {
- "amount": "275",
- "currency": "EUR"
}, - "taxAmount": {
- "amount": "55",
- "currency": "EUR"
}, - "grossAmount": {
- "amount": "330",
- "currency": "EUR"
}
}
], - "totalAmount": {
- "amount": "1210",
- "currency": "EUR"
}, - "paymentId": "string",
- "tableId": "string"
}
}, - "requestId": "string"
}| action | string the executed command |
| status | string status of the executed command ok ok failed error |
| statusCode | integer status code of the executed command |
| correlationId | string Each reply message contains a correlation id, a unique identifier that indicates which request message this reply is for (unique request id generated by POS) |
{- "action": "PutReceipt",
- "status": "ok",
- "statusCode": 200,
- "correlationId": "string"
}