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:
-
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
ethosIdLookupMap - If all buildings match, execute Prisma transaction to set
externalId
-
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
- For each matched building, query Ethos
Error Handling: Mismatches logged as "HC <> Ethos Building Name Mismatch: [code]" in validation log.
Charge Codes (Costs)
Process:
- Fetch all Housing.Cloud costs with non-null
codefield - Paginate through Ethos
/api/accounting-codes - Match:
HC Cost.code==Ethos accounting-code.code(exact match) - Update via
updateMany(multiple costs can share same code)
Cycles (Academic Periods)
Process:
- Fetch Housing.Cloud cycles with non-null
externalTermIdand nullexternalId - For each cycle, query Ethos
/api/academic-periodswith criteria filter:{ type: EthosAcademicPeriodQuery.CODE, values: [externalTermId] } - Match:
HC Cycle.externalTermId==Ethos academic-period.code - Expect exactly 1 result; log error if 0 or >1
Meal Plans
Process:
- Fetch Housing.Cloud meal plans with non-null
externalCode - Paginate through Ethos
/api/meal-plans - Match:
HC MealPlan.externalCode==Ethos meal-plan.code - Update individual records via
update
Profiles (Persons)
Process:
- Triggered manually or via bulk operation (concurrency: 2, batch size: 250 profiles)
- For each profile, determine lookup credential:
-
sisId: Query
/api/personswith criteria{ credentials: [{ type: 'bannerId'|'colleaguePersonId', value: sisId }] } -
email: Query
/api/personswith criteria{ emails: [{ address: schoolEmail }] }
-
sisId: Query
- Expect exactly 1 person result
- Parse Ethos person data via
parseEthosPersonToHCProfile() - Update Housing.Cloud profile with
externalIdand 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.