Skip to main content

Authentication

DRE ships in two deployment shapes, and they authenticate differently. Choose the section that matches the instance you are connecting to:

TargetMechanismCredential on the wire
BTP (cloud)OAuth 2.0 client credentials via SAP XSUAAAuthorization: Bearer <jwt>
Local-store (on-prem / edge)API key (POS) · session cookie (admin UI)X-Api-Key: <key> · session cookie

There is no inbound OAuth 2.0 token endpoint on a local-store instance. OAuth 2.0 is the BTP mechanism. (A local store does use OAuth 2.0 client credentials, but only outbound — to authenticate itself when syncing up to BTP. That is not a path integrators call.)


Connecting to a BTP (cloud) instance

The BTP deployment is secured with the SAP Authorization and Trust Management Service (XSUAA). Machine-to-machine integrators authenticate with the OAuth 2.0 client credentials grant and present the resulting JWT directly to the DRE application URL.

1. Obtain a service key

Create a service key for the DRE XSUAA service instance in your SAP BTP subaccount (cockpit → Instances and Subscriptions, or cf create-service-key). It contains url (the token endpoint), clientid, and clientsecret.

2. Request an access token

curl -X POST '<xsuaa-url>/oauth/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials' \
-d 'client_id=<clientid>' \
-d 'client_secret=<clientsecret>'

The response carries the JWT in access_token:

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "bearer",
"expires_in": 14399,
"scope": "dre.POSReader"
}

3. Call DRE with the token

Present the JWT as a bearer token on every request to the DRE application URL. The BTP application router fronts /pos and /admin and enforces XSUAA, so the token is validated before your request reaches the engine.

# Real-time evaluation (POS Service)
curl -X POST 'https://<dre-url>/pos/v2/evaluate' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-d '{ "request": { "posGroupCode": "STORE-001", "items": [ ... ] } }'

# Read promotion master data (Admin Service, OData V4)
curl -H 'Authorization: Bearer <access-token>' \
"https://<dre-url>/admin/Promotions?\$filter=status eq 'ACTIVE'"

Token refresh

Client-credentials tokens have a limited lifetime (DRE issues ~4-hour tokens; read expires_in from the token response — do not hard-code it). Build caching and refresh into your integration:

  • Cache the token and reuse it until shortly before expiry.
  • Request a fresh token before the current one expires.
  • On 401 Unauthorized, refresh the token and retry once.

Roles and scopes (BTP)

Your service binding must include the scope your integration needs. Request the narrowest role that covers your use case.

RoleScopeGrantsTypical consumer
POSReaderdre.POSReaderEvaluate / simulate / confirm, coupon ops, article import, heartbeatPOS, webshop, kiosk
PromotionManagerdre.PromotionManagerPromotion CRUD on the Admin ServiceBack-office / ERP sync
Admindre.AdminFull administrative accessAdmin tooling

The POS Service accepts POSReader or Admin; the Admin Service accepts PromotionManager or Admin.


Connecting to a local-store instance

A local-store instance is the offline-capable derivative of DRE that runs at or near the point of sale (its data lives in a local SQLite file, data/store.db). It serves the same /pos endpoints as BTP, but authenticates with a POS API key rather than XSUAA. The store's web admin UI (/local-admin) uses a password-protected session.

POS endpoints — API key

Every request to /pos/* must carry the API key in the X-Api-Key header:

curl -X POST 'http://localhost:4004/pos/v2/evaluate' \
-H 'X-Api-Key: <pos-api-key>' \
-H 'Content-Type: application/json' \
-d '{ "request": { "posGroupCode": "STORE-001", "items": [ ... ] } }'

A missing or wrong key returns:

{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}

Where the key comes from. The key is a 64-character hex string generated automatically on the store's first start-up and persisted locally. There is no CLI to create it. Retrieve or rotate it through the store's admin service (which requires a valid admin session — see below):

# Fetch the current key (POST, not GET — keeps the secret out of URL/referrer logs)
curl -X POST 'http://localhost:4004/local-admin/getApiKey' \
-b cookies.txt -H 'Content-Type: application/json' -d '{}'
# → { "apiKey": "<64-hex-characters>" }

# Rotate it (invalidates the previous key)
curl -X POST 'http://localhost:4004/local-admin/regenerateApiKey' \
-b cookies.txt -H 'Content-Type: application/json' -d '{}'

Admin UI — session login

The local admin surface (/local-admin/*) is protected by an express-session cookie with a 30-minute idle timeout.

# First start only: set the admin password (min. 8 characters)
curl -X POST 'http://localhost:4004/local-admin/setup' \
-H 'Content-Type: application/json' \
-d '{ "password": "ChangeMe!23", "confirmPassword": "ChangeMe!23" }' \
-c cookies.txt

# Subsequent logins — store the session cookie
curl -X POST 'http://localhost:4004/local-admin/login' \
-H 'Content-Type: application/json' \
-d '{ "password": "ChangeMe!23" }' \
-c cookies.txt
# → { "success": true } (or { "redirect": "/local-admin/setup" } if no password is set yet)

There are no default admin credentials — the password must be set via /local-admin/setup on first run. To reset a forgotten password from the host, run the bundled CLI (or set RESET_ADMIN_PASSWORD=true to force the setup flow on next login):

npx dre-reset-password   # interactive: prompts for a new admin password
note
dre-config is not an auth tool

The dre-config CLI imports/exports the store's BTP-connection settings (the outbound sync link). It does not manage the POS API key or the admin password.


Error handling (all targets)

HTTP statusMeaningAction
401UnauthorizedRefresh the token (BTP) or check X-Api-Key / session (local)
403ForbiddenYour role/scope does not grant this operation
429Rate limitedBack off and retry with exponential backoff