Skip to content

Contract authority: OpenAPI is the machine-readable public v1 contract. This page is generated from the Privilege Integrator Pack. If prose and OpenAPI disagree, stop and contact Privilege.

3. Authentication ​

Wire format ​

http
Authorization: Basic base64(<clientKey>:<clientSecret>)
RolePublic nameTypical form
Username / client identifierclientKeystarts with pic_
Password / secretclientSecretstarts with pcs_

These are Integration Client machine credentials — not Member, Partner App, or browser session tokens.

How merchants obtain credentials ​

Public API vs management UX

SurfaceStatus
https://dev.privilege.hr/api/integrations/v1 (validate / confirm / cancel / reverse)Available in production
Merchant self-service (Partner Portal → Integrations)Not available yet — coordinate with Privilege

Today, vendors must coordinate credential and outlet-mapping provisioning with Privilege during onboarding. Privilege provisions an Integration Client for the agreed merchant/profile and shares clientKey / clientSecret securely (secret shown once). Merchant self-service for creating clients is not available yet — HTTP Basic with those credentials is the only supported auth for this API.

When Partner Portal → Integrations becomes available to merchants, the normal workflow will be:

  1. Company Admin opens Partner Portal → Integrations.
  2. Creates an Integration Client for the correct company/profile (operational company the POS serves).
  3. Privilege shows clientKey + clientSecret once.
  4. Store the secret in your POS secure vault / HSM / server-side config.

Rules (apply regardless of who creates the client):

  • Secret is shown once at create (and again only on rotate). It cannot be retrieved later.
  • Store secrets server-side only. Never embed clientSecret in browser, mobile apps, or public repos.
  • An Integration Client that is disabled (or not enabled) cannot authenticate → 403 CLIENT_DISABLED.
  • Wrong or unknown credentials → 401 UNAUTHENTICATED (generic message).

Required application scopes on the client (configured by Privilege at create; not OAuth):

  • redemptions:validate
  • redemptions:confirm
  • redemptions:cancel
  • redemptions:reverse

Missing scope → 403 INSUFFICIENT_SCOPE.

Credential rotation (summary) ​

See §13 Credential rotation. Default grace for the previous secret is 24 hours (INTEGRATION_CREDENTIAL_ROTATION_GRACE_HOURS, default 24).


4. Outlet mapping ​

Your POS has its own stable outlet identifier. Privilege has its own outlets. They are linked by mapping:

text
POS externalOutletId  ←→  Privilege Outlet
  • On every validate (and optionally on confirm/cancel), send your externalOutletId.
  • Outlet mappings are configured in Privilege against that Integration Client (today: coordinated with Privilege during onboarding; later: Company Admin in Partner Portal → Integrations → locations/mappings when that UI is available).
  • An Integration Client is bound to one operational company/profile. Mappings and redemptions for that client only apply inside that bound company. Credentials from Company A must not be used for Company B’s outlets.

Promotion mapping (POS-owned pricing)

Privilege does not send pricing instructions or basket/item eligibility rules. The POS owns % / fixed / B1G1 / SKU / stacking.

On successful validate, Privilege returns:

  • privilegePromotionId — stable public promotion identity (= Deal.id; map to your local POS promotion; not an authorization secret; not a pricing instruction)
  • benefit: null — Privilege does not tell the till what amount or percent to apply

Configure the till so privilegePromotionId maps to a local promotion. An unknown/unconfigured mapping must not silently become a whole-basket discount — fail closed in the POS and cancel the reservation (or let TTL expire).

Supported authorized deal types: Percentage | Standard | B1G1. Privilege does not calculate their commercial benefit for POS. Stale aliases FixedAmount/BOGO and unknown types return OFFER_UNSUPPORTED and do not create a reservation.

Reservations without a frozen privilegePromotionId: cancel is allowed; validate replay / confirm return OFFER_SNAPSHOT_MISSING — cancel and re-validate.

Fictional example

SideValue
Merchant profile“Demo Café Zagreb” (Privilege company/profile)
POS till idstore-zg-01-till-3
Privilege outlet“Demo Café — Ilica”
MappingexternalOutletId=store-zg-01-till-3 → that Privilege outlet
Local POS promoPRIV-FOOD-PROMO ↔ privilegePromotionId from validate

Unmapped outlet → 404 OUTLET_UNMAPPED. Disabled mapping → 403 OUTLET_DISABLED (validate path).


13. Credential rotation ​

Rotation creates a new clientSecret (shown once). The previous secret remains usable only during rotation grace (default 24 hours, INTEGRATION_CREDENTIAL_ROTATION_GRACE_HOURS). After grace, the old secret stops authenticating. During grace, at most two secrets may authenticate (active + rotated-in-grace). Plan POS cutover inside that window. Disabling the Integration Client blocks all secrets for that client.

Today, request rotation through Privilege support/onboarding.

When Partner Portal → Integrations is available to merchants, the workflow will be:

  1. Partner Portal → Integrations → open the integration
  2. Generate new Secret (rotate)
  3. Copy the new clientSecret (shown once) into the POS secure config
  4. Verify validate/confirm with the new secret
  5. Complete cutover before grace ends

Privilege Developers — public External Integration documentation. OpenAPI is the machine-readable contract.