ICD - Salesforce - EPC - Partner, Offer and Voucher Sync

Interface Control Document (ICD): Salesforce - EPC

DRAFT FOR DISCUSSION. This document is not an agreed interface. It exposes the shapes of the current EPC backoffice API requests for creating and updating partners, offers and vouchers, so that the Salesforce team can tell us, field by field, what Salesforce holds and can send. Endpoints, behaviour, classifications and the activation model described here are proposals and will change once the field list is agreed.

Document Revision History

Version Status Update Comment By Date
1.0 Draft Initial draft for field discussion with the Salesforce team. Inventory of the current EPC create and update request fields for partners, offers and vouchers, with what is mandatory today and what would need to hold before activation. Proposes the "create as draft, enrich in the backoffice, guard at activation" model Retter 19 Oct 2026

Definitions & List of Abbreviations

Abbreviation Description
EPC Emirates Platinum Card — the Platinum programme and its API
Salesforce The CRM in which partner accounts, contracts and the commercial terms of offers and vouchers are agreed. The source of truth for every field marked SF in this document
Backoffice The EPC administration portal where programme staff enrich and activate records
Partner A merchant organisation contracted to offer benefits to Platinum members
Venue A physical location of a partner at which offers are redeemed. Called "location" in the EPC API
Offer A benefit a partner publishes to members: a percentage discount, a special price, a special deal or a lifestyle-hub access
Voucher A partner-supplied benefit sold or allocated to members as a redeemable code, with stock and a sale window
Pending The EPC status of a partner, offer or voucher that has been created but not activated. Members never see a Pending record. This document uses "draft" and "Pending" interchangeably
Activation The EPC control point after which a record is live for members. Always performed in the backoffice, never by this interface
Activation blocker A field or condition that must be satisfied before a record may be activated. Shown in the backoffice so operators can see what is still missing
API key A static secret issued to the Salesforce integration and sent in the X-API-Key header on every call
AED, fils UAE Dirham and its minor unit (1 AED = 100 fils). Money in this interface is sent in AED; EPC stores fils
UAT User Acceptance Testing environment

1. Interface Description

Partners, their contracts and the commercial terms of offers and vouchers are agreed in Salesforce. Today the same data is typed a second time into the EPC backoffice. This draft describes an interface through which Salesforce would create and update the EPC partner, offer and voucher records directly, so that Salesforce becomes the source of truth for the fields it holds and the backoffice is used for what Salesforce does not hold: images, categories, eligibility rules, finance coding, voucher codes and the activation decision itself. Which fields those are is the question this draft is meant to settle: section 4.4 lists every field of the current EPC requests for the Salesforce team to mark as available or not.

Business Value

Objective

Scope

In scope: creation and update of partners (including venues), offers and vouchers, in the direction Salesforce to EPC.

Out of scope: activation, deactivation and deletion through this interface (see open item 4 for the one proposed exception); images, documents and voucher codes (binary content stays in the backoffice); member data; redemption, sales or usage data flowing back to Salesforce (open item 8).

2. Assumptions & Risk

Assumptions

Risks

Risk Mitigation
Salesforce creates an offer or voucher for a partner EPC has not received EPC returns 404; Salesforce sends the partner first, then retries
A Salesforce push overwrites a value an operator corrected in the backoffice Salesforce-owned fields are read-only in the backoffice, so there is nothing to overwrite. The audit log records both values
A record stays Pending because nobody notices the missing enrichment The backoffice lists what is still missing for activation; a daily digest of Pending Salesforce-created records is recommended (open item 6)
Dates, prices or quantities change in Salesforce after a record is live EPC applies the update to the live record exactly as a backoffice edit would, including the existing approval rules (open item 5)
Network timeouts Client timeout of 30 s; retry with back-off; the upsert makes a duplicate retry safe

3. Non-Functional Requirements

3.1 Security Requirements

Sr No. Non-Functional Requirement Value
1 PHI or Credit Card data? No credit card data and no patient health information. Only partner business data and partner contact details
2 Authentication Pattern Static API key sent in the X-API-Key header, one key per environment, issued by the EPC team at onboarding
3 Authorisation The key identifies the Salesforce integration. It may create and update partners, offers and vouchers and nothing else. It cannot activate, deactivate or delete
4 Secure Channel / Encryption in Transit TLS 1.2 or higher (HTTPS only)
5 Input validation Yes. Every field is validated against the JSON schema in section 4.4. Unknown and EPC-only fields are dropped, never stored
6 Internet exposed? IP whitelisting? Yes, exposed via CloudFront. An IP allow-list (WAF) for the Salesforce egress ranges is recommended
7 Logging and audit Every call is recorded with its outcome, without the API key or body (integration-call log). Every created or changed record writes an EPC audit entry with actor salesforce and the before and after values
8 Data exposure Responses return EPC identifiers and status only. No member data is ever returned

4. Solution View

4.1 Logical

Component Value
Source Salesforce (CRM)
Source Protocol HTTPS REST API
Source Data Format JSON, UTF-8
Target EPC (Emirates Platinum Card) API
Target Protocol HTTPS
Target Data Format JSON
Direction Inbound to EPC. Every call is initiated by Salesforce; EPC does not call Salesforce in this ICD
Operation Upsert: one PUT per record, keyed by the Salesforce identifier. Create when it is unknown, update when it is known

4.2 Architecture

4.2.1 Interface Architecture

┌──────────────┐    PUT /partners/salesforce/{sfId}      ┌──────────────┐    enrich + activate   ┌──────────────┐
│              │    PUT /offers/salesforce/{sfId}        │              │  ◀───────────────────  │              │
│  Salesforce  │    PUT /vouchers/salesforce/{sfId}      │   EPC API    │                        │  Backoffice  │
│   (Source)   │  ─────────────────────────────────────▶ │   (Target)   │  ───────────────────▶  │  (Operator)  │
│              │  ◀─────────────────────────────────────  │              │   missing for          │              │
└──────────────┘    created / updated + what is missing   └──────────────┘   activation           └──────────────┘
                                                                 │
                                                                 ▼
                                                   Pending ──(blockers cleared,
                                                            operator activates)──▶ Active

Flow:

4.2.2 Security Mechanisms

4.2.3 Exception / Error Management Guidelines

Standard EPC error envelope and HTTP statuses (400 validation, 401 invalid key, 404 unknown partner, 409 locked by a pending approval, 500 retry with back-off). The error catalogue is specified once the field list is agreed.

4.4 Fields Definition

Data Conventions

Column Legend

Column Values
API Which current EPC backoffice request carries the field. C create only, U update only, C, U both. — not in either request today: it has its own endpoint (image upload, venue, eligibility rule, code import) or is set by EPC
Today Whether the EPC create request requires it today. Req required, Opt optional, Cond conditional (stated in the description), — not in the create request
Salesforce Whether Salesforce holds and sends the field. ? not yet known: to be confirmed with the Salesforce team field by field (open item 3). Once confirmed each becomes M (mandatory on create, 400 without it) or O (optional). — EPC-owned, never part of this interface. M is already fixed only for the owning partner reference
Activation Whether it must hold before the record may be activated. Req required, Cond conditional (stated in the description), — not required

4.4.1 Partner

Field Type API Today Salesforce Activation Description
brandName String (1–200) C, U Req ? Req Trading name shown to members, e.g. "Acme Hotels"
legalName String (≤200) C, U Opt ? — Registered entity name, e.g. "Acme Hospitality LLC"
contractId String C, U Req ? Req Contract reference, e.g. "SF-00123". Today exported under the heading "Salesforce ID"; see open item 1 for whether it is the Contract Id or a contract number
contractStartDate Date C, U Req ? Req YYYY-MM-DD
contractEndDate Date C, U Opt ? — YYYY-MM-DD. null = open-ended
businessAddress String C, U Req ? Req Head-office address
city String C, U Req ? Req City
country String C, U Req ? Req Country
website URL C, U Opt ? — Full URL including https://
primaryContact.name String C, U Opt ? — Contact person
primaryContact.email Email C, U Opt ? — Must be a valid e-mail address
primaryContact.phone String C, U Opt ? — E.164 recommended, e.g. "+971501234567"
partnerTier String C, U Opt ? — Free-text tier label
partnerGroup String (1–100) C, U Opt ? — Free-text grouping
accountAgent String C, U Opt ? — Owning account manager
tradeLicenseNumber String C, U Opt ? — Trade licence number
socialMediaAccounts Array C, U Opt ? — Items of { platform, url }. platform is one of facebook, instagram, linkedin, x, youtube, tiktok
locations Array — — ? — Venues, one item per venue; see 4.4.2. null leaves venues untouched
brandLogo Image C Opt — Req (new) Uploaded in the backoffice. The backoffice create form already requires it; the API does not, so this is a new activation check
heroImage, additionalImages Image — — — — Uploaded in the backoffice
documents File — — — — Contract documents uploaded in the backoffice
status, statusReason Enum — — — — pending, active, inactive. Changed only by backoffice activation and deactivation

4.4.2 Partner Venue (item of `locations`)

Venues have their own add and update requests in the current API; this draft nests them in the partner payload. Each venue would need a stable Salesforce identifier to be matched by (see Data Conventions). A venue EPC has not seen is added active, as the backoffice does. A venue present in EPC but absent from the array is left untouched (no deletion through this interface).

Field Type API Today Salesforce Activation Description
name String (1–200) C, U Req ? — Venue name, e.g. "Acme Downtown"
address String C, U Req ? — Street address
coordinates.latitude Number C, U Req ? — Decimal degrees, -90 to 90. Required by EPC for the member map; if Salesforce cannot supply coordinates, venues are EPC-owned and entered in the backoffice (open item 2)
coordinates.longitude Number C, U Req ? — Decimal degrees, -180 to 180
contact.name, contact.email, contact.phone String C, U Opt ? — Venue contact
status Enum — — — — active, inactive. Deactivated in the backoffice

4.4.3 Offer

Field Type API Today Salesforce Activation Description
partnerId String (UUID) C Req M Req EPC id of the owning partner; 404 if unknown. Immutable after create. Salesforce would send its own partner identifier here, which EPC resolves (see Data Conventions)
name String (1–200) C, U Req ? Req Offer name, e.g. "Two-for-one brunch"
offerType Enum C, U Req ? Req discount, special_price, special_deal, lifestyle_hub. Salesforce picklist mapping in open item 3
percentage Number (0–100) C, U Cond ? Cond Required when offerType is discount, forbidden otherwise
price Number (AED) C, U Cond ? Cond Required when offerType is special_price, forbidden otherwise
startDate Date C, U Req ? Req YYYY-MM-DD. First day the offer may be redeemed
endDate Date C, U Opt ? — YYYY-MM-DD, on or after startDate. null = open-ended. Cannot be activated once past
viewStartDate Date C, U Req ? Req YYYY-MM-DD. When null, EPC sets it to startDate
viewEndDate Date C, U Cond ? Cond YYYY-MM-DD. Required once endDate is set and may not be later than it; when null EPC sets it to endDate
quota Integer (≥0) C, U Opt ? — Total redemptions allowed. null = unlimited
shortDescription String (1–500) C, U Req ? Req Member-facing summary
longDescription String C, U Req ? — Member-facing rich text
description.termsAndConditions String C, U Opt ? — Rich text
description.discountInfo, includes, guests, howToBook, howToRedeem, disclaimer String C, U Opt ? — Rich text sections of the member detail page
categories Array of ids C, U Req — Req At least one EPC category serving offers. Existing activation check (MISSING_CATEGORY)
subcategories Array of ids C, U Opt — — Sub-category ids
keywords Array (≤100 each) C, U Opt — — Search keywords
partnerLocations Array of venue ids C, U Opt — — Venues the offer is valid at. Empty = every active venue
isFeatured Boolean C, U Opt — — Default false
isVisibleToAll Boolean C, U Opt — Cond Default false. See eligibilityRules
label String (≤50) C, U Opt — — Editable only for special_deal; derived by EPC otherwise
badges Array (≤10 of ≤30) C, U Opt — — Display badges
lifestyleHubDetails Object C, U Cond — Cond Required when offerType is lifestyle_hub: accessOptions (at least one of individual, couple, family with an optional daily quota), day-pass prices, access text
eligibilityRules Array — — — Cond (new) Who may see and redeem. Proposed check: at least one active rule, or isVisibleToAll set to true, so that "everyone" is an explicit decision and not a default
heroImage Image — — — Req (new) Uploaded in the backoffice. No activation check today
additionalImages Image — — — — Uploaded in the backoffice
offerId String (8 digits) — — — — Human-readable offer number, allocated on create and returned
status, statusReason Enum — — — — pending, active, inactive, expired

4.4.4 Voucher

Field Type API Today Salesforce Activation Description
partnerId String (UUID) C, U Req M Req EPC id of the owning partner; 404 if unknown. The current update request accepts a partner change; this draft proposes to make it immutable as on offers. Salesforce would send its own partner identifier here (see Data Conventions)
name String (1–200) C, U Req ? Req Voucher name
memberPrice Number (AED) C, U Req ? Req What the member pays. 0 for a free-of-charge voucher. Must be 0 when distributionModel is free_of_charge or manual_allocation
denomination Number (AED) C, U Req ? Req Face value the member redeems at the outlet
supplierCost Number (AED) C, U Opt ? — What the programme pays the partner per voucher. Never shown to members or partners
releaseQuantity Integer (≥0) C, U Req ? Req Agreed number of vouchers released. In a later phase code uploads are capped against it
saleReleaseAt DateTime C, U Req ? Req Sale opens. Must be before saleClosingAt
saleClosingAt DateTime C, U Req ? Req Sale closes. Must be no later than validUntil
validFrom DateTime C, U Req ? Req Instrument becomes redeemable. Must be before validUntil
validUntil DateTime C, U Req ? Req Expiry carried onto every issued code
discountType String (≤100) C, U Opt ? — Pricing mechanic as described in Salesforce. Already planned as read-only from Salesforce
vendorReference String (≤200) C, U Opt ? — Vendor invoice or batch reference
vatCode String (≤50) C, U Opt ? — VAT code for the finance posting
taxable Boolean C, U Opt ? — Whether the member price is subject to VAT. Default false; a wrong default under-reports VAT, so Salesforce should send it for every priced voucher
limitPerMember Integer (≥1) C, U Req ? Req How many one member may buy. Proposed default 1 when null
distributionModel Enum C, U Req ? Req first_come_first_serve, manual_allocation, free_of_charge, raffle. Picklist mapping in open item 3
shortDescription String (1–500) C, U Req ? Req Member-facing summary
longDescription String C, U Opt ? — Member-facing rich text
description.inclusions, howToRedeem, termsAndConditions, disclaimer String C, U Opt ? — Rich text sections
customerServiceContact.email, phone String C, U Opt ? — Who the member contacts when a code does not work. Editable after release
categories Array of ids C, U Req — Req At least one EPC category serving vouchers
subcategories Array of ids C, U Opt — — Sub-category ids
keywords Array C, U Opt — — Search keywords
isFeatured Boolean C, U Opt — — Default false
isVisibleToAll Boolean C, U Opt — — Preview to a wider audience; eligibility rules still decide who may buy
waitlistEnabled Boolean C, U Opt — — Waitlist once sold out. A raffle always uses the waitlist
redemptionType Enum C, U Opt — — electronic (default), physical
presentationFormat Enum C, U Opt — — text (default), barcode_1d, qr_2d
defaultPaymentTypes Array C, U Req — Cond credit_card, salary_deduction. A priced voucher must offer at least one rail through this list or a rule. Existing activation check (NO_PAYMENT_TYPE_AVAILABLE)
eligibilityRules Array C Opt — — Rules with optional per-rule payment types. No rule = everyone eligible
financeConfig Object C, U Opt — Cond GL coding: cost centre, nominal, sub-nominal, analysis key, ERP comment prefix. Required when memberPrice is greater than 0. Existing activation check (FINANCE_CONFIG_REQUIRED)
trackCoding Object C, U Opt — Cond TRACK receivable coding. Required whenever financeConfig is set. Existing check (TRACK_CODING_REQUIRED)
codes File — — — Req At least one code list loaded. Existing activation check (NO_CODES_LOADED)
heroImage Image — — — Req (new) Uploaded in the backoffice. No activation check today
additionalImages Image — — — — Uploaded in the backoffice
voucherId String (8 digits) — — — — Human-readable voucher number, allocated on create and returned
status, statusReason Enum — — — — pending, active, deactivated

4.5 Request Samples (current backoffice API)

These are the requests the EPC backoffice sends today, shown with real eu-uat records (the Costa Coffee partner, one of its venues, its offer 89786458 and its voucher 39320053, as stored on 19 Oct 2026). They show the exact field names and value formats of the current API, which is what the Salesforce payloads would be mapped onto. Contact names, e-mail addresses and phone numbers are replaced with placeholders. Images, documents and voucher codes are uploaded through separate endpoints and are not shown. The update requests are partial today: only the fields sent are changed.

All requests carry an administrator token:

Authorization: Bearer <admin access token>
Content-Type: application/json

4.5.1 Create Partner

POST /partners HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "brandName": "Costa Coffee",
  "legalName": null,
  "partnerTier": "Platinum",
  "partnerGroup": "ELR",
  "businessAddress": "EMIRATES LEISURE RETAIL CORPORATE HEAD OFFICE Level 5, Emirates Holidays Building P.O.Box 122199, Sheikh Zayed Road",
  "city": "Dubai",
  "country": "AE",
  "website": "https://www.costacoffee.ae/",
  "primaryContact": {
    "name": "<contact name>",
    "email": "<contact e-mail>",
    "phone": "<contact phone>"
  },
  "tradeLicenseNumber": null,
  "contractId": "575876543",
  "contractStartDate": "2026-03-01",
  "contractEndDate": null,
  "accountAgent": null,
  "socialMediaAccounts": [
    { "platform": "facebook", "url": "https://www.facebook.com/CostaCoffeeUAE" },
    { "platform": "instagram", "url": "https://www.instagram.com/costacoffeeuae/" }
  ],
  "brandLogoFileId": "<id of a pending logo upload, optional>"
}

4.5.2 Update Partner

PUT /partners/da63c652-316c-4b57-ba94-3e1176665086 HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "contractEndDate": "2027-02-28",
  "accountAgent": "<account manager name>"
}

4.5.3 Add Partner Venue

POST /partners/da63c652-316c-4b57-ba94-3e1176665086/locations HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "name": "Emirates Group HQ",
  "address": "2ND FLOOR, EMIRATES GROUP HEADQUARTERS",
  "coordinates": { "latitude": 25.241316, "longitude": 55.366476 },
  "contact": {
    "name": "<venue contact name>",
    "email": "<venue contact e-mail>",
    "phone": "<venue contact phone>"
  }
}

4.5.4 Update Partner Venue

PUT /partners/da63c652-316c-4b57-ba94-3e1176665086/locations/f0b6bd30-08ee-445a-b1f5-57bf4049e92c HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "address": "2nd Floor, Emirates Group Headquarters, Airport Road, Dubai"
}

4.5.5 Create Offer

Special-price offer. A discount offer sends percentage instead of price; special_deal and lifestyle_hub send neither. The list of venues is shortened here; the stored offer names 30 of the partner's venues.

POST /offers HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "name": "Flat Rate AED 15 Any Coffee",
  "partnerId": "da63c652-316c-4b57-ba94-3e1176665086",
  "partnerLocations": [
    "ca3a5f4b-7a32-47e7-bebf-0c410a69077e",
    "5f93a8cd-093e-4c9b-85e1-858385b759ba",
    "da584b5f-8f2b-4eab-88bf-be4b389148fd"
  ],
  "offerType": "special_price",
  "price": 15,
  "isFeatured": false,
  "isVisibleToAll": true,
  "label": "AED 15",
  "categories": ["c391f62e-d854-478e-9085-7890217f0a33"],
  "subcategories": [
    "522a5613-c514-4a90-bc8d-70dec417667a",
    "54fbc405-b1d3-40ca-8e3c-a0c2c3ac70d8"
  ],
  "startDate": "2026-01-01",
  "endDate": "2027-12-01",
  "viewStartDate": "2026-01-01",
  "viewEndDate": "2027-12-01",
  "shortDescription": "Any regular coffee for just AED 15 at selected Costa Coffee branches. Choose from Americano, Latte, Cappuccino, and more.",
  "longDescription": "Keep it simple with our flat rate coffee deal. Any regular-sized coffee from our core menu is yours for just AED 15. Whether you prefer a bold Americano, a creamy Latte, or a classic Cappuccino, the choice is yours.",
  "description": {
    "includes": "Any regular-sized coffee from the core menu",
    "howToRedeem": "Show your membership card or app at the counter before ordering",
    "termsAndConditions": "Valid on regular size only. Excludes specialty and seasonal drinks. Valid at selected locations only.",
    "disclaimer": "Subject to availability. Management reserves the right to modify or cancel this offer."
  }
}

4.5.6 Update Offer

PUT /offers/e348af64-5068-4770-8eda-3803bcc063f3 HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "price": 16,
  "label": "AED 16",
  "endDate": "2028-03-31",
  "viewEndDate": "2028-03-31"
}

4.5.7 Create Voucher

Money is sent in AED. The four dates carry a time of day and are shown in Asia/Dubai.

POST /vouchers HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "name": "Costa Coffee AED 50 Gift Voucher",
  "partnerId": "da63c652-316c-4b57-ba94-3e1176665086",
  "categories": ["c391f62e-d854-478e-9085-7890217f0a33"],
  "subcategories": [],
  "isFeatured": true,
  "discountType": "20% off face value",
  "memberPrice": 40,
  "denomination": 50,
  "supplierCost": 35,
  "taxable": false,
  "financeConfig": {
    "costCentre": "53050",
    "nominal": "48001",
    "subnominal": "P943",
    "analysisKey": "00000000",
    "erpCommentPrefix": "Voucher"
  },
  "trackCoding": {
    "lob": "99",
    "responsibilityCentre": "50000",
    "nominalCode": "37012",
    "subnominalCode": "G274",
    "analysisKey": "00000000"
  },
  "vendorReference": "COSTA-GV50-UAT-2026Q4",
  "limitPerMember": 2,
  "distributionModel": "first_come_first_serve",
  "redemptionType": "electronic",
  "presentationFormat": "qr_2d",
  "defaultPaymentTypes": ["credit_card", "salary_deduction"],
  "isVisibleToAll": true,
  "saleReleaseAt": "2026-09-01T09:00:00+04:00",
  "saleClosingAt": "2026-10-31T23:00:00+04:00",
  "validFrom": "2026-09-01T09:00:00+04:00",
  "validUntil": "2027-03-31T23:00:00+04:00",
  "releaseQuantity": 100,
  "shortDescription": "Pay AED 40 for an AED 50 Costa Coffee gift voucher",
  "longDescription": "Enjoy your favourite Costa Coffee for less. Purchase this AED 50 digital gift voucher for AED 40, then show the QR code from your wallet at the till in any participating Costa Coffee store across the UAE. Valid until 31 March 2027.",
  "description": {
    "howToRedeem": "<p>Redeemable on drinks, food and merchandise at participating Costa Coffee stores in the UAE.</p>",
    "termsAndConditions": "<p>Valid on drinks, food and merchandise. One voucher per transaction. Not exchangeable for cash.</p>",
    "disclaimer": "<p>This voucher is for UAT testing only.</p>"
  },
  "keywords": ["costa", "coffee", "gift voucher", "cafe", "drinks"],
  "customerServiceContact": {
    "email": "<partner customer service e-mail>",
    "phone": "<partner customer service phone>"
  }
}

4.5.8 Update Voucher

PUT /vouchers/616fee21-6317-41b0-88c8-966e4d2f3796 HTTP/1.1
Host: uat.api.platinum.retter.io

{
  "saleClosingAt": "2026-12-31T23:00:00+04:00",
  "releaseQuantity": 150,
  "supplierCost": 34
}

5. API Endpoints

Environment Base URL
Staging https://staging.api.platinum.retter.io
UAT https://uat.api.platinum.retter.io
Production Issued at go-live
Method Path Purpose
PUT /partners/salesforce/{id} Create or update a partner and, optionally, its venues
PUT /offers/salesforce/{id} Create or update an offer
PUT /vouchers/salesforce/{id} Create or update a voucher

Paths are provisional until the interface is built; {id} is the Salesforce identifier of the record. All three require the X-API-Key header.

6. Appendix

6.1 Business Rules Applied on Every Call

These rules run today on the backoffice create and update paths and will run unchanged on this interface. They are evaluated on the merged record (stored values plus the payload).

Entity Rule
Offer endDate on or after startDate; viewEndDate on or after viewStartDate; viewEndDate required once endDate is set and not later than it
Offer discount requires percentage and forbids price; special_price requires price and forbids percentage; special_deal and lifestyle_hub take neither
Offer lifestyle_hub offers must carry the lifestyle-hub category and no other type may (EPC-owned category, so this surfaces as an activation blocker)
Offer Named venues must belong to the offer's partner (EPC-owned field)
Voucher saleClosingAt after saleReleaseAt; validUntil after validFrom; saleClosingAt not later than validUntil
Voucher No voucher date may be in the past on create
Voucher memberPrice must be 0 for free_of_charge and manual_allocation
Voucher financeConfig implies trackCoding

6.2 Activation Gate Summary

What must hold before an operator can activate a Salesforce-created record. Which checks are needed depends on the outcome of the field discussion, so this section states the rule rather than the final list.

Checks that exist today and apply unchanged

Entity Check
Offer Partner is active
Offer Partner has at least one active venue
Offer At least one category
Offer endDate not in the past
Voucher financeConfig present when the voucher is priced
Voucher trackCoding present when financeConfig is set
Voucher At least one payment rail when the voucher is priced
Voucher At least one code list loaded

Rule for fields the create request requires today. Every field marked Req or Cond in the Today column of section 4.4 is either sent by Salesforce or completed in the backoffice. If Salesforce sends it, it is mandatory in the payload and nothing changes. If Salesforce does not hold it, the create-time requirement is lifted for this interface and the same condition becomes an activation check instead, so the record is created as Pending and cannot go live until the field is filled. The list of such fields is known only once every ? in section 4.4 is resolved.

Checks that would be new whatever Salesforce sends, because they concern content that is always EPC-only, or a precondition that moves from create time to activation time:

Entity Check
Partner Brand logo uploaded
Offer Hero image uploaded
Offer At least one active eligibility rule, or isVisibleToAll set to true, so that "everyone" is an explicit decision
Offer Partner is active and has an active venue: enforced at create today, checked at activation for records created by Salesforce against a Pending partner
Voucher Hero image uploaded
Voucher Partner is active: enforced at create today, checked at activation for records created by Salesforce against a Pending partner

6.3 Open Items

No. Item Owner
1 Which Salesforce object is a Partner and what contractId carries: a Salesforce record identifier or a contract number. The export heading already reads "Salesforce ID" Emirates / Salesforce team
2 Whether Salesforce holds venues or outlets with coordinates. If not, section 4.4.2 is dropped and venues stay EPC-owned Emirates / Salesforce team
3 Field-by-field confirmation of what Salesforce holds: every ? in section 4.4 becomes M or O. Includes the picklist mappings (Salesforce offer type to offerType, sales model to distributionModel) and whether a shared category code list exists so Salesforce can send categories Both
4 Whether Salesforce sends its lifecycle status and which values, if any, should deactivate a live record in EPC, and whether a reactivation in Salesforce should ever reactivate in EPC (this draft says no) Emirates
5 Whether a Salesforce update to a live offer or voucher bypasses the EPC approval policy or is held for approval like a backoffice edit. This draft holds it for approval and returns 202 Emirates
6 Notification of Pending Salesforce-created records awaiting enrichment: in-app only, or a daily e-mail digest to the partnerships team Emirates
7 Whether Salesforce is also the source of marketing copy (shortDescription, longDescription, description sections) or only of the commercial terms Emirates
8 Reverse direction (EPC to Salesforce): activation status, offer and voucher numbers, redemption and sales figures Both