Building an integration
DRE has no vendor- or plugin-specific contract. Whatever your channel — a till, a webshop checkout, a kiosk, a CRM, an ERP — your integration (the "adapter") has the same three jobs:
- Map your basket →
EvaluateRequestand callPOST /pos/v2/evaluate. - Map
EvaluateResponseV2→ your UI / receipt (discounts, totals, free items, recommendations). - Commit at checkout with
POST /pos/v2/confirm, then reconcile via the side-effects poll.
This page gives the mapping tables, per-channel recipes, and the resilience and performance practices that keep a customer-facing checkout fast and safe.
Request mapping — your basket → EvaluateRequest
| Your concept | Request field | Notes |
|---|---|---|
| Store / register | posGroupCode or posGroupId | At least one is required. A code is friendlier than a UUID. |
| Cart line SKU | items[].articleNumber | Required, one entry per line. |
| Quantity | items[].quantity | > 0 sale, < 0 return/refund, 0 rejected. |
| Unit price | items[].unitPrice | Per unit, before discounts. Echoed unverified — you own price correctness. |
| Barcode | items[].ean | Optional. |
| Product group | items[].articleGroupId | Enables article-group promotions. |
| Stable line id | items[].lineReference | Recommended. Lets you correlate response lines back to your cart lines. |
| Shopper | customer.customerId, loyaltyCardNo, loyalty.{tier,points} | Optional; required for loyalty/customer-gated promotions. |
| Vouchers | coupons[] = [{ "code": "…" }] | Object array, not bare strings. |
| Sales channel | channel | e.g. IN_STORE, ONLINE, MOBILE — drives CHANNEL conditions. |
| Payment | paymentInfo.{paymentMeans,cardType,cardNumber} | For payment-method promotions. |
Remember the whole body is wrapped in a top-level request object:
{
"request": {
"header": { "transactionId": "TXN-1" },
"posGroupCode": "STORE-001",
"channel": "ONLINE",
"items": [
{ "lineReference": "L1", "articleNumber": "ART-1001", "quantity": 2, "unitPrice": 89.99 }
],
"customer": { "customerId": "CUST-4711" },
"coupons": [ { "code": "WELCOME15" } ]
}
}
Response mapping — EvaluateResponseV2 → your UI
| Response field | Use it to render |
|---|---|
lineItems[].discounts[] | Per-line discount rows / strike-through pricing. |
lineItems[].lineNet | The net price to display and charge for the line. |
lineItems[].isFreeItem | Mark an in-cart line as a free gift. |
grantedItems[] | Free items to add to the cart/receipt (they were not scanned). |
totals.grandTotal | The amount due. |
totals.savingsSummary.totalSavings | A "you saved X" banner. |
totals.savingsSummary.loyaltyPointsEarned | Points-earned messaging. |
recommendations[] | Upsell / near-miss hints — render via the hint catalog. |
appliedCoupons[] / invalidCoupons[] | Coupon accept/reject feedback. |
budgetLimitedPromotions[] | Explain why an expected promotion did not apply. |
Because lineItems is strictly 1:1 with your input items (correlated by
lineReference), the simplest adapters zip the response back onto the request
by position or by lineReference — no matching logic needed.
Per-channel recipes
POS / checkout terminal
- Call
evaluateon every basket change (debounce rapid scans, e.g. 100 ms). - Render
lineItems[].discounts[]andtotalslive. - At payment,
confirmthe current iteration, then poll side-effects for coupon redemption and any post-purchase voucher to print. - For offline resilience, target a local-store
instance; check
GET /pos/heartbeatfor connectivity and pending-transaction state.
Webshop / e-commerce
- Use
POST /pos/v2/simulatefor the cart and mini-cart preview — it is read-only and never consumes budgets or coupons. - Run a real
evaluate+confirmonly at order placement, so budgets and coupons are consumed exactly once. - Pass
channel: "ONLINE"so channel-gated promotions resolve correctly.
CRM / marketing automation
- Issue personalized coupons with
POST /pos/coupons/issue(no basket needed) — see the coupon lifecycle. - Track redemption via the side-effects poll or subscribe to coupon webhooks.
- Respect the 1000-issuances-per-minute-per-tenant rate limit; batch with
customerIds[].
ERP / master-data
- Push article master data with
POST /pos/articles/import(sync) orimport-batch(async) — see the wire contract. - Read promotion definitions for downstream systems via
GET /admin/Promotions(OData V4) — see the Promotions API. - Manage budgets through the Admin Service.
Resilience
A promotion engine sits on the critical path of a sale. Design so that a slow or unavailable engine never blocks a checkout.
- Timeouts.
evaluateis synchronous and customer-facing — set a client timeout (a few seconds) and treat a breach as a failure, not a hang. - Retries. Retry
evaluateon5xx/timeout with capped exponential backoff (e.g. 3 attempts, 100 ms → 200 ms → 400 ms). Do not blind-retryconfirm— poll the side-effects endpoint to learn whether it committed (why). - Fallback. After exhausting retries, proceed with no promotions rather than failing the sale. Log it and alert on a threshold so the gap is visible.
- Cache master data. For display or offline use, cache active promotions
read via
GET /admin/Promotionsand refresh on a poll interval; do not cache per-customer evaluate results.
Performance budget
evaluate/simulate run in a synchronous, customer-facing context. Target
these and alert when you exceed them:
| Percentile | Target | If exceeded |
|---|---|---|
| P50 | < 200 ms | Normal |
| P95 | < 500 ms | Monitor |
| P99 | < 1000 ms | Alert |
| Hard timeout | ~5000 ms | Fall back (see above) |
Helpers: scope each request to the right posGroupCode; keep baskets to the
lines actually scanned; reuse a pooled HTTP connection; cache and reuse the
auth token (BTP) until near expiry.
Correlation & idempotency
- Assign a stable
lineReferenceto every cart line and keep it for the life of the basket. - Carry the
(transactionId, transactionCounter)tuple fromevaluateintoconfirm— the server assigns the counter; you echo it back. See the lifecycle. GETreads are safe to retry.confirmand couponredeemare not idempotent — reconcile via the side-effects poll instead of replaying.
See also
- POS endpoints — the full endpoint catalogue.
- Evaluate → Confirm lifecycle — the transaction flow in detail.
- Promotion scenarios & actions — what each promotion produces in the response.