Ethos Integration Setup: Indexing Architecture and Process

Last updated: August 28, 2026

This document describes the technical architecture of Housing.Cloud's Ethos integration indexing system, including how entities are matched, GUIDs are derived, and data flows between the Housing.Cloud and Ellucian Ethos data models.

Overview

The Ethos indexing system establishes bidirectional data synchronization between Housing.Cloud and Ellucian's Ethos Integration platform. Indexing is the process of matching Housing.Cloud entities (buildings, rooms, charge codes, etc.) with their corresponding Ethos records and storing the Ethos GUID as the externalId in Housing.Cloud's database.

All indexing can be executed and triggered from the Admin dashboard at /admin/setup/integrations/ethos-utils. Once in production, indexing will happen automatically via a nightly job.

 

Basic Data Flow

┌─────────────────┐
│ Housing.Cloud   │
│ Admin Dashboard │
└────────┬────────┘
         │ Manual trigger (button click)
         ▼
┌─────────────────────────────────┐
│ executeEthosBuild*Index()       │
│ - Prepare ingest log            │
│ - Execute validation            │
│ - Match HC ↔ Ethos identifiers  │
└────────┬────────────────────────┘
         │ HTTP GET requests
         ▼
┌─────────────────────────────────┐
│ Ethos Integration API           │
│ integrate.elluciancloud.com     │
└────────┬────────────────────────┘
         │ JSON responses (paginated)
         ▼
┌─────────────────────────────────┐
│ Matching & GUID Extraction      │
│ - Parse Ethos response          │
│ - Match on code/name/id         │
│ - Extract Ethos GUID            │
└────────┬────────────────────────┘
         │ Prisma transaction
         ▼
┌─────────────────────────────────┐
│ Housing.Cloud Database          │
│ UPDATE entity SET externalId    │
└─────────────────────────────────┘

Entity Indexing Processes

Buildings and Rooms (Inventory)

Process:

  1. Building matching:
    • Fetch all Housing.Cloud buildings for the tenant
    • Paginate through Ethos /api/buildings (default version)
    • Match: HC Building.displayId == Ethos building.code (case-insensitive, lowercase comparison)
    • Store mapping in ethosIdLookup Map
    • If all buildings match, execute Prisma transaction to set externalId
  2. Room matching (only if no building errors):
    • For each matched building, query Ethos /api/rooms?buildingId={ethosId}
    • Match: HC Room.name == Ethos room.number (scoped per building)
    • Update InventoryRoom.externalId

Error Handling: Mismatches logged as "HC <> Ethos Building Name Mismatch: [code]" in validation log.

Charge Codes (Costs)

Process:

  1. Fetch all Housing.Cloud costs with non-null code field
  2. Paginate through Ethos /api/accounting-codes
  3. Match: HC Cost.code == Ethos accounting-code.code (exact match)
  4. Update via updateMany (multiple costs can share same code)

Cycles (Academic Periods)

Process:

  1. Fetch Housing.Cloud cycles with non-null externalTermId and null externalId
  2. For each cycle, query Ethos /api/academic-periods with criteria filter: { type: EthosAcademicPeriodQuery.CODE, values: [externalTermId] }
  3. Match: HC Cycle.externalTermId == Ethos academic-period.code
  4. Expect exactly 1 result; log error if 0 or >1

Meal Plans

Process:

  1. Fetch Housing.Cloud meal plans with non-null externalCode
  2. Paginate through Ethos /api/meal-plans
  3. Match: HC MealPlan.externalCode == Ethos meal-plan.code
  4. Update individual records via update

Profiles (Persons)

Process:

  1. Triggered manually or via bulk operation (concurrency: 2, batch size: 250 profiles)
  2. For each profile, determine lookup credential:
    • sisId: Query /api/persons with criteria { credentials: [{ type: 'bannerId'|'colleaguePersonId', value: sisId }] }
    • email: Query /api/persons with criteria { emails: [{ address: schoolEmail }] }
  3. Expect exactly 1 person result
  4. Parse Ethos person data via parseEthosPersonToHCProfile()
  5. Update Housing.Cloud profile with externalId and demographic data

Alternative Method: "Build Profile Index by EDU Email" (queries by school email domain).

Profile indexing only processes non-admin profiles to avoid syncing staff accounts to the SIS.

Data Model Mapping

Housing.Cloud ↔ Ethos Entity Relationships

Housing.Cloud Entity Ethos Resource HC Identifier Field Ethos Matching Field HC externalId Stores
Building buildings displayId code building.id (GUID)
Room rooms name number room.id (GUID)
Charge Code accounting-codes code code accounting-code.id
Cycle academic-periods externalTermId code academic-period.id
Meal Plan meal-plans externalCode code meal-plan.id
Profile persons sisId / schoolEmail credentials.value / emails.address person.id

 

Ethos API Integration

Client Implementation

The EthosGetWrapper class handles all HTTP communication with Ethos.

Base Configuration:

  • Base URL: https://integrate.elluciancloud.com
  • Authentication: JWT bearer token via POST /auth (auto-refresh on 401)
  • Pagination: ?offset={n}&limit={m} query parameters
  • Criteria Queries: &criteria={JSON.stringify(queryObj)} for filtered lookups

API Endpoints and Versions

Resource Endpoint Path Accept Header Version Usage
Buildings /api/buildings */* (default) Inventory index
Rooms /api/rooms */* Inventory index
Accounting Codes /api/accounting-codes */* Cost index
Academic Periods /api/academic-periods */* Cycle index
Meal Plans /api/meal-plans */* Meal plan index
Persons /api/persons v12 Profile index/sync

The indexing service does not implement exponential backoff or automatic retries. Failed pagination stops the process and logs the error.