| Abbreviation | Description |
|---|---|
| EPC | Emirates Platinum Card |
| EDP | Enterprise Data Platform (target data lake) |
| PII | Personally Identifiable Information |
| DDS | Direct Deduction from Salary |
| HRMS | Human Resource Management System |
| AED | United Arab Emirates Dirham |
| VAT | Value Added Tax |
| BG_ID | HRMS Business Group Identifier |
| AR | Accounts Receivable |
| GL | General Ledger |
| SSO | Single Sign-On |
| DPO | Data Protection Officer |
| M / O / C | Mandatory / Optional / Conditional |
EPC operates the Emirates Platinum Card membership programme: employee and dependant enrolment, tiered memberships, partner offers and venue access, and the collection of membership fees by card or salary deduction.
This interface delivers the programme's operational data to the Enterprise Data Platform so that it can be combined with other enterprise datasets for reporting and analysis. Two consuming use cases are in scope:
To provide a complete, regularly refreshed extract of EPC operational data in a form that EDP can load without bespoke transformation logic on the EPC side, and to define unambiguously:
currency and exponent fields are delivered so this need not be assumed.| Risk | Mitigation |
|---|---|
| Personal data, including data relating to dependants who are not employees, is delivered into a platform where it may be used for model training. Trained models cannot be selectively un-trained, so a subsequent erasure request cannot be satisfied by deleting records from the platform. | Documented as an explicit decision in section 3.1. Requires DPO approval recorded before the first production delivery. EDP to confirm retention and erasure procedures. |
Free-text fields (member.note, redemption.notes, invoice narrative) contain unstructured content entered by operators, the content of which has not been surveyed. |
EPC to complete a content review of free-text fields before first production delivery. EDP to treat these fields as unclassified until that review completes. |
| Monetary values misinterpreted as major units, overstating amounts by a factor of 100. | Section 4.4.1 defines the convention. currency and exponent delivered alongside every monetary field. Section 4.4.2 identifies the one dataset that uses major units. |
| Coded identifiers loaded without reference data, producing unreadable dimensions. | Section 4.6 code lists delivered with every extract. Section 4.4.5 lists every coded field and its corresponding code list. |
| Non-production membership numbers carry an environment suffix and will not reconcile against production. | Section 5.3. The two environments are to be treated as separate key spaces and not joined. |
| Schema drift on the EPC side breaks EDP ingestion silently. | Enumerated value sets are closed (section 4.6). EDP to alert on unrecognised values rather than discard. EPC to give advance notice of field additions; see section 5.4. |
| Sr No. | Non-Functional Requirement | Value |
|---|---|---|
| 1 | PHI or Credit Card data? | No to both. The feed carries no patient health information. EPC holds no card numbers at any point; the card tokens and mandate references it does hold, and the raw payment-gateway messages, are excluded (section 6.2). The delivered dataset is therefore outside PCI-DSS scope. |
| 2 | PII included? | Yes. The feed contains identified personal data relating to employees and to their dependants, including names, contact details, dates of birth, gender, marital status, home addresses, family relationships and free-text notes. Fields carrying PII are marked in the Data Definitions tables. |
| 3 | Authentication Pattern | Determined by the transfer mechanism agreed under 5.1. No inbound interface is exposed by this feed. |
| 4 | Secure Channel / Encryption in Transit | To be confirmed with the transfer mechanism (5.1). Encryption in transit is required. |
| 5 | Encryption at Rest | To EDP standard, at the destination agreed under 5.1 |
| 6 | Internet exposed? | No public endpoint is created by this feed. Exposure of the destination is determined by the mechanism agreed under 5.1. |
| 7 | Credentials in payload | None. Authentication credentials and password material are excluded from every dataset (section 6.2). |
| Component | Value |
|---|---|
| Source | EPC (Emirates Platinum Card) |
| Target | EDP (Enterprise Data Platform) |
| Direction | Unidirectional, EPC to EDP |
| Extract type | Full extract of every dataset on each delivery |
| Transfer protocol | Open — requires EDP decision. See 5.1 |
| Data format | Open — requires EDP decision. See 5.1 |
| Cadence | Open — requires EDP decision. See 5.1 |
> This section is deliberately unresolved. The transfer mechanism, encoding
> and scheduling have not been agreed and are an EDP-side decision — see 5.1.
> The data content of the feed, defined in 4.4 to 4.6, is independent of that
> decision and does not change with it.
Once the transfer mechanism is agreed, this section will document the interface
architecture, security mechanisms and exception-handling guidelines for the
chosen approach.
Membership growth, tier mix, renewal and lapse behaviour, and dependant enrolment. Primary datasets: member, membership, tier, tier_enrollment, with member_type, member_subtype and tier_type for labels.
Amounts billed, collected and refunded, across both card and salary-deduction routes. Primary datasets: payment, payment_refund, transaction, invoice, invoice_line. For salary deduction specifically, dds_deduction_cycle and payroll_feed_line are authoritative — see section 4.4.6.
Take-up of partner offers and venue access, and the value delivered to members. Primary datasets: redemption, venue_checkin, venue_checkin_companion, offer, partner, partner_location.
Reconstruction of prior state — a member's status at a past date, a tier's VAT treatment when a charge was raised. Only audit_log supports this; all other datasets carry current state only. See section 4.4.7.
These conventions apply across all datasets and must be implemented by EDP before the field definitions in section 4.5 can be interpreted correctly.
All monetary fields whose name ends in Value are integers in minor units (fils). They are never decimals.
| Element | Meaning |
|---|---|
|
Integer amount in minor units |
currency |
ISO currency code of the amount. Always AED at time of writing |
exponent |
Number of decimal places. Always 2 at time of writing |
Display value = / 10^exponent. For example amountValue = 300 with exponent = 2 represents AED 3.00.
Every dataset carrying a monetary field delivers currency and exponent alongside it. Where the source record has no such field of its own (see 4.4.3), EPC stamps currency = AED and exponent = 2 at extraction. With the single exception in 4.4.2, the feed delivers minor units only; no dataset carries the same amount at two scales.
One dataset carries amounts in major units (decimal AED) because it reproduces values exactly as posted to the finance system. It is the only exception in the feed.
| Dataset | Fields in major units |
|---|---|
invoice_line |
unitSellingPrice, taxAmount, distributionAmount |
Note that invoice header totals (totalAmountValue, totalBaseAmountValue, totalTaxAmountValue) remain in minor units. Reconciling an invoice header against its lines therefore requires a scale conversion.
The tier fee is delivered as feeValue (minor units) only. The major-unit fee shown in EPC's own user interfaces is computed for display and is not stored; it is not part of the feed.
The following carry monetary values without a currency or exponent field in the source. EPC stamps currency = AED and exponent = 2 on these records at extraction; the stamped fields appear in each dataset's field table.
| Dataset | Monetary fields | Stamped at extraction |
|---|---|---|
membership |
installmentAmountValue, lastInstallmentAmountValue, ddsChargeAmountValue |
currency, exponent |
dds_deduction_cycle |
amountValue |
currency, exponent |
payment_refund |
amountValue |
currency, exponent |
payroll_feed |
totalAmountValue |
currency, exponent |
payroll_feed_line |
amountValue |
currency, exponent |
redemption |
transactionAmountValue, discountAmountValue |
currency, exponent |
venue_checkin |
paymentAmountValue, excessQuotaPriceValue, additionalGuests.*PriceValue |
currency, exponent |
venue_checkin_companion |
priceValue |
currency, exponent |
tier |
feeValue |
currency, exponent |
offer |
priceValue, lifestyleHubDetails.*PriceValue |
currency, exponent |
transaction |
amountValue |
exponent (currency is native) |
invoice |
totalAmountValue, totalBaseAmountValue, totalTaxAmountValue |
exponent (trxCurrency is native) |
payment carries both fields natively. invoice_line is in major units and carries neither; see 4.4.2.
| Type | Format | Example |
|---|---|---|
| Timestamp | ISO 8601, UTC, Z suffix |
2026-09-04T08:41:59.255Z |
| Date | YYYY-MM-DD |
2026-09-04 |
| Accounting period | YYYY-MM |
2026-09 |
Timestamps within records are delivered as stored, in UTC. The time zone that defines a delivery day is an open decision — see 5.1, where EPC recommends Asia/Dubai for consistency with the payroll and financial reporting calendar.
The following fields carry stable identifiers, not display labels. EDP must join to the corresponding code list in section 4.6.
| Field | Dataset | Resolve against |
|---|---|---|
memberType |
member |
member_type |
memberSubType |
member |
member_subtype |
relation |
member, member_family |
member_subtype |
company.id |
member |
company |
companyGroupId |
company |
company_group |
tierType.id |
tier |
tier_type |
tierId |
membership, payment, invoice, payroll_feed_line |
tier |
eligibilityRuleId |
membership, payment |
tier_eligibility_rule |
categories, subcategories |
offer |
benefit_category, benefit_subcategory |
documentId |
member_policy_acceptance |
policy_document |
Labels are subject to change over time; identifiers are stable. EDP should resolve labels at query time rather than persisting them into fact records.
Identifier formats are not uniform. Three shapes appear across the feed and all
are valid: UUIDs (9a5a488e-9ebe-45fa-bc06-7b33baf68752), ULIDs
(01KYMKHRDEF88PBPV7ZX3AP2JB), and short lower-case slugs (employee, spouse,
base, airlines). Slugs are the earliest identifiers; later records use generated
values. Treat every identifier as an opaque string — do not validate its format,
and do not assume a single pattern per dataset.
An identifier must never be read as a label. The two diverge in live data:
| Code list | Identifier | Actual name |
|---|---|---|
member_type |
family |
"EK Temporary" |
tier_type |
premium |
"Club" |
tier_type |
01kk1bb0hjp7h8czcbpxnxhsgf |
"Premium" |
company_group |
airlines |
"CORE" |
Inferring meaning from an identifier will therefore produce wrong results. Always
join to the code list.
The member_type and member_subtype code lists carry an hrmsMapping column giving the corresponding HRMS value, allowing EDP to join directly to enterprise HR reference data.
| Question | Dataset |
|---|---|
| What was billed? | payment |
| What money moved? | transaction |
| What document was issued? | invoice, invoice_line |
| What did payroll actually deduct? | dds_deduction_cycle where state = confirmed, and payroll_feed_line where successFlag = Y |
Important: for salary-deducted memberships, payment.completedAt is set at enrolment, before any money moves. It must not be used as a collection date. The authoritative collection date is payment.deductedAt, or equivalently the confirmedAt of the corresponding dds_deduction_cycle record.
A salary-deducted membership records a single payment covering its entire term. Per-period billing is recorded only in dds_deduction_cycle.
All datasets except audit_log carry current state only. Where an analysis depends on a value as it stood at a past date, audit_log is the only source.
Two datasets have status transitions that carry no timestamp on the record itself:
| Transition | Dataset | How to date it |
|---|---|---|
| General status changes | membership |
Specific transitions carry cancelledAt, unsubscribedAt and convertedAt; there is no general last-modified timestamp. Other transitions are dated from the audit_log entries of the owning member (entityType = member). |
active to expired |
tier_enrollment |
tier_enrollment writes no audit_log entries of its own. Expiry is a side effect of the owning membership ending, so date it from that membership's endDate, cancelledAt, unsubscribedAt or convertedAt, or from the member's audit_log entries. |
redemption.status has a voided value defined, but no current process produces it (see 4.5.16); there is therefore no transition to date.
Records are delivered as whole objects with nested collections intact. EDP flattens to the grain stated for each dataset in section 4.5. The nested collections are:
| Parent | Nested collection | Resulting dataset |
|---|---|---|
member |
memberships[] |
membership |
member |
memberships[].ddsDeductionCycles[] |
dds_deduction_cycle |
member |
family[] |
member_family |
member |
companions[] |
member_companion |
member |
documents[] |
member_document |
member |
acceptedPolicyDocuments[], policyDocumentAcceptanceHistory[] |
member_policy_acceptance |
payment |
refunds[] |
payment_refund |
invoice |
lines[] |
invoice_line |
payroll_feed |
lines[] |
payroll_feed_line |
venue_checkin |
companions[] |
venue_checkin_companion |
tier |
eligibilityRules[] |
tier_eligibility_rule |
offer |
eligibilityRules[] |
offer_eligibility_rule |
partner |
locations[] |
partner_location |
company |
memberSubTypes[] |
company_member_subtype |
Where a child dataset requires the parent key, EPC injects it at extraction; the injected keys are listed in the relevant field tables.
| Column | Meaning |
|---|---|
| Field | Field name as delivered |
| Type | Data type. minor units denotes an integer per 4.4.1 |
| Req | M Mandatory, always present · O Optional, may be absent · C Conditional, present only in defined circumstances |
| PII | Y where the field carries personal data |
| Description | Meaning of the field, and any interpretation notes |
An optional field may occasionally be delivered as an explicit null rather than being absent; this occurs in particular on partner and partner_location. EDP should treat null and absent identically.
Thirty-five datasets are delivered, in six groups. Each definition states the record grain, the primary key, and any key injected by EPC at extraction.
| Group | Datasets | Count |
|---|---|---|
| Member & household | member, membership, dds_deduction_cycle, member_family, member_companion, member_document, member_policy_acceptance |
7 |
| Financial | payment, payment_refund, transaction, invoice, invoice_line, payroll_feed, payroll_feed_line |
7 |
| Programme utilisation | redemption, venue_checkin, venue_checkin_companion, search_history |
4 |
| Catalogue | tier, tier_eligibility_rule, tier_enrollment, offer, offer_eligibility_rule, partner, partner_location, company, company_member_subtype, benefit_category, benefit_subcategory, policy_document |
12 |
| Reference data | member_type, member_subtype, tier_type, company_group |
4 |
| Change history | audit_log |
1 |
| Total | 35 |
Grain: one record per enrolled person. Primary members (employees) and dependants share this dataset.
Primary key: id
Distinguishing rule: records carrying primaryMemberId are dependants; records without it are primary members.
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique record identifier. Referenced as memberId by all child datasets. |
|
| memberId | String | M | Membership number issued to the member; ten digits. Appears as "Membership No" on partner-facing records. See 5.3 for the non-production suffix. | |
| staffId | String | C | Y | Employee number as held in HRMS. Primary join key to enterprise HR data. Present on primary members only. |
| previousStaffIds | Array[String] | M | Y | Employee numbers previously held. Retained so historical records remain joinable after a staff number change. Empty array where none. |
| name | String | M | Y | Given name. |
| middleName | String | O | Y | Middle name. |
| surname | String | M | Y | Family name. |
| String | M | Y | Email address used for programme correspondence. | |
| phone | String | O | Y | Mobile number. |
| gender | String | O | Y | male or female. Frequently absent; see 6.1. |
| maritalStatus | String | O | Y | single or married. Primary members only. Frequently absent; see 6.1. |
| birthdate | String (date) | O | Y | Date of birth. Determines dependant age eligibility. Frequently absent; see 6.1. |
| company.id | String | M | Employing company. Resolve against company. |
|
| grade | String | O | Employment grade as reported by HRMS. | |
| coreGrade | String | O | Normalised grade band, EK.01 to EK.14. Used by tier eligibility rules. Frequently absent; see 6.1. |
|
| department | String | O | Department as reported by HRMS. | |
| workAddress | String | O | Place of work as reported by HRMS. | |
| address.country | String | O | Y | Home address — country. |
| address.address | String | O | Y | Home address — street and locality, single line. |
| memberType | String | M | Membership category identifier. Resolve against member_type. |
|
| memberSubType | String | O | Membership sub-category identifier. Resolve against member_subtype. |
|
| relation | String | C | Dependants only: relationship to the primary member. Resolve against member_subtype. |
|
| primaryMemberId | String (UUID) | C | Dependants only: the member.id of the household's primary member. |
|
| dependantId | String | O | The dependant's correlation identifier within the household. | |
| hrmsFamilyMemberId | String | O | Y | HRMS person identifier for this dependant. Durable link to the enterprise family record. |
| status | String (enum) | M | Enrolment lifecycle state. Values in 4.6.1. | |
| statusReason | String | O | Narrative accompanying the current status. | |
| registrationSource | String (enum) | O | How the record was created. Values in 4.6.11. | |
| deactivatedBy | String (enum) | O | What caused deactivation: system, hrms or program_management. |
|
| deactivatedAt | String (timestamp) | O | When the member was deactivated. Cleared on reactivation. | |
| suspensionEndDate | String (date) | C | Date a suspension lifts. Present only while status = suspended. |
|
| hrmsJoiningDate | String (date) | O | Employment start date from HRMS. Not a programme enrolment date. Primary members only. | |
| hrmsValidated | Boolean | O | Whether the record has been confirmed against HRMS. | |
| leavingReason | String | O | Y | Reason for leaving employment, as reported by HRMS. |
| lastDayOfService | String (date) | O | Y | Final day of employment. |
| isRetiree | Boolean | O | Whether classified as a retiree. | |
| isAlumni | Boolean | O | Alumni classification, recalculated nightly from joining date and date of birth. May revert to false if upstream data is corrected. |
|
| ddsLimit | Number | O | Y | Salary-deduction headroom as last reported by payroll. |
| availedDds | Number | O | Y | Salary-deduction amount already committed. |
| ddsCheckedAt | String (timestamp) | O | When ddsLimit and availedDds were last refreshed. Required to assess their currency. |
|
| loginMethod | String (enum) | M | sso or email_password. |
|
| lastLoginAt | String (timestamp) | O | Most recent sign-in. Engagement indicator. | |
| idPhotoStatus | String (enum) | O | pending, approved or rejected. The image itself is not delivered; see 6.2. |
|
| idPhoto | String | O | Internal storage reference for the identity photograph. Delivered as an opaque string; not resolvable outside EPC. The reference to any superseded photograph is withheld; see 6.2. | |
| permissions.sms | Boolean | O | Consent to receive SMS. | |
| permissions.email | Boolean | O | Consent to receive email. | |
| invitationSentAt | String (timestamp) | O | When the enrolment invitation was first sent. | |
| lastInvitationSentAt | String (timestamp) | O | When an invitation was most recently re-sent. | |
| note | String (max 2000) | O | Y | Free-text administrative note. Unstructured; content not surveyed. See section 2 Risks. |
| isFace | Boolean | M | *Derived.* Whether the member holds a Face card, computed from grade. |
|
| actionRequired | Boolean | M | *Derived.* Whether the record is missing information required to complete enrolment. | |
| actionMessage | String | M | *Derived.* Which details are missing, as a readable list. Empty when actionRequired is false. |
|
| requiresPaymentInstrumentUpdate | Boolean | M | *Derived.* Whether any membership awaits a renewed payment method. | |
| paymentInstrumentUpdateDeadline | String (timestamp) | O | *Derived.* Earliest such deadline across the member's memberships. | |
| createdAt | String (timestamp) | M | When the record was created. | |
| updatedAt | String (timestamp) | O | When the record was last modified. | |
| createdBy.type | String (enum) | M | Actor category. Values in 4.6.12. | |
| createdBy.id | String | M | Actor identifier. | |
| createdBy.name | String | O | Y | Actor display name. |
| createdBy.email | String | O | Y | Actor email address. |
Grain: one record per enrolment in a tier. A member may hold several concurrently — a base tier plus upgrades or add-ons.
Primary key: id · Injected key: memberId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier for the enrolment. | |
| memberId | String (UUID) | M | *Injected.* The member holding this membership. | |
| tierId | String | M | Tier enrolled in. Resolve against tier. |
|
| eligibilityRuleId | String | O | The tier rule under which the member qualified. Determines price, payment options and quota. Absent on older enrolments. | |
| paymentId | String (UUID) | O | The payment that purchased this membership. | |
| status | String (enum) | M | Membership lifecycle state. Values in 4.6.2. Note the treatment of converted and scheduled. |
|
| paymentType | String (enum) | M | How the membership is funded. Values in 4.6.3. | |
| startDate | String (timestamp) | M | Start of the membership term. A full timestamp, not a date. | |
| endDate | String (timestamp) | M | End of the membership term. A full timestamp. | |
| autoRenewal | Boolean | O | Whether the membership renews automatically at term end. | |
| statusReason | String | O | Narrative accompanying the current status. | |
| unsubscribedAt | String (timestamp) | O | When the member opted out. | |
| unsubscribedBy.id | String | O | Identifier of the party that performed the opt-out. | |
| unsubscribedBy.type | String (enum) | O | Actor category. Values in 4.6.12. | |
| unsubscribedBy.name | String | O | Y | Actor display name. |
| cancelledAt | String (timestamp) | O | When the membership was cancelled. | |
| paymentSchedule | String (enum) | O | one_time or installment. |
|
| totalInstallments | Integer | O | Instalments in the current arrangement. Resets if the payment method changes mid-term. | |
| paidInstallments | Integer | O | Instalments collected to date. | |
| originalTotalInstallments | Integer | O | Instalments agreed at enrolment. Use for lifetime counts — survives a mid-term change of payment method. | |
| installmentAmountValue | Integer (minor units) | O | Amount of each instalment. | |
| lastInstallmentAmountValue | Integer (minor units) | O | Amount of the final instalment where it differs to absorb rounding. | |
| nextInstallmentDate | String (date) | O | When the next instalment falls due. | |
| installmentStatus | String (enum) | O | active, suspended or completed. |
|
| paymentPeriodMonths | Integer | O | Length of the payment period in months. | |
| ddsChargeAmountValue | Integer (minor units) | O | Salary-deduction charge where it differs from the tier fee. Set on mid-term conversions, where the member owes only the pro-rated difference, and on dependants, where it is the pro-rated price the dependant was charged (one-time or instalment plan total). When absent, the tier fee applies. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| pendingRenewalSince | String (timestamp) | O | When the membership entered payment recovery. | |
| pendingRenewalReason | String (enum) | O | instrument_failed or retry_exhausted. |
|
| recoveryDeadlineAt | String (timestamp) | O | Deadline for restoring payment before the membership lapses. | |
| renewsMembershipId | String (UUID) | O | The membership this one renews. Follow for continuous-tenure analysis. | |
| convertsMembershipId | String (UUID) | O | Set on the successor of a mid-term upgrade, referencing the source membership. | |
| convertedToMembershipId | String (UUID) | O | Set on the source, referencing its successor. | |
| convertedAt | String (timestamp) | O | When the conversion took effect. The source membership's effective end date. | |
| requiresPaymentInstrumentUpdate | Boolean | M | *Derived.* Whether this membership awaits a renewed payment method. | |
| paymentInstrumentUpdateDeadline | String (timestamp) | O | *Derived.* The deadline for doing so. | |
| createdAt | String (timestamp) | O | When the enrolment was created. |
Grain: one record per membership per monthly billing period.
Injected keys: membershipId, memberId
> Authoritative for salary-deduction reconciliation. A salary-deducted membership records a single payment for its entire term, so payment alone cannot identify which months were billed. This dataset is that record.
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| membershipId | String (UUID) | M | *Injected.* The membership being billed. | |
| memberId | String (UUID) | M | *Injected.* The member. | |
| periodMonth | String (period) | M | Billing period, YYYY-MM. |
|
| state | String (enum) | M | emitted, confirmed or released. Only confirmed indicates money left payroll. Values in 4.6.7. |
|
| amountValue | Integer (minor units) | M | Amount billed for the period. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| feedId | String (UUID) | M | The payroll batch carrying the line. Resolve against payroll_feed. |
|
| interfaceLineId | Integer | O | The line within that batch. Resolve against payroll_feed_line. |
|
| emittedAt | String (timestamp) | M | When the deduction line was raised. | |
| confirmedAt | String (timestamp) | C | When payroll confirmed the deduction. Present only when state = confirmed. |
|
| releasedAt | String (timestamp) | C | When the attempt was abandoned. Present only when state = released. |
|
| releaseReason | String | O | Why the period was released. |
Grain: one record per family member recorded against a primary member. A family record denotes a known relative; the person becomes a dependant member only upon enrolment.
Injected key: primaryMemberId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| primaryMemberId | String (UUID) | M | *Injected.* The primary member this family record belongs to. | |
| memberId | String | M | Y | HRMS person identifier for the family member. |
| relation | String | O | Relationship to the primary member. Resolve against member_subtype. Empty where the HRMS relationship type has no configured equivalent. |
|
| dependantId | String | O | Set once the person has been enrolled as a dependant member. Presence marks the family record as converted. | |
| dependantStatus | String | O | Enrolment state of the resulting dependant. | |
| name | String | O | Y | Given name as held in HRMS. |
| surname | String | O | Y | Family name as held in HRMS. |
| String | O | Y | Email address as held in HRMS. | |
| phone | String | O | Y | Mobile number as held in HRMS. |
| birthdate | String (date) | O | Y | Date of birth. Determines eligibility against dependant age limits. |
| contactStatus | String | O | Whether the relationship remains current in HRMS. | |
| error | String | O | Readable explanation of why the family member cannot currently be enrolled, most commonly incomplete contact details or an inactive HRMS relationship. |
Grain: one record per companion registered by a member. Companions are guests a member may bring to venues; they hold no membership.
Injected key: memberId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| memberId | String (UUID) | M | *Injected.* The member who registered the companion. | |
| name | String | M | Y | Given name. |
| surname | String | M | Y | Family name. |
| gender | String (enum) | M | Y | male or female. |
| addedAt | String (timestamp) | M | When the companion was registered. | |
| status | String (enum) | M | active or inactive. |
Grain: one record per document held against a member. Metadata only — document contents are not delivered.
Injected key: memberId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| memberId | String (UUID) | M | *Injected.* The member the document belongs to. | |
| id | String (UUID) | M | Unique identifier for the document. | |
| name | String | M | Y | File name as supplied. |
| documentType | String | O | Classification of the document. | |
| status | String (enum) | M | active or archived. |
|
| uploadedAt | String (timestamp) | M | When the document was provided. | |
| uploadedBy.type | String (enum) | M | Actor category. Values in 4.6.12. | |
| uploadedBy.id | String | M | Actor identifier. | |
| uploadedBy.name | String | O | Y | Actor display name. |
| filePath | String | M | Internal storage reference. Delivered as an opaque string; not resolvable outside EPC. |
Grain: one record per acceptance of a policy document, including superseded acceptances. The complete consent history is therefore present.
Injected key: memberId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| memberId | String (UUID) | M | *Injected.* The member who accepted. | |
| documentId | String | M | The document accepted. Resolve against policy_document. |
|
| documentType | String (enum) | M | Kind of document. Values in 4.6.17. | |
| version | Integer | M | Version accepted. Consent is version-specific: a new version requires a fresh acceptance. | |
| entityType | String (enum) | M | What the document was bound to. Values in 4.6.17. | |
| entityId | String | M | Identifier of that entity. | |
| targetGroup | String (enum) | O | Audience to which the document applies. Values in 4.6.17. | |
| status | String (enum) | M | State of the acceptance: accepted or waiting. Values in 4.6.17. |
|
| acceptedAt | String (timestamp) | M | When the acceptance was recorded. | |
| isCurrent | Boolean | M | *Derived.* true for the acceptance in force; false for superseded acceptances. |
Grain: one record per collection attempt, successful or otherwise.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier for the attempt. | |
| memberId | String (UUID) | M | The member being charged. | |
| dependantId | String | O | Set where the charge relates to a dependant's membership. | |
| tierId | String | M | Tier being paid for. | |
| eligibilityRuleId | String | M | Rule that determined the price. | |
| invoiceId | String (UUID) | O | Invoice raised for this payment. | |
| paymentType | String (enum) | M | Funding route. Values in 4.6.3. | |
| provider | String (enum) | M | cpg (card payment gateway) or dds (salary deduction). |
|
| paymentReason | String (enum) | O | Why the charge was raised. Values in 4.6.5. | |
| orderCode | String | O | Order reference exchanged with the payment gateway. Card payments only. | |
| refId | String | O | Gateway-side reference for the order. Card payments only. | |
| cpgOrderStatus | String | O | Last order status string returned by the payment gateway, as received. Card payments only. | |
| amountValue | Integer (minor units) | M | Amount charged. | |
| currency | String | M | ISO currency code. | |
| exponent | Integer | M | Decimal places. | |
| totalFeeValue | Integer (minor units) | O | Full fee, where this payment covers only part of it. | |
| status | String (enum) | M | Outcome of the attempt. Values in 4.6.4. | |
| statusReason | String | O | Narrative explanation of the outcome. | |
| errorCode | String | O | Machine-readable failure code. Basis for decline analysis. | |
| recurringType | String (enum) | O | CIT (member present) or MIT (taken automatically). |
|
| installmentNumber | Integer | O | Position of this instalment in the plan. | |
| totalInstallments | Integer | O | Instalments in the plan. | |
| retryCount | Integer | O | Retries following a decline for insufficient funds. | |
| transientRetryCount | Integer | O | Retries following a technical failure. Counted separately from declines. | |
| nextRetryAt | String (timestamp) | O | When the next retry is scheduled. | |
| transientAdminAlerted | Boolean | O | Whether a technical-failure alert has been raised for this payment. | |
| parentPaymentId | String (UUID) | O | The originating payment, for retries and instalments. | |
| renewalMembershipId | String (UUID) | O | Membership being renewed by this payment. | |
| scheduledStartDate | String (date) | O | Start of the term the renewal will cover. | |
| scheduledEndDate | String (date) | O | End of that term. | |
| convertsMembershipId | String (UUID) | O | Membership being upgraded away from. The amount is the pro-rated difference, not the target tier's full fee. | |
| refundedAmountValue | Integer (minor units) | O | Total refunded against this payment to date. | |
| refundedReasonCode | String (enum) | O | Reason for the most recent refund. Full history in payment_refund. Values in 4.6.6. |
|
| refundedReasonDetails | String (max 500) | C | Y | Free-text detail. Present when refundedReasonCode = other. |
| refundedAt | String (timestamp) | O | When the most recent refund was issued. | |
| refundedBy | String | O | Identifier of the party that issued the most recent refund. | |
| createdAt | String (timestamp) | M | When the attempt was raised. | |
| updatedAt | String (timestamp) | O | When the record was last modified. | |
| completedAt | String (timestamp) | O | When the attempt completed. For salary deduction this is set at enrolment, before money moves — do not use as a collection date. See 4.4.6. | |
| deductedAt | String (timestamp) | C | Salary deduction only. When payroll confirmed the money was taken. The authoritative collection date for deducted memberships. |
Grain: one record per individual refund. A payment may be refunded more than once, and partially.
Primary key: id · Injected key: paymentId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| paymentId | String (UUID) | M | *Injected.* The payment being refunded. | |
| id | String (UUID) | M | Unique identifier for the refund. | |
| amountValue | Integer (minor units) | M | Amount refunded. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| reasonCode | String (enum) | M | Reason for the refund. Values in 4.6.6. | |
| reasonDetails | String (max 500) | C | Y | Free-text detail. Mandatory when reasonCode = other. |
| refundType | String (enum) | M | cpg (to card) or dds (through payroll). |
|
| refundedAt | String (timestamp) | M | When the refund was issued. | |
| payrollFeedId | String (UUID) | C | Payroll batch carrying the refund. Salary-deduction refunds only. | |
| payrollPushedAt | String (timestamp) | C | When payroll confirmed the refund. While absent, a payroll refund remains in flight. | |
| refundedBy | String | M | Identifier of the party that issued the refund. |
Grain: one record per ledger movement — a payment taken or a refund given.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier. | |
| memberId | String (UUID) | M | The member. | |
| paymentId | String (UUID) | M | Payment the movement belongs to. | |
| type | String (enum) | M | payment or refund. |
|
| status | String (enum) | M | completed, failed or pending. |
|
| amountValue | Integer (minor units) | M | Amount moved. | |
| currency | String | M | ISO currency code. | |
| exponent | Integer | M | Decimal places. Stamped at extraction; see 4.4.3. | |
| description | String | M | Readable description of the movement. | |
| tierName | String | M | Tier name as at the time of the movement. Retained so historical statements are not rewritten by later renaming. | |
| reasonCode | String (enum) | C | Refund reason. Refund movements only. Values in 4.6.6. | |
| reasonDetails | String (max 500) | O | Y | Free-text refund detail. |
| refundEntryId | String (UUID) | C | The specific refund settled. Resolve against payment_refund. |
|
| actorId | String | O | Identifier of the party that initiated the movement, where a person did. | |
| createdAt | String (timestamp) | M | When the movement was recorded. | |
| updatedAt | String (timestamp) | O | When the record was last modified. |
Grain: one record per invoice or credit note.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier. | |
| paymentId | String (UUID) | M | Payment the document relates to. | |
| memberId | String (UUID) | M | The member. | |
| tierId | String | M | Tier concerned. | |
| membershipId | String (UUID) | O | Membership concerned. | |
| refundEntryId | String (UUID) | C | On credit notes, the refund being documented. | |
| type | String (enum) | M | invoice or credit_note. |
|
| trxNumber | String | M | Document number as issued. | |
| trxDate | String (date) | M | Document date. | |
| trxCurrency | String | M | Currency of the document. | |
| exponent | Integer | M | Decimal places applying to the header totals. Stamped at extraction; see 4.4.3. | |
| comments | String | M | Narrative shown on the document. | |
| internalNotes | String | M | Y | Allocation reference. Embeds the employee number and a short order reference. |
| totalAmountValue | Integer (minor units) | M | Total including tax. | |
| totalBaseAmountValue | Integer (minor units) | M | Total excluding tax. | |
| totalTaxAmountValue | Integer (minor units) | M | Tax portion. | |
| arSubmission | Boolean | M | Whether the document is submitted to Accounts Receivable. false for salary-deducted memberships, which are documented but not posted to AR. |
|
| erpInvoiceNumber | String | O | Number assigned by the finance system. | |
| erpErrorDetails | String | O | Failure detail returned by the finance system. | |
| erpSubmittedAt | String (timestamp) | O | When the document was submitted. | |
| erpResponseAt | String (timestamp) | O | When the finance system responded. | |
| pdfStatus | String (enum) | M | pending, generated or failed. |
|
| pdfGeneratedAt | String (timestamp) | O | When the printable document was produced. | |
| pdfError | String | O | Error from the last failed generation attempt. | |
| pdfFileKey | String | O | Internal storage reference for the generated PDF. Opaque outside EPC. | |
| retryCount | Integer | M | Submission attempts made. | |
| nextRetryAt | String (timestamp) | O | When the next submission attempt is scheduled. | |
| status | String (enum) | M | pending, submitted, completed or failed. |
|
| createdAt | String (timestamp) | M | When the document was raised. | |
| updatedAt | String (timestamp) | O | When it was last modified. | |
| createdBy | String | M | Identifier of the party that raised it. |
Grain: one record per line on an invoice or credit note.
Injected key: invoiceId
> Scale exception. The monetary fields on this dataset are in major units (decimal AED), whereas invoice header totals are in minor units. See 4.4.2.
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| invoiceId | String (UUID) | M | *Injected.* Parent document. | |
| lineNumber | Integer | M | Position of the line on the document. | |
| description | String | M | What is being charged. | |
| unitSellingPrice | Number (major units) | M | Price excluding tax, as decimal AED. | |
| quantityOrdered | Integer | M | Quantity. | |
| uomCode | String | M | Unit of measure. | |
| taxAmount | Number (major units) | M | Tax on the line, as decimal AED. Negative on credit notes. | |
| taxRateCode | String | M | Tax rate applied. | |
| segment2 | String | M | Cost centre in the enterprise chart of accounts. | |
| segment3 | String | M | Nominal code. | |
| segment4 | String | M | Subnominal code. | |
| distributionAmount | Number (major units) | M | Amount posted to that account combination. |
Grain: one record per batch submitted to payroll.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier for the batch. | |
| type | String (enum) | M | Nature of the batch. Values in 4.6.9. | |
| status | String (enum) | M | Batch outcome. Values in 4.6.8. | |
| periodMonth | String (period) | M | Payroll period, YYYY-MM. |
|
| batchName | String | M | Batch identifier as presented to payroll. | |
| fileBatchName | String | M | File-level batch identifier. | |
| s3Bucket | String | M | Internal storage location of the submitted file. Opaque outside EPC. | |
| s3Key | String | M | Internal storage reference of the submitted file. Opaque outside EPC. | |
| applicationName | String | M | Payroll application targeted. | |
| totalLines | Integer | M | Lines in the batch. | |
| successCount | Integer | M | Lines accepted by payroll. | |
| failedCount | Integer | M | Lines rejected by payroll. | |
| totalAmountValue | Integer (minor units) | M | Total value of the batch. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| interfaceLoadId | String | O | Reference returned by payroll on receipt. | |
| failureReason | String | O | One-line explanation where the batch failed. | |
| failedAt | String (timestamp) | O | When the batch was marked failed. | |
| submittedAt | String (timestamp) | O | When the batch was submitted. | |
| completedAt | String (timestamp) | O | When processing completed. | |
| createdAt | String (timestamp) | M | When the batch was created. | |
| updatedAt | String (timestamp) | O | When it was last modified. | |
| createdBy | String | M | Originator of the batch. |
Grain: one record per deduction or refund line. The most direct join between programme data and enterprise payroll records.
Injected keys: feedId, periodMonth
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| feedId | String (UUID) | M | *Injected.* Batch the line belongs to. | |
| periodMonth | String (period) | M | *Injected.* Payroll period. | |
| interfaceLineId | Integer | M | Line number within the batch. | |
| staffId | String | M | Y | Employee number the deduction is raised against. Primary payroll join key. |
| memberId | String (UUID) | M | The member. | |
| membershipId | String (UUID) | M | The membership. | |
| tierId | String | O | Tier the membership belongs to. | |
| paymentId | String (UUID) | O | Payment the line settles, resolved once payroll confirms. | |
| isDependant | Boolean | M | Whether the deduction covers a dependant's membership. | |
| primaryMemberId | String (UUID) | C | The employee bearing the cost, where the line relates to a dependant. | |
| elementType | String | M | Payroll element the deduction posts to. | |
| applicationName | String | M | Payroll application targeted. | |
| amountValue | Integer (minor units) | M | Amount to deduct. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| remarks | String | M | Y | Narrative shown on the payslip. Carries the dependant reference on dependant lines. |
| payrollDate | String (date) | M | Date the deduction is scheduled for. | |
| successFlag | String (enum) | O | Y or N — whether payroll accepted the line. Primary reconciliation field. Absent while awaiting response. |
|
| errorDetails | String | O | Reason for rejection. | |
| refundEntryId | String (UUID) | C | Refund returned by this line, on refund batches. | |
| membershipType | String | O | Membership descriptor, on seasonal batches. | |
| costingLob | String | O | Line of Business, seasonal batches (payroll VALUE_7). Absent on lines before Oct 2026. | |
| costingRc | String | O | Responsibility Centre, seasonal batches (VALUE_8). | |
| costingAc | String | O | Nominal, seasonal batches (VALUE_9). | |
| costingSubNominal | String | O | Sub Nominal, seasonal batches (VALUE_10). | |
| costingAnalysisKey | String | O | Analysis Key, seasonal batches (VALUE_11). | |
| costingAmount | String | O | Legacy: the amount, on seasonal lines before Oct 2026 only. | |
| glJournalId | String (UUID) | O | GL batch this line was aggregated into. | |
| postedToGlAt | String (timestamp) | O | When the line was included in a GL submission. |
Grain: one record per offer redeemed at a partner.
Primary key: id
> redemption and venue_checkin are disjoint. An offer is either redeemable or a venue-access offer, never both. See 4.6.10.
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier. | |
| memberId | String (UUID) | M | The member who redeemed. | |
| memberDisplayId | String | M | The member's membership number, as quoted at the point of sale. | |
| memberName | String | M | Y | Given name at the time of redemption. |
| memberSurname | String | M | Y | Family name at the time of redemption. |
| offerId | String (UUID) | M | Offer redeemed. | |
| partnerId | String (UUID) | M | Partner honouring the offer. | |
| locationId | String | M | Partner location. | |
| partnerUserId | String (UUID) | M | Partner staff member who processed the redemption. | |
| offerName | String | M | Offer name as at the time of redemption. | |
| locationName | String | M | Location name as at the time of redemption. | |
| offerType | String (enum) | M | discount, special_price or special_deal. Venue access is excluded by definition. |
|
| transactionAmountValue | Integer (minor units) | M | Amount spent by the member before discount. | |
| discountAmountValue | Integer (minor units) | M | Amount saved by the member. Principal programme value measure. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| notes | String (max 500) | O | Y | Free-text note entered by partner staff. |
| status | String (enum) | M | completed or voided. voided is reserved: no current EPC process produces it, so every record carries completed at time of writing. Should it appear, exclude voided from value totals. |
|
| voidedReason | String | O | Reserved alongside voided; not populated by any current process. |
|
| redeemedAt | String (timestamp) | M | When the redemption took place. | |
| createdAt | String (timestamp) | M | When the record was created. | |
| createdBy.type | String (enum) | M | Actor category. Values in 4.6.12. | |
| createdBy.id | String | M | Actor identifier. | |
| createdBy.name | String | O | Y | Actor display name. |
Grain: one record per visit to a venue offering Lifestyle Hub access.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier. | |
| memberId | String (UUID) | M | The member checking in. | |
| memberDisplayId | String | M | The member's membership number. | |
| memberName | String | M | Y | Given name at the time of the visit. |
| memberSurname | String | M | Y | Family name at the time of the visit. |
| offerId | String (UUID) | M | Venue offer. | |
| partnerId | String (UUID) | M | Partner operating the venue. | |
| locationId | String | M | Venue location. | |
| partnerUserId | String (UUID) | M | Venue staff member who admitted the party. | |
| offerName | String | M | Offer name as at the time of the visit. | |
| locationName | String | M | Location name as at the time of the visit. | |
| accessType | String (enum) | O | Entitlement used: individual, couple or family. Determines who entered free. Absent on visits predating per-entitlement quotas; see 6.1. |
|
| isPaid | Boolean | M | Whether any charge was raised for the visit. | |
| paymentAmountValue | Integer (minor units) | M | Total charged. | |
| excessQuotaPriceValue | Integer (minor units) | M | Entry fee charged to the member where the day's allocation was already exhausted. | |
| isExcessQuota | Boolean | M | Whether the visit occurred after the allocation was exhausted. | |
| quotaConsumed | Boolean | M | Whether the visit consumed a place from the day's allocation. | |
| quotaRecovered | Boolean | O | Whether that place was returned at check-out. Absent while the party remains on site. | |
| additionalGuests.adultCount | Integer | M | Paying adult guests beyond the member's own party. | |
| additionalGuests.childCount | Integer | M | Paying child guests. | |
| additionalGuests.adultPriceValue | Integer (minor units) | M | Price charged per adult guest. | |
| additionalGuests.childPriceValue | Integer (minor units) | M | Price charged per child guest. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| offerLocationDate | String | M | Composite grouping key of offer, location and date. | |
| status | String (enum) | M | checked_in, checked_out or cancelled. |
|
| checkInTime | String (timestamp) | M | Arrival. | |
| checkOutTime | String (timestamp) | O | Departure. Dwell time is the difference between the two. | |
| cancelledAt | String (timestamp) | O | When the visit was cancelled. | |
| createdAt | String (timestamp) | M | When the record was created. | |
| createdBy.type | String (enum) | M | Actor category. Values in 4.6.12. | |
| createdBy.id | String | M | Actor identifier. | |
| createdBy.name | String | O | Y | Actor display name. |
Grain: one record per companion on a visit.
Injected key: checkinId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| checkinId | String (UUID) | M | *Injected.* The visit. | |
| id | String | M | Identifier of the companion. | |
| name | String | M | Y | Given name. May relate to a person who is not an employee. |
| surname | String | M | Y | Family name. |
| relationship | String (enum) | M | adult or child. A pricing category, not a family relationship. |
|
| isPaid | Boolean | M | Whether this companion was charged for. | |
| priceValue | Integer (minor units) | M | Amount charged. Zero where the companion entered free. | |
| currency | String | M | ISO currency code. Stamped at extraction. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| source | String (enum) | M | How the companion was identified. Values in 4.6.13. | |
| isMember | Boolean | M | Whether the companion holds a membership in their own right. | |
| isSpouse | Boolean | M | Whether the companion occupied the spouse place. At most one per visit. |
Grain: one record per member per distinct normalised query. A rolling snapshot, not an event log.
Primary key: composite of memberId and normalizedQuery
> Repeating a search does not add a record; it overwrites searchedAt on the existing one. Each member retains at most 100 records, the oldest being pruned, and a record expires 90 days after its last search. The dataset therefore answers "what has each member searched for recently", not "how many searches were made". Search counts and long-run trends cannot be derived from it, and a full extract carries only the trailing 90 days.
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| memberId | String (UUID) | M | Y | The member who searched. Attribution renders these records personal data. |
| originalQuery | String | M | Y | The query as most recently typed, verbatim. |
| normalizedQuery | String | M | The query lower-cased and trimmed. Grouping key. | |
| searchedAt | String (timestamp) | M | When this query was most recently searched by the member. |
Grain: one record per tier. A tier is a purchasable level of membership with a fee, a term and eligibility rules.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String | M | Unique identifier. | |
| name | String | M | Internal name. | |
| label | String | M | Name presented to members. | |
| description | String | O | Descriptive copy. | |
| color | String | O | Brand colour used in member-facing presentation. | |
| tierType.id | String | M | Tier type. Resolve against tier_type. |
|
| tierType.group | String (enum) | M | base, upgrade or add_on. |
|
| feeValue | Integer (minor units) | M | Standard fee for the term, in minor units. The major-unit fee shown in EPC user interfaces is derived from this value and is not delivered; see 4.4.2. |
|
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| startDate | String (timestamp) | M | Start of the window during which the tier may be purchased. A full timestamp, not a date. | |
| endDate | String (timestamp) | M | End of that window. A full timestamp; end-of-day values appear as ...T19:59:59.999Z. |
|
| membershipDuration | Integer | O | Length of the resulting membership, in months. | |
| membershipEndDate | String (date) | O | Fixed end date, used instead of a duration for fixed-season tiers. | |
| taxable | Boolean | M | Whether the fee attracts VAT. Reflects the current setting only. This value changes over a tier's life; historical VAT analysis must use audit_log. See 4.4.7. |
|
| financeConfig.costCentre | String | O | Cost centre revenue posts to. | |
| financeConfig.nominal | String | O | Nominal code. | |
| financeConfig.subnominal | String | O | Subnominal code. | |
| financeConfig.analysisKey | String | O | Analysis key. | |
| financeConfig.erpCommentPrefix | String | O | Narrative prefix applied to finance postings. | |
| ddsConfig.staffElementType | String | O | Payroll element used to deduct from an employee. | |
| ddsConfig.dependantElementType | String | O | Payroll element used for a dependant's membership. | |
| status | String (enum) | M | Tier lifecycle state: pending, active, inactive or expired. Values in 4.6.16. |
|
| statusReason | String | O | Narrative accompanying the current status. | |
| createdAt | String (timestamp) | M | When the tier was created. | |
| updatedAt | String (timestamp) | O | When it was last modified. | |
| createdBy.type / .id / .name | Object | M | Originator. |
Grain: one record per rule on a tier. Rules determine who may purchase a tier, on what payment terms, and how many places exist.
Injected key: tierId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| tierId | String | M | *Injected.* Tier the rule belongs to. | |
| id | String | M | Rule identifier. Referenced by membership.eligibilityRuleId. |
|
| name | String | M | Rule name. | |
| paymentTypes | Array[String] | M | Payment methods the rule permits. Values in 4.6.3; free_dependant never appears on a rule. |
|
| paymentPeriod | String (enum) | M | Instalment period offered under the rule: monthly or one_time. Values in 4.6.18. |
|
| quota | Integer | O | Maximum places available. Absent denotes unlimited. | |
| status | String (enum) | M | active or inactive. |
|
| conditions[].key | String | M | Member attribute tested. | |
| conditions[].logicalOperator | String (enum) | M | Comparison applied. Values in 4.6.14. | |
| conditions[].value | Mixed | O | Value compared against. May be string, number, boolean or array. |
Grain: one record per member per tier. Records consumption of an eligibility rule's quota.
Primary key: composite of tierId and memberId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| tierId | String | M | Tier enrolled in. | |
| memberId | String (UUID) | M | Member enrolled. | |
| eligibilityRuleId | String | M | Rule whose quota the place was taken from. | |
| paymentType | String (enum) | M | Payment method used. | |
| enrolledAt | String (timestamp) | M | When the place was taken. | |
| status | String (enum) | M | active or expired. No expiry timestamp is carried; see 4.4.7 for how to date the transition. |
Grain: one record per offer.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier. | |
| offerId | String | M | Reference presented to members. | |
| name | String | M | Offer name. | |
| partnerId | String (UUID) | M | Partner providing the offer. | |
| partnerLocations | Array[String] | M | Locations at which the offer is honoured. An empty array denotes all of the partner's locations. | |
| offerType | String (enum) | M | Nature of the offer. Values in 4.6.10. | |
| percentage | Number | C | Discount percentage. Discount offers only. | |
| priceValue | Integer (minor units) | C | Fixed member price. Special-price offers only. | |
| categories | Array[String] | M | Benefit categories. Resolve against benefit_category. |
|
| subcategories | Array[String] | O | Benefit subcategories. Resolve against benefit_subcategory. |
|
| keywords | Array[String] | O | Search terms associated with the offer. | |
| label | String | O | Merchandising label. | |
| badges | Array[String] | O | Merchandising badges. | |
| isFeatured | Boolean | M | Whether the offer is promoted. | |
| isVisibleToAll | Boolean | M | Whether the offer bypasses eligibility rules and is shown to all members. | |
| startDate | String (date) | M | Start of the redemption window. | |
| endDate | String (date) | O | End of the redemption window. | |
| viewStartDate | String (date) | M | Start of the visibility window, often wider than the redemption window. | |
| viewEndDate | String (date) | O | End of the visibility window. | |
| shortDescription | String (max 500) | M | Summary presented in listings. | |
| longDescription | String | O | Full descriptive copy. | |
| description.discountInfo | String | O | What the offer provides. | |
| description.includes | String | O | What is included. | |
| description.guests | String | O | Guest entitlements. | |
| description.howToBook | String | O | Booking instructions. | |
| description.howToRedeem | String | O | Redemption instructions. | |
| description.termsAndConditions | String | O | Terms attached to the offer. | |
| description.disclaimer | String | O | Disclaimer text. | |
| quota | Integer | O | Capacity limit; absent or null denotes unlimited. Meaning depends on offerType. For redeemable offers it is the lifetime number of redemptions permitted, enforced against completedRedemptionsCount. For venue offers it is a legacy daily capacity, superseded by the per-entitlement quotas in lifestyleHubDetails.accessOptions[] wherever those are present. |
|
| quotaCheckedIn | Integer | M | Venue offers: places occupied today, across all entitlement levels. | |
| quotaCheckedOut | Integer | M | Venue offers: places released today, across all entitlement levels. | |
| quotaSnapshotDate | String (date) | O | Day to which the occupancy counters relate. | |
| accessQuotaCounters.*.checkedIn | Integer | O | Venue offers: places occupied today under one entitlement level. The key is individual, couple or family. Shares quotaSnapshotDate. |
|
| accessQuotaCounters.*.checkedOut | Integer | O | Venue offers: places released today under that entitlement level. | |
| completedRedemptionsCount | Integer | M | Redeemable offers: lifetime count of completed redemptions. | |
| lifestyleHubDetails.accessType | Array[String] | C | Entitlement levels offered: individual, couple, family. Mirror of accessOptions[].accessType. |
|
| lifestyleHubDetails.accessOptions[].accessType | String (enum) | C | Entitlement level: individual, couple or family. |
|
| lifestyleHubDetails.accessOptions[].quota | Integer | O | Daily capacity for that entitlement level; absent or null denotes unlimited. Authoritative daily capacity for venue offers. Absent on offers configured before per-entitlement quotas existed; those fall back to quota. |
|
| lifestyleHubDetails.adultPriceValue | Integer (minor units) | O | Standard adult companion price. | |
| lifestyleHubDetails.childPriceValue | Integer (minor units) | O | Standard child companion price. | |
| lifestyleHubDetails.guestDayPassAdultPriceValue | Integer (minor units) | O | Adult day-pass price for additional guests. | |
| lifestyleHubDetails.guestDayPassChildPriceValue | Integer (minor units) | O | Child day-pass price for additional guests. | |
| lifestyleHubDetails.excessQuotaDayPassAdultPriceValue | Integer (minor units) | O | Adult price once the daily allocation is exhausted. | |
| lifestyleHubDetails.excessQuotaDayPassChildPriceValue | Integer (minor units) | O | Child price once the daily allocation is exhausted. | |
| lifestyleHubDetails.accessDescription | String | O | Guidance on venue access. | |
| lifestyleHubDetails.howToRegister | String | O | Registration instructions. | |
| lifestyleHubDetails.additionalGuests | String | O | Guidance on additional guests. | |
| lifestyleHubDetails.cancelWindowMinutes | Integer | O | Cancellation window, in minutes. | |
| currency | String | M | ISO currency code. Stamped at extraction; see 4.4.3. | |
| exponent | Integer | M | Decimal places. Stamped at extraction. | |
| heroImagePath | String | O | Internal storage reference for the primary image. Opaque outside EPC. | |
| additionalImagePaths | Array[String] | O | Internal storage references for further images. Opaque outside EPC. | |
| status | String (enum) | M | Offer lifecycle state: pending, active, inactive or expired. Values in 4.6.16. |
|
| statusReason | String | O | Narrative accompanying the current status. | |
| createdAt | String (timestamp) | M | When the offer was created. | |
| updatedAt | String (timestamp) | O | When it was last modified. | |
| createdBy.type / .id / .name | Object | M | Originator. |
Grain: one record per rule on an offer. Determines which members are shown the offer.
Injected key: offerId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| offerId | String (UUID) | M | *Injected.* Offer the rule belongs to. | |
| id | String | M | Rule identifier. | |
| name | String | M | Rule name. | |
| status | String (enum) | M | active or inactive. |
|
| conditions[].key | String | M | Member attribute tested. | |
| conditions[].logicalOperator | String (enum) | M | Comparison applied. Values in 4.6.14. | |
| conditions[].value | Mixed | O | Value compared against. |
Grain: one record per partner business.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String (UUID) | M | Unique identifier. | |
| brandName | String | M | Trading name presented to members. | |
| legalName | String | O | Registered company name. | |
| brandLogoPath | String | O | Internal storage reference for the logo. Opaque outside EPC. | |
| heroImagePath | String | O | Internal storage reference. Opaque outside EPC. | |
| additionalImagePaths | Array[String] | O | Internal storage references for further images. Opaque outside EPC. | |
| partnerTier | String | O | Commercial classification of the partnership. | |
| partnerGroup | String | O | Commercial grouping. | |
| businessAddress | String | M | Registered address. | |
| city | String | M | City. | |
| country | String | M | Country. | |
| website | String | O | Public website. | |
| tradeLicenseNumber | String | O | Trade licence reference. | |
| contractId | String | M | Contract reference governing the partnership. | |
| contractStartDate | String (date) | M | Contract start. | |
| contractEndDate | String (date) | O | Contract end. Absent denotes open-ended. | |
| accountAgent | String | O | Y | Person managing the relationship. |
| primaryContact.name | String | O | Y | Named contact at the partner. |
| primaryContact.email | String | O | Y | Contact email address. |
| primaryContact.phone | String | O | Y | Contact telephone number. |
| socialMediaAccounts[].platform | String (enum) | O | Social platform. Values in 4.6.18. | |
| socialMediaAccounts[].url | String | O | Profile URL. | |
| status | String (enum) | M | Partner lifecycle state: pending, active or inactive. Values in 4.6.16. |
|
| statusReason | String | O | Narrative accompanying the current status. | |
| createdAt | String (timestamp) | M | When the partner was created. | |
| updatedAt | String (timestamp) | O | When last modified. | |
| createdBy.type / .id / .name | Object | M | Originator. |
Grain: one record per partner outlet. Coordinates support catchment and proximity analysis.
Injected key: partnerId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| partnerId | String (UUID) | M | *Injected.* Owning partner. | |
| id | String | M | Location identifier. Referenced by redemption and venue_checkin. |
|
| name | String | M | Outlet name. | |
| address | String | M | Street address. | |
| coordinates.latitude | Number | M | Latitude, decimal degrees. | |
| coordinates.longitude | Number | M | Longitude, decimal degrees. | |
| contact.name | String | O | Y | Outlet contact name. |
| contact.email | String | O | Y | Outlet contact email. |
| contact.phone | String | O | Y | Outlet contact telephone. |
| status | String (enum) | M | active or inactive. |
Grain: one record per participating company.
Primary key: id
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String | M | Unique identifier. Referenced by member.company.id. |
|
| name | String | M | Company name. | |
| description | String | O | Description. | |
| companyGroupId | String | M | Parent group. Resolve against company_group. |
|
| bgIds | Array[String] | O | HRMS Business Group identifiers (BG_ID). Direct join key to enterprise organisational structure. | |
| eligibleMemberTypes | Array[String] | M | Member types the company may enrol. Resolve against member_type. |
|
| maxFreeDependants | Integer | M | Free dependant places available to each employee. | |
| hrContact.name | String | M | Y | HR contact name. |
| hrContact.email | String | M | Y | HR contact email address. |
| emailPasswordOnly | Boolean | O | Whether the company is outside SSO, its members using email and password. | |
| status | String (enum) | M | pending, active or inactive. Values in 4.6.16. |
|
| statusReason | String | O | Narrative accompanying the current status. | |
| createdAt | String (timestamp) | M | When the company was created. | |
| updatedAt | String (timestamp) | O | When last modified. | |
| createdBy.type / .id / .name | Object | M | Originator. |
Grain: one record per member subtype configured for a company. Sets dependant enrolment limits.
Injected key: companyId
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| companyId | String | M | *Injected.* The company. | |
| memberSubTypeId | String | M | Subtype being limited. Resolve against member_subtype. |
|
| maxDependants | Integer | M | Number of dependants of this subtype an employee may enrol. | |
| maxUpgradeDependants | Integer | O | Number that may concurrently hold an upgrade tier. Falls back to maxDependants where absent. |
Grain: one record per category, and one per subcategory. Required to resolve offer.categories and offer.subcategories.
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String | M | Category or subcategory identifier. | |
| categoryId | String | C | Parent category. Subcategories only. | |
| name | String | M | Display name. | |
| description | String | O | Description. | |
| sortOrder | Integer | C | Presentation order. Categories only. | |
| icon | String | O | Presentation asset reference: an image reference for categories, an icon name for subcategories. Opaque outside EPC. | |
| mapPinIcon | String | O | Map-pin icon name. Categories only. | |
| status | String (enum) | M | pending, active or inactive for categories; active or inactive for subcategories. Values in 4.6.16. |
|
| createdAt | String (timestamp) | C | Creation. Categories only. | |
| updatedAt | String (timestamp) | O | Last modification. Categories only. |
Grain: one record per version of a policy document.
Primary key: composite of id and version
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String | M | Identifier of the document. Together with version, identifies the record. |
|
| documentType | String (enum) | M | Kind of document. Values in 4.6.17. | |
| title | String | M | Title of the document version. | |
| version | Integer | M | Version number. Consent is recorded against a specific version. | |
| content | String | M | Full text of the document version, as presented to the reader. Up to 350 KB. | |
| forceAccept | Boolean | M | Whether this version must be accepted before the reader may continue using the service. | |
| entityType | String (enum) | M | What the document is bound to. Values in 4.6.17. | |
| entityId | String | M | Identifier of that entity. | |
| targetGroup | String (enum) | M | Audience to which the document applies. Values in 4.6.17. | |
| status | String (enum) | M | Document state: active or archived. Applies to the document as a whole, not to individual versions. Values in 4.6.17. |
|
| createdAt | String (timestamp) | M | When the version was created. | |
| updatedAt | String (timestamp) | O | When the document was last modified. |
Four code lists. Each carries id, name, description (optional), status (pending, active or inactive; see 4.6.16), createdAt and updatedAt (optional). The additional columns below carry the analytical value.
| Dataset | Resolves | Additional fields |
|---|---|---|
member_type |
member.memberType, company.eligibleMemberTypes |
hrmsMapping (String, O) — corresponding HRMS employment-type value, permitting a direct join to enterprise HR reference data. |
member_subtype |
member.memberSubType, member.relation, member_family.relation, company_member_subtype.memberSubTypeId |
hrmsMapping (Array[String], O) — corresponding HRMS relationship values. maximumAge (Integer, O) — age limit for dependants of this subtype. tag (String enum, O) — spouse or child for entitlement purposes; absent denotes neither. |
tier_type |
tier.tierType.id |
group (String enum, M) — base, upgrade or add_on. level (Integer, O) — rank within the upgrade ladder. |
company_group |
company.companyGroupId |
type (String enum, O) — internal or external; see 4.6.18. Absent on the earliest configured group. |
Grain: one record per change to any record in the programme. Append-only, indexed on timestamp.
Primary key: id
> The only dataset supporting point-in-time analysis. All other datasets carry current state. This is also the largest dataset in the feed by a substantial margin — see 5.2.
| Field | Type | Req | PII | Description |
|---|---|---|---|---|
| id | String | M | Unique identifier for the change. | |
| entityType | String (enum) | M | Category of record changed. 28 values; see 4.6.15. | |
| entityId | String | M | Identifier of the record changed. Resolve against the corresponding dataset's id. |
|
| action | String | M | Action performed, in the vocabulary of that record type — e.g. create, update, suspend, enroll-tier, approve-id-photo. |
|
| actor.type | String (enum) | M | Actor category. Values in 4.6.12. | |
| actor.id | String | M | Actor identifier. | |
| actor.name | String | O | Y | Actor display name. |
| actor.email | String | O | Y | Actor email address. |
| timestamp | String (timestamp) | M | When the change occurred. | |
| fieldUpdates[].key | String | M | Field changed, expressed as a path, e.g. /status, /memberships/0/endDate. |
|
| fieldUpdates[].operation | String (enum) | M | add, remove, replace or other. |
|
| fieldUpdates[].oldValue | String (JSON) | M | Y | Previous value, JSON-encoded. Truncated beyond 1 KB. |
| fieldUpdates[].newValue | String (JSON) | M | Y | New value, JSON-encoded. Truncated beyond 1 KB. |
| fieldUpdates[].isLarge | Boolean | O | true where the value exceeded 1 KB and was truncated. Treat such values as incomplete. |
|
| isLargeLog | Boolean | M | Whether the change record as a whole exceeded the size threshold. | |
| largeLogPath | String | O | Internal storage reference for overflow values. Opaque outside EPC. | |
| additionalData | Object | O | Y | Context specific to the action, as free-form keys and values. |
All sets below are closed. A value outside these lists indicates a schema change on the EPC side and must be alerted on rather than discarded — see section 2 (Risks) and 5.4.
| Value | Description |
|---|---|
| pending_invite | Record created; invitation not yet sent |
| pending_invitation_acceptance | Invitation sent; not yet accepted |
| pending_approval | Awaiting administrative approval |
| pending_id_photo | Awaiting identity photograph |
| pending_tier | Awaiting tier selection |
| pending_payment | Awaiting payment |
| active | Fully enrolled |
| inactive | No longer participating |
| suspended | Temporarily withdrawn |
| rejected | Application declined |
| Value | Description |
|---|---|
| active | In force |
| scheduled | Purchased in advance; commences at a future date |
| expired | Term ended |
| unsubscribed | Member opted out |
| suspended | Temporarily withdrawn |
| cancelled | Terminated |
| converted | Upgraded mid-term; the successor membership carries the entitlement. Exclude from active membership counts |
| Value | Description |
|---|---|
| credit_card | Paid by card |
| salary_deduction | Deducted through payroll |
| company_paid | Funded by the employer |
| free_dependant | Free dependant place |
| free_of_charge | Complimentary |
| Value | Description |
|---|---|
| initiated | Attempt started |
| pending | Awaiting outcome |
| completed | Collected |
| failed | Declined or errored |
| expired | Not completed within the permitted window |
| partially_refunded | Part of the value returned |
| refunded | Fully returned |
| Value | Description |
|---|---|
| enrollment | First purchase |
| dependant_enrollment | First purchase for a dependant |
| installment | Scheduled instalment |
| dependant_installment | Instalment for a dependant |
| renewal | Renewal of a term |
| dependant_renewal | Renewal of a dependant's term |
| conversion | Mid-term upgrade |
| instrument_update | Verification of a new payment method |
| Value | Description |
|---|---|
| system_error | Fault on the EPC side |
| duplicate_payment | Charged more than once |
| member_request | Requested by the member |
| payment_failure | Collection problem |
| service_unavailability | Benefit could not be provided |
| other | Detail carried in reasonDetails |
| Value | Description |
|---|---|
| emitted | Line raised; not yet confirmed by payroll |
| confirmed | Money left payroll. The authoritative collection signal |
| released | Attempt failed definitively; the period becomes billable again |
| Value | Description |
|---|---|
| generated | Batch built; not yet submitted |
| submitted | Sent to payroll |
| completed | Fully accepted |
| partially_failed | Some lines rejected |
| failed | Batch rejected |
| duplicate | Superseded by another batch |
| Value | Description |
|---|---|
| regular_membership | Standard membership deductions |
| termination | Leaver adjustments |
| face_card | Face card deductions |
| voucher_event | Voucher and event charges |
| seasonal_membership | Fixed-season memberships |
| refund | Amounts returned |
| Value | Description |
|---|---|
| discount | Percentage reduction |
| special_price | Fixed member price |
| special_deal | Bundled or conditional offer |
| lifestyle_hub | Venue access. Appears in venue_checkin, never in redemption |
| Value | Description |
|---|---|
| self_register | Member self-registered |
| backoffice_register | Created by a programme administrator |
| hrms_register | Created from the HRMS feed |
| Value | Description |
|---|---|
| system | Automated process |
| admin | Programme administrator |
| member | The member |
| hr_integration | HRMS interface |
| partner_user | Partner staff |
| Value | Description |
|---|---|
| dependant | An enrolled dependant member |
| hrms | A family member recorded in HRMS who has not enrolled |
| companion | A companion registered by the member |
| primary | The household's primary member |
| Value | Description |
|---|---|
| equals · not_equals | Exact match, or its negation |
| in · not_in | Membership of a set, or its negation |
| less_than · less_than_equal | Numeric or date comparison |
| greater_than · greater_than_equal | Numeric or date comparison |
| is_null · is_not_null | Presence test |
approval, approval_policy, category, company, companyGroup, content, location-association, loyalty-card-session, member, memberSubtype, memberType, notificationTemplate, offer, partner, partner-role, partner_user, payment, policy-document, policy-document-acceptance, redemption, report-run, role, tier, tierConfig, tierType, track-feed, user, venue_checkin.
Note that entityType values reflect historical vocabulary and are not uniformly cased.
Status and type fields not enumerated in their own section above take the following closed sets.
| Dataset(s) | Field | Values |
|---|---|---|
tier, offer |
status |
pending, active, inactive, expired |
partner, company, benefit_category, member_type, member_subtype, tier_type, company_group |
status |
pending, active, inactive |
benefit_subcategory, partner_location, tier_eligibility_rule, offer_eligibility_rule, member_companion |
status |
active, inactive |
member_document |
status |
active, archived |
tier_enrollment |
status |
active, expired |
redemption |
status |
completed, voided (reserved; see 4.5.16) |
venue_checkin |
status |
checked_in, checked_out, cancelled |
invoice |
status |
pending, submitted, completed, failed |
invoice |
pdfStatus |
pending, generated, failed |
invoice |
type |
invoice, credit_note |
transaction |
status |
completed, failed, pending |
transaction |
type |
payment, refund |
membership |
paymentSchedule |
one_time, installment |
membership |
installmentStatus |
active, suspended, completed |
membership |
pendingRenewalReason |
instrument_failed, retry_exhausted |
member |
deactivatedBy |
system, hrms, program_management |
member |
loginMethod |
sso, email_password |
member |
idPhotoStatus |
pending, approved, rejected |
member, member_companion |
gender |
male, female |
member |
maritalStatus |
single, married |
payment |
provider |
cpg, dds |
payment |
recurringType |
CIT, MIT |
payment_refund |
refundType |
cpg, dds |
payroll_feed_line |
successFlag |
Y, N |
venue_checkin_companion |
relationship |
adult, child |
venue_checkin, offer |
accessType |
individual, couple, family |
tier, tier_type |
tierType.group, group |
base, upgrade, add_on |
member_subtype |
tag |
spouse, child |
Apply to policy_document and member_policy_acceptance.
| Field | Values |
|---|---|
documentType |
terms_and_conditions, privacy_policy |
entityType |
global, tier, partner, member, program_management_user, partner_user |
targetGroup |
member, program_management_user, partner_user, public |
policy_document.status |
active, archived |
member_policy_acceptance.status |
accepted, waiting |
| Dataset | Field | Values |
|---|---|---|
company_group |
type |
internal, external |
tier_eligibility_rule |
paymentPeriod |
monthly, one_time |
tier_eligibility_rule |
paymentTypes[] |
As 4.6.3, excluding free_dependant |
partner |
socialMediaAccounts[].platform |
facebook, instagram, linkedin, x, youtube, tiktok |
member |
coreGrade |
EK.01 to EK.14 |
Records below are taken from the UAT environment. **Structure, identifier formats,
code values, amounts and dates are real**, so they show exactly what the feed
looks like. Personal fields have been replaced with fictional values — names,
email addresses, telephone numbers, employee numbers, membership numbers and the
identifiers that resolve to a person. Nothing below relates to a real individual.
Optional fields that were absent in the source record are shown absent, since that
is itself informative — see 6.1.
{
"id": "b7c41e02-9a3d-4f18-8e55-2c9d7a614f30",
"memberId": "8292538047-eu-uat",
"staffId": "EK998877",
"name": "Amina",
"surname": "Rahman",
"email": "amina.rahman@example.com",
"phone": "+9715XXXXXXX",
"company": { "id": "368bd56d-ae38-484b-aa83-d4a58181fb96" },
"memberType": "employee",
"coreGrade": "EK.10",
"status": "active",
"registrationSource": "backoffice_register",
"loginMethod": "email_password",
"idPhotoStatus": "approved",
"isFace": false,
"actionRequired": false,
"actionMessage": "",
"requiresPaymentInstrumentUpdate": false,
"createdAt": "2026-07-15T10:31:02.114Z",
"updatedAt": "2026-07-28T14:54:03.236Z",
"createdBy": { "type": "admin", "id": "…", "name": "…" },
"memberships": [ /* see 4.7.3 */ ]
}
Note memberType is employee — an identifier, not a label. It resolves to
"EK Permanent" in the member_type code list.
{
"id": "f10c8b44-27ae-4d93-a6b1-88e0c3f7a521",
"memberId": "5186822519-eu-uat",
"name": "Layla",
"surname": "Rahman",
"email": "layla.rahman@example.com",
"primaryMemberId": "b7c41e02-9a3d-4f18-8e55-2c9d7a614f30",
"hrmsFamilyMemberId": "9911223",
"relation": "spouse",
"memberType": "employee",
"memberSubType": "spouse",
"coreGrade": "EK.07",
"status": "pending_invitation_acceptance",
"registrationSource": "hrms_register",
"loginMethod": "email_password",
"company": { "id": "368bd56d-ae38-484b-aa83-d4a58181fb96" }
}
The presence of primaryMemberId is what makes this a dependant. **staffId is
absent**, as it is on every dependant — reach the employee number through the
primary member.
{
"id": "27703d45-8988-4db3-9371-d5c260914070",
"memberId": "f10c8b44-27ae-4d93-a6b1-88e0c3f7a521",
"tierId": "9a5a488e-9ebe-45fa-bc06-7b33baf68752",
"eligibilityRuleId": "db8be072-dcf7-4a5b-9be6-c549f2da8db5",
"status": "active",
"paymentType": "free_dependant",
"startDate": "2026-07-28T14:54:02.859Z",
"endDate": "2027-07-31T19:59:59.999Z",
"autoRenewal": false,
"createdAt": "2026-07-28T14:54:03.236Z"
}
Both dates are full timestamps, not calendar dates. The instalment fields are
absent because this membership carries no charge, and paymentId is absent for the
same reason.
{
"id": "d4a90f61-33bc-42e7-9ac5-6b1e80c2f7d9",
"memberId": "b7c41e02-9a3d-4f18-8e55-2c9d7a614f30",
"tierId": "9a5a488e-9ebe-45fa-bc06-7b33baf68752",
"eligibilityRuleId": "db8be072-dcf7-4a5b-9be6-c549f2da8db5",
"invoiceId": "0a1f6c73-58d2-4e19-b7a4-91cc3e5f0d82",
"paymentType": "salary_deduction",
"provider": "dds",
"paymentReason": "enrollment",
"amountValue": 30000,
"currency": "AED",
"exponent": 2,
"status": "completed",
"createdAt": "2026-07-15T10:37:22.030Z",
"completedAt": "2026-07-15T10:37:22.030Z",
"deductedAt": "2026-07-16T02:00:50.452Z",
"refunds": []
}
This record demonstrates the most important trap in the feed. amountValue is
30000 with exponent 2, so the amount is AED 300.00 — not 30,000. And
completedAt equals createdAt to the millisecond, because for salary deduction it
is stamped at enrolment; the money did not move until deductedAt, the following
day. Reporting collections on completedAt would book this in the wrong period.
See 4.4.6.
{
"id": "01KYMKHRDEF88PBPV7ZX3AP2JB",
"memberId": "9c2e5741-6b08-4a3f-95d1-7fe4a0b83c66",
"memberDisplayId": "2813865170-eu-uat",
"memberName": "Yusuf",
"memberSurname": "Haddad",
"offerId": "6b1ccb92-b91d-48e5-91cf-5e00c1374f68",
"partnerId": "5b4b1253-0e89-473e-b414-5e00e1f4c18a",
"locationId": "4d3a14c9-681a-485b-8122-0e982d1833ca",
"offerName": "Introduction to Golf Course",
"locationName": "Desert Links Golf Resort",
"offerType": "special_price",
"transactionAmountValue": 100000,
"discountAmountValue": 55000,
"currency": "AED",
"exponent": 2,
"status": "completed",
"redeemedAt": "2026-07-28T14:55:05.134Z",
"createdAt": "2026-07-28T14:55:05.134Z"
}
The member spent AED 1,000.00 and saved AED 550.00. Note the record id is a
ULID while offerId and partnerId are UUIDs — see the note on identifier formats
in 4.4.5. currency and exponent are stamped by EPC at extraction (4.4.3).
{
"id": "9a5a488e-9ebe-45fa-bc06-7b33baf68752",
"name": "Platinum 2026",
"label": "Platinum",
"tierType": { "id": "base", "group": "base" },
"feeValue": 30000,
"currency": "AED",
"exponent": 2,
"startDate": "2026-02-28T20:00:00.000Z",
"endDate": "2027-02-27T19:59:59.999Z",
"membershipDuration": 12,
"taxable": true,
"financeConfig": {
"costCentre": "53050",
"nominal": "48001",
"subnominal": "P929",
"analysisKey": "00000000",
"erpCommentPrefix": "Platinum Base Membership"
},
"status": "active",
"createdAt": "2026-07-06T15:34:29.936Z"
}
feeValue 30000 with exponent 2 is AED 300.00; currency and exponent are
stamped at extraction (4.4.3). membershipEndDate is absent because membershipDuration is set — exactly
one of the two is present. taxable reflects the tier's setting today; for the
VAT treatment applied to a past charge, use audit_log (4.4.7).
{
"tierId": "9a5a488e-9ebe-45fa-bc06-7b33baf68752",
"id": "db8be072-dcf7-4a5b-9be6-c549f2da8db5",
"name": "EK Group Annually",
"paymentTypes": ["credit_card", "salary_deduction", "company_paid", "free_of_charge"],
"paymentPeriod": "one_time",
"status": "active",
"conditions": [
{ "key": "companyGroupId", "logicalOperator": "in", "value": "airlines" },
{ "key": "memberType", "logicalOperator": "equals", "value": "employee" }
]
}
value is typed loosely: a plain string here even where the operator is in. It may
also be a number, boolean or array — see 4.5.21.
{
"id": "a6a65072-e5bc-47a3-b1dc-b5e0c57841ab",
"type": "termination",
"status": "completed",
"periodMonth": "2026-08",
"batchName": "16082026040040",
"totalLines": 1,
"successCount": 1,
"failedCount": 0,
"totalAmountValue": 2500,
"createdAt": "2026-08-16T04:00:40.626Z"
}
batchName is DDMMYYYYHHMMSS. totalAmountValue 2500 is AED 25.00.
[
{ "id": "employee", "name": "EK Permanent", "hrmsMapping": "EMP", "status": "active" },
{ "id": "family", "name": "EK Temporary", "hrmsMapping": "TEMP", "status": "active" },
{ "id": "01kjyb6pd62vt1yjdhaj3jsvp0", "name": "Associate Permanent", "status": "active" }
]
[
{ "id": "spouse", "name": "Spouse", "tag": "spouse",
"hrmsMapping": ["Wife", "Husband", "Spouse"], "status": "active" },
{ "id": "child", "name": "Child", "tag": "child",
"hrmsMapping": ["Child", "Daughter", "Son", "Step Child", "Legitimate Child"],
"status": "active" },
{ "id": "01kjw4r60zvc9rdwecqrmb3sah", "name": "Parent",
"hrmsMapping": ["Father", "Mother", "Parent"], "status": "active" }
]
The child entry's hrmsMapping array is abridged above; the live list is longer.
Three things to carry from these:
id is not the label. family is named "EK Temporary". Never derive meaning from an identifier.hrmsMapping is a string on member_type and an array on member_subtype, because one Platinum subtype absorbs many HRMS relationship descriptions. It is the join back to enterprise HR reference data.status where only current values are wanted, but retain inactive rows so historical records still resolve.Not yet agreed. The following are open and must be decided by EDP before
build can commence. EPC has no fixed requirement on any of them and can
accommodate a range of options.
| Decision | Options to consider | Owner |
|---|---|---|
| Transfer mechanism | Object-storage drop, managed file transfer, database load, streaming, or an EDP-provided ingestion endpoint | EDP |
| Destination | An EDP-provided landing area, or a location provided by EPC for EDP to collect from | EDP |
| Encoding | Row-oriented (e.g. delimited JSON, CSV) or columnar (e.g. Parquet), and whether compressed | EDP |
| Cadence | Frequency, and the time of day that suits downstream processing | EDP |
| Day boundary | The time zone that defines a delivery day. EPC recommends Asia/Dubai, matching the payroll and financial reporting calendar, so that daily aggregates reconcile with finance | EDP |
| Completion signalling | How EDP is told a delivery is complete and safe to ingest | EDP |
| Nested structures | Whether EPC delivers whole records with nested collections intact (see 4.4.8), or flattened to the grain of each dataset | EDP |
| Authentication and encryption | Credential exchange, transport security and encryption at rest | EDP |
| Failure and retry handling | Behaviour on a failed or partial delivery, and how recovery is signalled | Joint |
Two properties of the data are worth carrying into that decision:
Indicative record counts from the non-production environment. **These are not
production volumes**; they indicate relative dataset sizes and scaling
behaviour, and are provided to inform the decisions in 5.1.
| Dataset | Records | Ratio to member count | Scaling driver |
|---|---|---|---|
| audit_log | 4,171 | 21.5x | Activity. Grows without bound, independent of headcount |
| payment | 373 | 1.9x | Memberships multiplied by instalments |
| transaction | 355 | 1.8x | Payments and refunds |
| tier_enrollment | 230 | 1.2x | Memberships |
| member | 194 | 1.0x | Population |
| invoice | 187 | 1.0x | Payments |
| venue_checkin | 52 | 0.3x | Engagement |
| redemption | 30 | 0.2x | Engagement |
| search_history | 27 | 0.1x | Engagement. Bounded: at most 100 records per member, trailing 90 days (4.5.19) |
| payroll_feed | 38 batches | n/a | One to two per period per feed type |
| Catalogue datasets | offer 95, policy_document 82, partner 30, tier 20 | n/a | Slow-changing |
Notes:
audit_log dominates the feed and is the only dataset with a volume concern. It scales with activity rather than membership, so its share grows over time. It is the dataset most likely to influence the encoding and cadence decisions in 5.1.audit_log, the entire feed is under twice the member count.Membership numbers (memberId) carry an environment suffix outside production,
for example 1234567890-eu-staging. Non-production and production identifiers
therefore do not correspond.
**The two environments must be treated as separate key spaces and must not be
joined.** This holds regardless of the transfer mechanism chosen.
| Change | Notice | EDP action |
|---|---|---|
| New field added to an existing dataset | Advance notice; schema version incremented | None required. Additive changes are backward-compatible |
| New value added to a closed code list | Advance notice; schema version incremented | Load the revised code list |
| New dataset added | Advance notice; revised specification issued | Extend ingestion |
| Field removed or renamed, or a dataset withdrawn | Advance notice; revised specification issued and agreed before the change | Coordinate cut-over |
Fields populated less consistently in live data than their definitions suggest. EDP should build tolerantly rather than constraining on them.
| Field | Dataset | Expectation |
|---|---|---|
| birthdate, gender, maritalStatus, coreGrade | member | Frequently absent. The derived actionRequired flag identifies records lacking required detail; prefer it to testing each field individually |
| staffId | member | Never present on dependants. Reach the employee number via primaryMemberId |
| hrmsJoiningDate | member | Primary members only. HRMS supplies no joining date for dependants |
| eligibilityRuleId | membership | Absent on older enrolments |
| dds_deduction_cycle records | membership | Absent for memberships predating the per-period ledger. For those, payment.deductedAt is the fallback collection signal |
| accessType | venue_checkin | Absent on visits predating per-entitlement quotas |
| relation | member_family | Empty where the HRMS relationship type has no configured equivalent. The family record still exists |
| quotaRecovered | venue_checkin | Absent while the party remains on site |
| additionalGuests | venue_checkin | On the earliest visits this is a plain integer (a headcount) rather than the object described in 4.5.17. Treat an integer as adultCount, with the other three fields zero |
| reason, refundedReason | payment_refund, payment | Legacy free-text refund reasons written before the coded reasonCode existed. May still be present on older records until a backfill completes; superseded by reasonCode and refundedReasonCode wherever both are present |
| type | company_group | Absent on the earliest configured group |
| search_history records | search_history | Rolling window only: at most 100 per member, expiring 90 days after the last search. See 4.5.19 |
The following are withheld from the feed. Their exclusion is by agreement and does not affect reconciliation: payment outcomes remain fully described by status, statusReason and errorCode.
| Field | Dataset | Category | Rationale |
|---|---|---|---|
| passwordHash, loginAttempts, lockedUntil | member | Credential | Authentication material |
| passwordHash, passwordHistory, loginAttempts, lockedUntil | (partner users and administrative users) | Credential | Authentication material |
| invitationToken, invitationExpiresAt | (administrative users) | Credential | Account-takeover vector |
| agreementId | membership, payment | Instrument token | Capable of authorising charges |
| cardId, lastFourDigits, paymentMethod | membership, payment | PCI | Cardholder data |
| cpgLogs[] | payment | PCI | Raw payment-gateway request and response bodies; the sole location in which cardholder data may appear in free form. Excluding it keeps the delivered dataset outside PCI-DSS scope |
| Identity photograph images | member | Biometric | The images are not delivered. The storage reference of the current photograph (idPhoto) and the review status (idPhotoStatus) are delivered; the reference to any superseded photograph (previousIdPhotoPath) is withheld |
| erpLogs[] | invoice | Third-party payload | Raw request and response bodies exchanged with the finance system. The outcome is fully described by status, erpInvoiceNumber, erpErrorDetails, erpSubmittedAt and erpResponseAt |
| hrmsResponse | payroll_feed | Third-party payload | Raw response body returned by payroll. The outcome is fully described by status, successCount, failedCount, interfaceLoadId, failureReason and the per-line successFlag and errorDetails |
| returnUrl, redirectionUrl, postPaymentRedirectPath | payment | Internal | Browser redirect targets used during card checkout; no analytical content |
| pendingApprovalId | tier, offer, partner, company | Internal | Transient lock held while a change awaits internal approval |
| renewalNotificationsSent | membership | Internal | Idempotency cache for reminder notifications |
| tierRuleKey | tier_enrollment | Internal | Storage index key; derivable from tierId and eligibilityRuleId |
| Storage index attributes (GSI keys, sort keys) | all | Internal | Present on some records; carry no information beyond the fields already delivered |
| documents[] | partner | Out of scope | Metadata of contract documents held against a partner; the files themselves are not held in a deliverable form |
The following datasets are out of scope for this interface: general ledger journals, user notifications, member session records, payment instrument history, partner location associations, card-management sessions, and all internal operational datasets (approval workflow, role and permission configuration, notification templates, content management, reporting engine state, asynchronous job orchestration and search indexes).
| Approval | Owner | Required before | Status |
|---|---|---|---|
| Interface design and field scope | EPC / EDP technical | Build commencement | Pending |
| Data protection sign-off — see section 2 Risks | DPO | First production delivery | Pending |
| Free-text content review | EPC | First production delivery | Pending |
| Transfer mechanism, format and cadence agreed (5.1) | EDP | Build commencement | Pending |
| Production cut-over | EPC / EDP | Production delivery | Pending |
| Ref | Item | Owner |
|---|---|---|
| 1 | Transfer mechanism, destination, encoding, cadence and completion signalling — see 5.1 | EDP |
| 2 | Confirmation of retention period and erasure procedure for delivered personal data | EDP / DPO |
| 3 | Criteria for promotion from non-production to production delivery | EPC / EDP |
| 4 | Whether a reference transform implementation is required for the nested-collection flattening in 4.4.8 | EDP |
| 5 | Historical depth expected at first delivery. Note the programme commenced operation in 2026; no data predates it | EPC / EDP |