Common Data Model

Every PropTech system models the world a little differently. The Common Data Model is the single normalized shape PropSocket maps them all into, so you write deserialization once instead of once per vendor. The MVP exposes four entities — Property, Unit,Resident, and Lease — plus the LeaseResidentrelation that ties residents to leases.

How they relate

The hierarchy is small and predictable:

Property
├─ 1 — N ─▶ Unit
└─ 1 — N ─▶ Lease
     │
     └─ N — N ─▶ Resident  (via LeaseResident)
  • A Property has many Units and many Leases.
  • A Lease belongs to exactly one Unit and one Property.
  • A Lease and a Resident have a many-to-many relationship — a lease can have several residents (primary, co-resident, guarantor), and a resident can hold several leases over time. LeaseResident is that join.

Conventions every entity follows

These hold across all four entities. Learn them once:

  • IDs. Every record has a PropSocket-minted id (the canonical identifier you use in /v1/{entity}/{id} calls) and an x_id— the native identifier from the source integration. It's x_id, neversource_id.
  • Money. Always an object: { "amount": 285000, "currency": "USD" }.amount is an integer in minor units — 285000 is $2,850.00. No floats, no rounding drift.
  • Datetimes & dates. Datetimes are UTC ISO 8601 (2026-05-11T18:04:58Z). Date-only fields are YYYY-MM-DD.
  • Enums. Lowercase snake_case strings (active,month_to_month). Code defensively — tolerate enum values you don't recognize, as we add new ones additively.
  • Soft deletion. Records are never physically deleted. A removed record gets a non-null deleted_at timestamp. List endpoints exclude soft-deleted records by default; pass ?include_deleted=true to see them.
  • custom_data. A free-form JSON object on every entity for integration-specific fields the CDM doesn't standardize. Defaults to {}.
  • Freshness. Every record carries ps_synced_at — the UTC timestamp of the last successful sync that covered it, even when nothing changed (distinct fromupdated_at). It's PropSocket operational metadata in the reserved ps_namespace. See Conventions.

Property

A physical asset — a building, community, complex, or standalone home. The top of the hierarchy; everything location-bound references a Property.

FieldTypeNotes
namestringDisplay name.
typeenumapartment, condo, single_family, …
statusenumactive, inactive, lease_up, …
addressAddressStructured object.
total_unitsintegerRentable units.
GET /v1/properties/{id}
{
  "id": "prp_01HX0G5T8N3KEWBYV2QMR4DCFA",
  "x_id": "entrata-property-3391",
  "integration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Maple Court Apartments",
  "type": "apartment",
  "status": "active",
  "address": {
    "line_1": "1400 Maple Court",
    "line_2": null,
    "city": "Austin",
    "state": "TX",
    "postal_code": "78704",
    "country": "US"
  },
  "year_built": 2014,
  "total_units": 188,
  "total_buildings": 6,
  "phones": [
    { "type": "work", "number": "+15125550133", "primary": true }
  ],
  "custom_data": {},
  "created_at": "2026-05-01T09:12:44Z",
  "updated_at": "2026-05-11T18:04:58Z",
  "deleted_at": null,
  "ps_synced_at": "2026-05-11T18:04:58Z"
}

Unit

An individual rentable space within a Property — an apartment, a suite, a single-family home.

FieldTypeNotes
property_idUUIDParent Property.
unit_numberstringe.g. "204".
statusenumoccupied, vacant, notice, …
bedrooms / bathroomsnumberDecimals allowed (studios, half-baths).
market_rentMoneyInteger minor units + currency.
GET /v1/units/{id}
{
  "id": "unt_01HX1H6U9P4LFXCZW3RNS5EDGB",
  "x_id": "entrata-unit-55812",
  "integration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "property_id": "prp_01HX0G5T8N3KEWBYV2QMR4DCFA",
  "unit_number": "204",
  "type": "apartment",
  "status": "occupied",
  "floor": "2",
  "building": "C",
  "bedrooms": 2,
  "bathrooms": 1.5,
  "square_feet": 980,
  "market_rent": { "amount": 285000, "currency": "USD" },
  "floor_plan_name": "The Aspen 2BR",
  "custom_data": {},
  "created_at": "2026-05-01T09:13:02Z",
  "updated_at": "2026-05-11T18:04:58Z",
  "deleted_at": null,
  "ps_synced_at": "2026-05-11T18:04:58Z"
}

Resident

A person who is a current or past tenant. Carries contact and demographic detail.

FieldTypeNotes
first_name / last_namestringRequired.
statusenumcurrent, past, future, applicant, …
emails / phonesarrayEmail and Phone objects.
lease_idsUUID[]Leases this resident is on.
balanceMoneyOutstanding balance.
GET /v1/residents/{id}
{
  "id": "res_01HX2J7V0Q5MGYDAW4SOT6FEHC",
  "x_id": "entrata-resident-44218",
  "integration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "property_id": "prp_01HX0G5T8N3KEWBYV2QMR4DCFA",
  "first_name": "Dana",
  "last_name": "Okonkwo",
  "display_name": "Dana Okonkwo",
  "status": "current",
  "type": "primary",
  "emails": [
    { "type": "personal", "address": "dana.o@example.com", "primary": true }
  ],
  "phones": [
    { "type": "mobile", "number": "+14155550118", "primary": true }
  ],
  "move_in_date": "2026-06-01",
  "lease_ids": ["lse_01HX9P3K2N7QZRWY4B8MJ5VCDF"],
  "balance": { "amount": 0, "currency": "USD" },
  "custom_data": {},
  "created_at": "2026-05-01T09:14:20Z",
  "updated_at": "2026-05-11T18:04:58Z",
  "deleted_at": null,
  "ps_synced_at": "2026-05-11T18:04:58Z"
}

Lease

The rental agreement linking residents to a unit at a property. The core transactional entity — and the one that exposes the LeaseResident relation.

FieldTypeNotes
property_id / unit_idUUIDThe unit being leased.
resident_idsUUID[]At least one. The residents on the lease.
statusenumpending, active, renewed, expired, terminated, …
start_date / end_datedateend_date is null for month-to-month.
rent_amountMoneyMonthly rent.
residentsLeaseResident[]Nested relation — see below.
GET /v1/leases/{id}
{
  "id": "lse_01HX9P3K2N7QZRWY4B8MJ5VCDF",
  "x_id": "entrata-lease-8847291",
  "integration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "property_id": "prp_01HX0G5T8N3KEWBYV2QMR4DCFA",
  "unit_id": "unt_01HX1H6U9P4LFXCZW3RNS5EDGB",
  "resident_ids": ["res_01HX2J7V0Q5MGYDAW4SOT6FEHC"],
  "status": "active",
  "type": "fixed",
  "start_date": "2026-06-01",
  "end_date": "2027-05-31",
  "term_months": 12,
  "rent_amount": { "amount": 272500, "currency": "USD" },
  "security_deposit": { "amount": 285000, "currency": "USD" },
  "balance": { "amount": 0, "currency": "USD" },
  "signed_date": "2026-05-11",
  "is_renewal": false,
  "residents": [
    {
      "resident_id": "res_01HX2J7V0Q5MGYDAW4SOT6FEHC",
      "x_id": "entrata-resident-44218",
      "role": "primary"
    }
  ],
  "custom_data": {},
  "created_at": "2026-05-11T17:41:52Z",
  "updated_at": "2026-05-11T17:41:52Z",
  "deleted_at": null,
  "ps_synced_at": "2026-05-11T18:04:58Z"
}

LeaseResident (relation only)

LeaseResident is the join between a Lease and a Resident — it carries therole a resident plays on a specific lease (primary,responsible, occupant, …). role is the source PMS's relationship label, normalized to lowercase snake_case — an open set, not a fixed enum. It is not a first-class endpoint: there is no /v1/lease-residents collection and no standalone record to fetch. You read it as the nested residents array on a Lease, shown above:

LeaseResident — nested on Lease
"residents": [
  {
    "resident_id": "res_01HX2J7V0Q5MGYDAW4SOT6FEHC",
    "x_id": "entrata-resident-44218",
    "role": "primary"
  }
]

To go the other direction — every lease a resident is on — read the resident'slease_ids array, or filter leases with?resident_id={id}. See filtering.

Soft-deleted records

When a record disappears from the source integration, the next sync sets its deleted_atrather than removing the row. List endpoints hide these by default. Request them with?include_deleted=true and check the deleted_at field:

A soft-deleted unit (fields elided)
{
  "id": "unt_01HX1H6U9P4LFXCZW3RNS5EDGB",
  "x_id": "entrata-unit-55812",
  "status": "down",
  "deleted_at": "2026-05-12T03:22:10Z",
  "updated_at": "2026-05-12T03:22:10Z",
  "ps_synced_at": "2026-05-12T03:22:10Z"
}

Next

See these shapes served live in the API reference, learn how the cache stays in sync in the architecture overview, or start reading in the quickstart.