# Entrata API Method Index

A scannable index of every method in the Entrata OpenAPI spec, so an agent working a task
can find the right method, group, version, and required params without loading the 2.8 MB YAML.

> 🟢 **Start with [`entrata-touchpoints.md`](entrata-touchpoints.md)** if what you need is the
> current state of the integration (transport, traps, the 22 usable reads, window caps, measured
> limits, what is not available). It is the current-state reference and **it wins over this file
> where the two disagree.** This index is the per-method lookup for all 128 spec methods,
> permissioned or not, which is the one job it does that the touchpoints file deliberately does not.

- **Source spec:** `reference/entrata-openapi-2026-07-28.yaml` (2,807,945 bytes, sha256 `eb4f723605e4ec3f1dd18e6275f35cdc2d12fe0cbb6211dd50ee531ff4c335ef`)
- **Spec `updated_at`:** 2026-07-10 (per Entrata. The date is not embedded in the YAML itself.)
- **Captured:** 2026-07-28, vendored into this repo 2026-07-31 from the VPS copy at `/opt/foothold-entrata/entrata-openapi.yaml`
- **Coverage:** 18 groups, 128 methods, 146 method+version combinations, 302 schemas
- **Index generated:** 2026-07-31 from the spec, plus live probe results and the full
  `getAccessibleServices` roster captured the same day
- **Permission roster refreshed:** 2026-08-03 (`getAccessibleServices`, **28 services**, up from 22).
  Six reads were newly granted. Writes did not change.
- **Live probes completed:** 2026-08-05. The five newly granted reads that were still unprobed on
  2026-08-03 were called and **all five returned HTTP 200 with real data.** Nothing on the roster is
  granted-but-unprobed any more.
- **Third pass, 2026-08-05.** The full lead history was swept (2021-01-01 through 2026-08-05) and the
  last never-called methods were probed: `getStatus`, `getAccessibleClients`, the three `oauth`
  methods, `getLeaseDetails` r2, and the LEAD side of `getMarketingPreferences`. **Every one of the 28
  services on the key has now been called at least once.** The pass also **corrected the `getLeads`
  birth-date coverage figure** (see the birth-dates note under `leads`), **proved the lead-to-resident
  join**, established that **`getLeads` takes a 730-day window**, and found a **Cloudflare User-Agent
  trap** (see the gotchas below). All reads, serial, from the VPS.

---

## 🚫 STOP: this is a live production building

> **Owyhee Park is a real, occupied building with real residents.** Every WRITE method in this
> index touches production data that a person lives in: their lease, their ledger, their work order,
> their move-out date.
>
> **No WRITE method may ever be called without Brent's explicit written, per-property sign-off.**
>
> **Having the permission is not authorization.** Liberty's PM enabled two write methods on the
> API key. That is not a green light. It only means the API will not stop you. The policy does.
>
> `sendLeads` and `updateLeads` are permissioned and confirmed callable. **They are BANNED.**
>
> **Correction, 2026-07-31, updated 2026-08-03:** `sendWorkOrders` and `updateWorkOrders` are **still
> NOT permissioned**, but the reason has changed. The `maintenance` group is **no longer absent** from
> the key. Liberty granted it on 2026-08-03, and granted exactly two reads out of it, `getWorkOrders`
> and `getWorkOrderPickLists`. The two work-order writes were not granted. So the old explanation
> ("the whole group is absent") is obsolete: the group is present and the writes simply were not
> included. Earlier versions of this file also said all four writes were enabled by the PM. That was
> wrong too. **The writes on this key are still exactly two, `sendLeads` and `updateLeads`.** Every
> other WRITE method in this index is unpermissioned, and banned on both counts.
>
> **The write cleanup ask (have Liberty uncheck the two) would have been two checkboxes, not four,
> and it was DECLINED BY BRENT on 2026-07-31.** It will not be made. The email that would have
> carried it was drafted 2026-07-30, never sent, and deleted 2026-07-31. **Do not re-raise it and do
> not recreate that email.** Both writes stay permissioned permanently, by choice, so **there is no
> vendor-side guard and there never will be**: the deny-by-default read-method allowlist in our code
> is the only control.
>
> This is Constitution rule 2 in `system-design.html`. Read it before you build anything that writes.

---

## The 28 accessible services (authoritative, captured 2026-08-03)

`getAccessibleServices` returned **exactly 28 services** (it returned 22 on 2026-07-31; six reads were
added 2026-08-03). This roster is the permission truth for every table below. **If a method is not on
this list it is not permissioned**, whether or not it was ever probed individually.

**🆕 = granted 2026-08-03.**

| group | services |
| --- | --- |
| `status` | `getStatus` |
| `oauth` | `getAccessToken`, `getJwtAccessToken`, `getUserInfo` |
| `appinfo` | `getAccessibleClients` (on the `rsync` org path, not `libertyassetgroup`), `getAccessibleServices`, `getAppAdditionalServices` |
| `communications` | 🆕 `getMarketingPreferences`, 🆕 `getMarketingPreferencePickList` |
| `financial` | `getGlTransactions` |
| `leads` | `getLeadPickLists`, `getLeads`, **`sendLeads` (WRITE)**, **`updateLeads` (WRITE)** |
| `leases` | `getLeaseDetails`, `getLeases`, 🆕 `getMitsLeases` |
| `maintenance` | 🆕 `getWorkOrders`, 🆕 `getWorkOrderPickLists` (reads only, **no work-order writes**) |
| `properties` | `getFloorPlans`, `getProperties`, `getWebsites`, 🆕 `getCalendarAvailability` |
| `propertyunits` | `getAmenities`, `getPropertyUnits`, `getSpecials`, `getUnitsAvailabilityAndPricing`, `getUnitTypes` |

**The accounting closes:** 28 = **22** verified-working reads and plumbing (the 16 probed 2026-07-31,
plus `getWorkOrders` probed 2026-08-03, plus the last 5 probed 2026-08-05: `getWorkOrderPickLists`,
`getMitsLeases`, `getCalendarAvailability`, `getMarketingPreferences`, `getMarketingPreferencePickList`),
plus **2** banned writes, plus **3** oauth methods (unused, this integration is `X-Api-Key`), plus
`getAppAdditionalServices`, which is OAuth-only and returns `400/107` on an apikey call.
22 + 2 + 3 + 1 = 28.

### ✅ Granted 2026-08-03 (the 2026-07-31 asks all landed), all six probed and working 2026-08-05

All six methods asked for on 2026-07-31 came back permissioned on 2026-08-03 and appear on the roster
above. **All six are reads.** The `maintenance` and `communications` grants are read-only: the group is
now on the key, but only the two `get*` methods from each were included.

**Permissioned is now also proven.** All six have been called live and all six returned HTTP 200:
`getWorkOrders` on 2026-08-03, the other five on 2026-08-05. None of them is a "permissioned but
unproven" row any more.

| Method(s) | Group | Status |
|---|---|---|
| `getWorkOrders` | `maintenance` | ✅ Granted 2026-08-03. **Probed live 2026-08-03** (r1, `propertyId` `1311115`): HTTP 200 with real production work orders |
| `getWorkOrderPickLists` | `maintenance` | ✅ Granted 2026-08-03. **Probed live 2026-08-05** (r1, no params): HTTP 200. Property-scoped `Locations` (with nested `unitTypes`), `Priorities`, `StatusTypes`, `Categories`, `Problems`, `SubMaintenanceProblems`, plus `WorkOrderTypes` (5), `CompanyEmployees` (12, the Liberty staff roster), `InspectionStatuses` (5) |
| `getMitsLeases` | `leases` | ✅ Granted 2026-08-03. **Probed live 2026-08-05** (r1, `propertyId`): HTTP 200, 100 `Tenant` records against 52 `LA_Lease`. **Not a birth-date source: the `BirthDate` field is in the schema and empty in Liberty's data.** It is where customer IDs come from (`IDType: "Customer ID"`) |
| `getCalendarAvailability` | `properties` | ✅ Granted 2026-08-03. **Probed live 2026-08-05** (r1, `propertyId` + `fromDate` + `toDate`, `MM/DD/YYYY`): HTTP 200, tour configuration. **Max span is 7 days, not 60** |
| `getMarketingPreferences`, `getMarketingPreferencePickList` | `communications` | ✅ Granted 2026-08-03. **Both probed live 2026-08-05:** HTTP 200. The pick list returns 24 rows; `getMarketingPreferences` returns `customers[].preferences[]` with `optIn` per consentType per channel |

**Nothing is in flight with Liberty as of 2026-08-03.** The write cleanup ask is dead by Brent's
decision (see the STOP block above), and the six reads above were the whole 2026-07-31 list.

**Deliberately NOT asked, so nobody re-adds them without thinking:** `getLeadEvents` (the `getLeads`
r1 `eventDateFrom` / `eventDateTo` / `eventTypeIds` filters cover the need), `getExpiringLeases`
(`getLeases` carries lease end dates), `getPropertyMedia` and the testimonial methods (not urgent),
and **`getCustomers`, dropped from consideration entirely** because its response schema has **no
birth-date field**, so it would not serve the birthday-card use case even if unblocked. Full reasons
in `entrata-api-context.md` §9 and `foothold-design-scope.md`. (The 2026-08-05 probes settled the
birthday question anyway: `getLeads` r1 carries a populated `birthDate`. See the birth-dates note under
`leads` below.)

**Whole groups absent from the key**, not merely returning 1403 on one method: `applications`,
`arcodes`, `arpayments`, `artransactions`, **`customers`**, `leasingcenter`, `pricing`, `queue`,
`vendors`. That is nine groups, down from eleven: `communications` and `maintenance` came onto the key
2026-08-03. The seven groups that are enabled (`communications`, `financial`, `leads`, `leases`,
`maintenance`, `properties`, `propertyunits`) are each enabled to exactly the methods listed above and
nothing else. (`status` and `appinfo` are plumbing and are enabled too.)

---

## Request shape cheat-sheet

```
POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/<group>

Headers:
  X-Api-Key: <key>
  Content-Type: application/json

Body:
{
  "auth": { "type": "apikey" },
  "requestId": "1",
  "method": {
    "name": "<methodName>",
    "version": "r1",
    "params": {}
  }
}
```

**The single most common failure: the group is in the URL and the method is in the body.** They are two
different things and they have to agree. Calling `getLeases` against `/v1/leads` returns a 400 (1404-family
"method not found" error), not a helpful redirect. Look the method up in the group map below before you call it.

Other gotchas:

- **Version matters.** `version` is not always `r1`. Several methods only accept `r2`, and `getSpecials` goes to `r4`. The version column below is the authoritative list of what the spec accepts. Guessing causes failures.
- **Times are Mountain (MST/MDT)** unless the spec says otherwise. Owyhee Park is in Boise, so that happens to be local time, but do not assume it for anything else.
- ⚠️ **Date format is DIRECTION-DEPENDENT, and this is a build-breaker if you get it backwards.**
  **What you SEND: `MM/DD/YYYY`**, and request datetimes are `MM/DD/YYYYTHH:MM:SS` (a literal `T`, not
  ISO 8601). **What you GET BACK: ISO `YYYY-MM-DD`.** Live response samples in
  `entrata-api-context.md` §4.10 / §4.11: `"createdOn":"2026-07-30"`,
  `"createdOnDateTime":"2026-07-30T03:05:00"`, `"startDate":"2025-08-30"`,
  `"leaseApprovedOn":"2025-08-27"`, `"moveInDate":"2023-11-01"`. ⚠️ **And response formats are not
  uniform across methods**: `getWorkOrders` timestamps came back as `03/11/2024 23:58:35.168295 MDT`.
  **So: format strictly on the way out, parse tolerantly on the way in.** A parser written to
  `MM/DD/YYYY` on the read path fails on every date it reads.
- ⚠️ **Set an explicit `User-Agent` header.** Entrata's edge is Cloudflare and it bans some runtime defaults. A Python `urllib` request on its default UA returned **HTTP 403 with the bare body `error code: 1010`** (a browser-signature ban, not an Entrata error), while the identical request through `curl` succeeded. **A 403 whose body does not parse as JSON is an edge block, not an auth or permission failure.** Confirmed 2026-08-05.
- ⚠️ **Date-window caps are PER METHOD. Never generalize one.** `getCalendarAvailability` r1 caps at **7 days**; `getLeads` r1 accepts **730**. Same key, same gateway, two orders of magnitude apart. Measure the cap on each method you use, and do not trust the spec for it (it claims 60 days for the calendar and live behavior says 7).
- **Auth:** `X-Api-Key` header plus `{"auth":{"type":"apikey"}}` in the body. Both. Some methods (`getAppAdditionalServices`) reject apikey auth entirely with code 107 and require OAuth.
- **Async:** long-running requests can come back with a `queueId` instead of data. The documented recovery is to poll `getResponse` in the `queue` group. **`queue` is not on our key**, so if a `queueId` ever comes back we cannot retrieve the payload. Keep requests small enough that they answer inline.
- **All calls originate from the VPS** (`5.78.139.104`). That is the allowlisted IP. Never call Entrata from a laptop, a Worker, or an agent. Constitution rule 1.

### Error vocabulary you will actually hit

| HTTP | code | meaning |
| --- | --- | --- |
| 400 | 1403 | `method is not allowed to the requested 'orgs'`. Liberty has not licensed or enabled that method for us. Not fixable in code, it needs a PM/Entrata permission change. |
| 400 | 107 | `Auth type 'apikey' is not supported`. That method needs OAuth. |
| 400 | 308 | `The date difference should not be more than 7 days`. The date span you asked for is too wide. Hit on `getCalendarAvailability` with an 8-day span, 2026-08-05. Narrow the window and page through it. |
| 400 | 310 | `fromDate and toDate is required`. A date range the method actually requires was omitted. Hit on `getLeads` r1, 2026-08-05, which the spec says needs only `propertyId`. |
| 400 | 1404-family | Method not found in that group. Almost always the wrong group in the URL. |
| **403** | 1403 | `You're not allowed to access this resource.` **Not the same as 400/1403.** Returned by the three `oauth` methods (`getAccessToken`, `getJwtAccessToken`, `getUserInfo`) on an apikey call, 2026-08-05. Note it is **1403, not the 107** an OAuth-only method would suggest. They are on the roster and still unusable. |
| **403** | **1010, body is NOT JSON** | ⚠️ **Cloudflare edge block, not Entrata.** Bare body reads `error code: 1010`, a browser-signature ban on the client's User-Agent. **Not an auth failure and not a permission failure.** Set an explicit UA. Parse the body before classifying the error: if it is not JSON, it never came from Entrata. |

---

## Permission column legend

| value | meaning |
| --- | --- |
| `YES (verified working)` | On the 28-service roster and probed live, returned a real 200. (Probed 2026-07-31, except `getWorkOrders`, probed 2026-08-03, and the five 2026-08-03 grants, probed 2026-08-05.) (`getAmenities` and `getSpecials` return 200 with zero data. That is a data gap, not a permission gap.) |
| `NO (not in accessible services)` | **Not on the 28-service roster.** Not permissioned. That is a fact about the key, not a guess. |
| `NO (1403, and absent from the roster)` | Probed live 2026-07-31 and returned 400/1403, *and* still absent from the roster. The two agree. Now only `getCustomers`, `getExpiringLeases`, and `getPropertyMedia` carry this value: `getWorkOrders` also 1403'd on 2026-07-31 but was granted 2026-08-03. |
| `NO (not in accessible services), BANNED regardless` | An unpermissioned WRITE. Blocked by the key and by policy, independently. |
| `**WRITE, permissioned but BANNED**` | The key can call it. Policy says never. **Only `sendLeads` and `updateLeads` carry this value.** |
| `NO (107, needs OAuth)` | On the roster but rejects apikey auth. Only `getAppAdditionalServices`, which this spec version does not document. See "Methods Entrata exposes that this spec does not document" below. |

**`YES (granted 2026-08-03, not yet probed)` is retired.** Five rows carried it between 2026-08-03 and
2026-08-05. All five were probed 2026-08-05, all five returned 200, and all five now read
`YES (verified working)`. No row carries the old value and no new row should.

**There is no `unknown (not probed)` value any more.** The full roster was recaptured 2026-08-03, so
each of the 128 methods is now either permissioned or not. Nothing needs probing to find out, and
nothing should be probed to find out. And as of 2026-08-05 there is no "not yet probed" state either:
every permissioned read has returned live data at least once.

⚠️ **"On the roster" is not the same as "callable," and the 2026-08-05 third pass made that concrete
by calling the last four.** `getAccessToken`, `getJwtAccessToken` and `getUserInfo` return **HTTP 403 /
error 1403** on an apikey call, and `getAppAdditionalServices` returns **400 / 107**. All four are on
the 28-service roster and none of them can be used. **The usable surface is 24: 22 reads plus the 2
banned writes.** Do not read "28 services" as 28 things this integration can do.

---

## Methods by group

`*` in the description column means the spec shipped no description for that method and the line was
inferred from the method name and its required params.

### `status` (1 method, 1 read / 0 WRITE)

API health check. The cheapest way to confirm the key and gateway are alive.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/status`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getStatus` | r1 | none | read | YES (verified working), probed 2026-08-05: **HTTP 200**, `{"status":"Success","message":"API service is available and running."}`. Limits 8,640/day, 360/hour, **6/minute** | Check the status of the API and whether it is running or not. **Free liveness check, no permissions needed.** ⚠️ **6/minute is the tightest per-minute limit on the whole API. It cannot be a heartbeat.** |

### `appinfo` (2 methods, 2 read / 0 WRITE)

What this API key can actually see: accessible clients and services.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/appinfo`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getAccessibleClients` | r1 | none | read | YES (verified working), re-probed 2026-08-05: **HTTP 200**, `{"subdomain":"libertyassetgroup","id":19530,"name":"Liberty Asset Group"}` | Retrieves a list of organizations that the authenticated user has access to. **Called on the literal path segment `rsync`, not `libertyassetgroup`.** |
| `getAccessibleServices` | r1 | none | read | YES (verified working) | Returns a list of services that are accessible to the caller, including the URI and service name for each. |

### `applications` (3 methods, 1 read / 2 WRITE)

Rental applications (company-level application list, submit, update).

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/applications`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getCompanyApplications` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieve a list of company applications associated with a specific property, including the questions within each application. |
| `sendApplication` | r1 | `applicants`, `originatingLeadSourceId`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Process a request to submit an application for a property. |
| `updateApplication` | r1 | `applicationId`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Update an existing application, including details about the property, lease terms, and associated applicants. |

### `arcodes` (1 method, 1 read / 0 WRITE)

Accounts-receivable charge codes.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/arcodes`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getArCodes` | r1 | none | read | NO (not in accessible services) | Retrieves a list of AR codes (Accounts Receivable codes) for a given property. |

### `arpayments` (1 method, 1 read / 0 WRITE)

Accounts-receivable payments.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/arpayments`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getArPayments` | r1 | none | read | NO (not in accessible services) | Retrieves accounts receivable (AR) payments based on specified criteria such as payment IDs, status types, and date ranges. |

### `artransactions` (5 methods, 3 read / 2 WRITE)

AR transactions at the lease level, plus reversals and MITS collections.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/artransactions`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getArInvoices` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves Accounts Receivable (AR) invoices based on criteria such as property ID, lease IDs, specific invoice ID, and date ranges. |
| `getLeaseArTransactions` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves Accounts Receivable (AR) transactions for specified leases, allowing filtering by property, lease status, transaction types, and AR codes. |
| `getMitsLeaseArTransactions` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves lease accounts receivable (AR) transactions in a MITS (Multi-Family Information Transaction Standard) format. |
| `sendLeaseArTransactionReversals` | r1 | `Transactions` | **WRITE** | NO (not in accessible services), BANNED regardless | Allows you to reverse specific lease accounts receivable (AR) transactions. |
| `sendLeaseArTransactions` | r1 | `transaction` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends lease Accounts Receivable (AR) transactions to be recorded. |

### `communications` (2 methods, 2 read / 0 WRITE)

Resident marketing/communication preferences (opt-in, opt-out). **The group came onto the API key on
2026-08-03.** It was absent before that. Both methods in the group are on the roster and **both were
probed live 2026-08-05: HTTP 200, real data.**

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/communications`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getMarketingPreferencePickList` | r1 | none | read | YES (verified working), probed 2026-08-05 (r1, no params): HTTP 200, 24 rows. recipientTypes `LEAD` (1) and `RESIDENT` (2); channels `email`, `phone`, `postal_mail`, `sms`; plus 5 `availabilityAlertFrequencies`. **Limits 1,500/day, 60/hour, 10/minute** | Retrieves a list of available marketing and communication preferences. |
| `getMarketingPreferences` | r1 | `customerIds`, `propertyId`, `recipientTypeId` | read | YES (verified working), probed 2026-08-05 (r1, `recipientTypeId` `2` = RESIDENT): HTTP 200, `customers[].preferences[]` with `optIn` per consentType per channel. **LEAD side (`recipientTypeId` `1`) probed the same day: HTTP 200 as well.** Limits 10,000/day, 1,000/hour, 60/minute | Retrieves the current marketing preferences for one or more specified customers. **⚠️ The same customer can carry BOTH a LEAD and a RESIDENT preference set**, so `recipientType` is a lens on the customer, not a partition of them. Read the type that matches the touch you are sending. |

**`getMarketingPreferencePickList` has the tightest HOURLY bucket on the key: 60/hour, plus 1,500/day
and 10/minute.** It is a pick list and it barely changes. Cache it once and read the cache. Do not
call it per request or per resident. Also **parse it defensively: some of the 24 rows come back with no
`consentType` key at all.**

⚠️ **Refinement, 2026-08-05: "the tightest bucket" needs a qualifier, because two pick lists are
tightest in different dimensions.** `getMarketingPreferencePickList` is tightest **hourly** (60/hour).
**`getWorkOrderPickLists` is tightest DAILY at 1,000/day**, below this method's 1,500 and below
everything else on the key. **Cache both.** Anywhere a doc calls the marketing pick list "the tightest
bucket" flatly, it is imprecise.

**Where `customerIds` comes from.** `getMarketingPreferences` requires customer IDs and the `customers`
group is not on our key, but that is not a blocker: **`getMitsLeases` returns them as
`IDType: "Customer ID"`.** Pull the IDs from there, then call this with `recipientTypeId` `2` for
residents (`1` is leads).

### `customers` (8 methods, 4 read / 4 WRITE)

Customer (resident/prospect person) records, testimonials, and review responses. **The entire group
is absent from the API key.** No `customers` service appears in `getAccessibleServices` at all, so
this is not a per-method 1403, it is a group we were never granted. `getCustomers` was probed and
returned 1403, which is consistent.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/customers`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getCustomers` | r1 | `propertyId` | read | NO (1403, and absent from the roster) | Retrieves detailed profiles for specific customers based on search criteria like property or lease status. |
| `getCustomerTestimonials` | r1 | none | read | NO (not in accessible services) | Retrieves customer testimonials for a property, allowing you to filter them by approval status and submission date. |
| `getTestimonialPickLists` | r1 | none | read | NO (not in accessible services) | Retrieves the lists of selectable options used for categorizing customer testimonials. |
| `searchCustomers` | r1 | `propertyId`, `search` | read | NO (not in accessible services) | Searches for customers within a specific property using a keyword, such as a name or building. |
| `sendCustomerTestimonials` | r1 | `PropertyId`, `Testimonials` | **WRITE** | NO (not in accessible services), BANNED regardless | Submits one or more new customer testimonials, including the review text, ratings, and author details. |
| `updateCustomers` | r1 | `customers` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates the profile information for one or more customers. |
| `updateCustomerTestimonials` | r1 | `isPublished`, `propertyId`, `transmissionVendorId` | **WRITE** | NO (not in accessible services), BANNED regardless | Publishes or unpublishes a specific customer testimonial. |
| `updatePropertyResponse` | r1 | `propertyId`, `reviewResponse`, `testimonialId` | **WRITE** | NO (not in accessible services), BANNED regardless | Adds or updates a property's response to a specific customer testimonial. |

### `financial` (15 methods, 11 read / 4 WRITE)

GL, budgets, journal entries, job costing, AP codes, bank accounts, tax forms.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/financial`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getApCodes` | r1 | none | read | NO (not in accessible services) | Retrieves a list of Accounts Payable (AP) codes. |
| `getBankAccounts` | r1 | none | read | NO (not in accessible services) | Retrieves a list of bank accounts and their associated properties. |
| `getBudgetActuals` | r1 | `budgetId`, `glTreeId`, `postMonthFrom`, `postMonthTo`, `propertyId` | read | NO (not in accessible services) | Retrieves a financial report that compares budgeted amounts to actual performance for specific accounts. |
| `getBudgets` | r1 | `propertyIds` | read | NO (not in accessible services) | Retrieves detailed budget information for one or more properties. |
| `getFinancialPickList` | r1, r2 | none | read | NO (not in accessible services) | Retrieves a wide range of predefined lists for financial data and entities. |
| `getGlTransactions` | r1 | `propertyIds` | read | YES (verified working) | Retrieves a detailed list of General Ledger (GL) transactions for specified accounts and properties. |
| `getGlTrees` | r1, r2 | none | read | NO (not in accessible services) | Retrieves the structure of one or more General Ledger (GL) Trees, which represent a company's chart of accounts. |
| `getJobCategories` | r1 | none | read | NO (not in accessible services) | Retrieves a list of job categories used for project accounting. |
| `getJobCostBudgets` | r1 | `propertyIds` | read | NO (not in accessible services) | Retrieves detailed budget information for specific jobs or projects. |
| `getJobs` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves a detailed list of jobs or projects, which can be filtered by property, category, or status. |
| `getTransactionTagLists` | r1 | none | read | NO (not in accessible services) | Retrieves lists of tags that can be applied to financial transactions. |
| `markGlTransactionsExported` | r1 | `glDetails` | **WRITE** | NO (not in accessible services), BANNED regardless | Marks one or more General Ledger (GL) transactions as exported. |
| `sendBudgets` | r1 | `budgets`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates one or more new budgets for a specific property. |
| `sendJournalEntries` | r1 | `glHeaders` | **WRITE** | NO (not in accessible services), BANNED regardless | Posts one or more new General Ledger (GL) journal entries. |
| `updateBudgets` | r1 | `budgets`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates the monthly budgeted amounts for one or more existing budgets. |

### `leads` (10 methods, 5 read / 5 WRITE)

Prospects and quotes. This is the demand-engine group.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/leads`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `applyQuote` | r1 | `applicationId`, `leaseTermId`, `propertyId`, `quoteId` | **WRITE** | NO (not in accessible services), BANNED regardless | Applies a specific rental price quote to a prospective tenant's application for a chosen lease term. |
| `generateQuotes` | r1 | `applicationId`, `propertyId`, `quotes` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates one or more rental price quotes for a prospective tenant. |
| `getLeadEvents` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves the communication and activity history for a specific lead. |
| `getLeadPickLists` | r1, r2 | **r1:** none<br>**r2:** `propertyId` | read | YES (verified working) | Retrieves a comprehensive set of predefined option lists for a specific property. |
| `getLeads` | r1 | `propertyId`, `fromDate`, `toDate`<br>(the spec lists only `propertyId`; the live API rejects the call without the date range, 400 / code 310)<br>**Window cap is 730 days**, confirmed 2026-08-05 | read | YES (verified working). Limits 27,000/day, 5,000/hour, 135/minute | Retrieves lead/prospect information with comprehensive filtering options including demographics, events, and customer preferences. **Carries `birthDate` and is the only working DOB source on this key, but it is a PARTIAL feed: 286 of 787 distinct lead-customers across the full 2021-2026 history, which is 36%.** (An earlier revision of this row said "122 of 122," which was a denominator artifact, not coverage. See the birth-dates note below.) **Also carries full pet records: 126 of them on the 2026-08-05 window, with `name`, `petType`, `breed`, `color`, `gender`, `age`, `weight`, `count`, `id`, `licenseCity`.** |
| `getMitsLeads` | r1 | none | read | NO (not in accessible services) | Retrieves detailed lead and prospect information based on various search criteria. |
| `getQuotes` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves one or more rental quotes associated with a prospective tenant's application. |
| `sendLeads` | r1 | `propertyId`, `prospects` | **WRITE** | **WRITE, permissioned but BANNED** | Adds a new sales lead to a property's database. |
| `sendMitsLeads` | r1 | `Prospects`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Submits a batch of one or more new sales leads to a property's management system. |
| `updateLeads` | r1, r2 | **r1:** `ApplicationId`, `PropertyId`, `Prospects`<br>**r2:** `propertyId`, `prospects` | **WRITE** | **WRITE, permissioned but BANNED** | Updates an existing lead/prospect with comprehensive customer information, events, and preferences. |

**`getLeadEvents` is NOT permissioned.** Only `getLeadPickLists` and `getLeads` are on the roster, so
there is no dedicated lead-event feed. **Mitigation: `getLeads` r1 accepts `eventDateFrom`,
`eventDateTo`, and `eventTypeIds` (max 5) and returns the matching events inline.** Lead-event deltas
are still pollable on a method we do have, which makes losing `getLeadEvents` a nuisance rather than a
blocker. Enabling it is still worth asking for (fewer calls, cleaner deltas), just not urgent.

**`getLeads` r1 needs `fromDate` and `toDate`, not just `propertyId`.** The spec says `propertyId` is
the only required param. It is wrong. Omit the dates and you get 400 / code 310,
`fromDate and toDate is required`. Confirmed 2026-08-05.

**`getLeads` r1 accepts a 730-day (2-year) window, so a full history sweep is 3 calls.** Confirmed
2026-08-05: 730-day spans were accepted on the first try and 2021-01-01 through 2026-08-05 covered in
three requests. Historical backfill on this method is cheap. ⚠️ **Do not carry that number to another
method.** `getCalendarAvailability` caps at 7 days. **Window caps are per method** (see the gotchas
above).

**Pets: `getLeads` r1 carries them too, 126 records on the 2026-08-05 window**, with `name`,
`petType`, `breed`, `color`, `gender`, `age`, `weight`, `count`, `id`, and `licenseCity`. It is the
deepest pet feed by volume but it is funnel data, so it includes prospects who never signed.
**`getLeases` r1 is the better source for residents** (see the pets note under `leases` below), and
the fair-housing filter on assistance animals applies to anything built off either.

**Birth dates: `getLeads` r1 is the only source that works, and it covers about two thirds of the
roll.** Five response schemas in this spec carry a birth-date field, `getLeads` r1 (`birthDate`),
`getLeases` r1 and r2 (`dateOfBirth`), `getMitsLeases` r1 (`BirthDate`), `getEvictedLeases` r1, and
`getMitsCollections` r1. **A schema field is not data.** Probed live 2026-08-05: `getLeases` r1 and r2
return zero birth keys, `getMitsLeases` returns zero. Liberty does not populate them. **`getLeads` r1
does.** So anything that needs a resident or prospect date of birth runs off `getLeads`.
(`getEvictedLeases` and `getMitsCollections` are not permissioned, so they were not probed and never
will be on this key.)

⚠️ **CORRECTION, 2026-08-05 third pass: this note used to say "122 of 122 records came back with a
non-empty `birthDate`," and that was not a coverage figure.** **Entrata omits null fields entirely**,
so counting non-empty values against *occurrences of the key* can only ever return 100%: the customers
with no birth date never carried the key and were never in the denominator. **Use distinct customers as
the denominator or you will re-derive the same wrong number.** The measured picture, from a full
historical sweep (2021-01-01 through 2026-08-05) joined to the rent roll:

| Measure | Count |
| --- | --- |
| Distinct lead-customers in `getLeads`, full history | **787** |
| Of those, carrying a `birthDate` | **286, which is 36%** |
| Customer records across the 52 leases (`getLeases`) | **103**, of which **88** are `Current` |
| Current residents appearing anywhere in `getLeads` | **70 of 88** |
| Current residents carrying a `birthDate` | **57 of 88** |
| **DOB coverage of current residents** | **65%** |

The 35% gap (31 residents) splits two ways: **18 current residents never appear in `getLeads` at all** (structural, no
window recovers them) and **13 appear with an empty field.** **Do not describe birthday coverage as
complete.** The Welcome Profile is the permanent fallback for the remainder. Full treatment in
`entrata-api-context.md` §4.20.

✅ **The join is proven.** `getLeads` `customers.customer[].customerId` and `getLeases` customer `id`
are **the same ID namespace**: 70 of 88 matched on that key alone, no name or email fuzzing. An earlier
worry that they were different ID spaces is resolved. Lead customer objects carry `applicantId`,
`birthDate`, `cellPhoneNumber`, `customerId`, `customerRelationshipType(Id)`, `customerType`, `email`,
`firstName`, `lastName`, `middleName`, `namePrefix`, `personalPhoneNumber`, `phones`, `addresses`.

### `leases` (24 methods, 12 read / 12 WRITE)

Leases and their lifecycle: details, documents, charges, move-in/out, notice, cancel.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/leases`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `cancelLease` | r1 | `leaseId`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Cancels a lease on a property. * |
| `getEvictedLeases` | r1 | `propertyId` | read | NO (not in accessible services) | Lists leases at a property that are in eviction. * |
| `getExpiringLeases` | r1 | `propertyId`, `toDate` | read | NO (1403, and absent from the roster) | Lists leases at a property expiring on or before a date. * |
| `getLeaseActivities` | r1 | `leaseId`, `propertyId` | read | NO (not in accessible services) | Lists the activity history logged against a lease. * |
| `getLeaseDetails` | r1, r2 | **r1:** `leaseId`, `propertyId`<br>**r2:** `propertyId` | read | YES (verified working). **r2 probed 2026-08-05: HTTP 200**, result keys `currencyCode` + `leases`. Limits 50,000/day, 5,000/hour, 1,000/minute | Full detail for a lease: residents, charges, terms, unit. * **r1 is the single-lease read, r2 is the property-wide sweep** (it takes `propertyId` only), so r2 is the cheaper shape for charge detail across the whole roll. **On a Cancelled lease r1 returns a near-empty stub**, so filter to Current first. |
| `getLeaseDocuments` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves lease document files for a property. * |
| `getLeaseDocumentsList` | r1 | `propertyId` | read | NO (not in accessible services) | Lists the lease documents available for a property (metadata, not files). * |
| `getLeasePickList` | r1 | none | read | NO (not in accessible services) | Method parameters (no parameters required for this method). |
| `getLeases` | r1, r2 | `propertyId` | read | YES (verified working) | Lists leases at a property with status, term, and resident info. * **Best pet source on the key: 30 of 52 leases have pets, 34 individual pet records, each with `name`, `petType`, `breed`, `color`, `gender`, `age`, `weight`, `moveInDate`, `customerId`, and `isAssistanceAnimal`** (r1 probed 2026-08-05). |
| `getMitsCollections` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves MITS collections data for a property. |
| `getMitsLeases` | r1 | `propertyId` | read | YES (verified working), probed 2026-08-05 (r1, `propertyId`): HTTP 200, 100 `Tenant` records against 52 `LA_Lease`. Limits 20,000/day, 4,500/hour, 200/minute | Retrieves MITS lease data for a property with various filtering options. **Its `BirthDate` field is empty in live data, so this is not the DOB source.** It is where customer IDs come from (`IDType: "Customer ID"`), which is what `getMarketingPreferences` needs. **Pets here are thin: `Count`, `PetType`, `Weight`, no name. Use `getLeases` instead.** ⚠️ **Its r1 response schema declares `SocialSecurity`.** Live data returned no SSN-like keys at all (Liberty leaves it empty), but **NPI never ingests, persists, or logs an SSN**: strip it at the request choke point on read. |
| `getParcelAlerts` | r1 | `propertyId` | read | NO (not in accessible services) | Lists package/parcel alerts logged for a property. * |
| `getRentersInsurancePolicies` | r1 | `propertyId` | read | NO (not in accessible services) | Lists renters insurance policies on file for a property. * |
| `moveInLease` | r1 | `leaseId`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Moves a lease in (records the move-in). * |
| `moveOutLease` | r1 | `leaseId`, `moveOutDate`, `moveOutReasonId`, `moveOutTypeId`, `propertyId`, `unitAvailableOnDate` | **WRITE** | NO (not in accessible services), BANNED regardless | Moves a lease out (records the move-out, reason, and unit-available date). * |
| `onNoticeLease` | r1 | `leaseId`, `moveOutDate`, `moveOutReasonId`, `moveOutTypeId`, `propertyId`, `submitRefundDetails`, `unitAvailableOnDate` | **WRITE** | NO (not in accessible services), BANNED regardless | Puts a lease on notice (notice to vacate with move-out date and reason). * |
| `sendLeaseActivities` | r1 | `events`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends lease activities. |
| `sendLeaseDocuments` | r1 | `files`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Upload one or more documents and associate them with a lease, application, or applicant. |
| `sendLeases` | r1 | `leases`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends leases. |
| `sendRentersInsurancePolicies` | r1, r2 | `insurancePolicies`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends renters insurance policies. |
| `sendRoommateGroups` | r1, r2 | **r1:** `propertyId`, `roommateGroups`<br>**r2:** `roommateGroups` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends roommate groups. |
| `sendScheduledCharges` | r1 | `propertyId`, `scheduledCharges` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends scheduled charges. |
| `updateLease` | r1 | `leaseId`, `occupants`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates a lease. |
| `updateScheduledCharges` | r1, r2 | **r1:** `leaseId`, `propertyId`, `scheduledCharges`<br>**r2:** `propertyId`, `scheduledCharges` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates scheduled charges. |

**`getLeaseDocuments` and `getLeaseDocumentsList` are the only route to an executed lease document, and
neither is permissioned.** Nothing else on this key returns the signed PDF or even its metadata.
`getLeases` and `getLeaseDetails` give you terms, dates, residents, and charges, not the document. If a
workflow ever needs the actual executed lease, that is the ask to put to Liberty. Until then it comes out
of Entrata by hand.

**Birth dates are not here.** `getLeases` r1/r2 (`dateOfBirth`) and `getMitsLeases` r1 (`BirthDate`) both
declare the field and both return it empty in Liberty's data. Probed 2026-08-05. Use `getLeads` r1, see
the birth-dates note under `leads` above, **and note that it covers only 65% of current residents**.

**What `getLeases` DOES supply for the birthday feed is the join key.** Its customer `id` is the same
namespace as `getLeads` `customerId`, proven 2026-08-05 (70 of 88 current residents matched). It is
also where the rent-roll denominator comes from: **103 customer records across the 52 leases, 88 of
them `Current`**, since roommates and guarantors make customers outnumber leases.

**Pets ARE here, and `getLeases` r1 is the best source on the key.** Probed 2026-08-05: **30 of 52
leases have pets, 34 individual pet records**, each carrying `name`, `petType`, `breed`, `color`,
`gender`, `age`, `weight`, `moveInDate`, `customerId`, and `isAssistanceAnimal`. `getMitsLeases` has
only `Count` / `PetType` / `Weight` and **no name**, so do not use it for pets. `getLeads` r1 carries
126 pet records but they are funnel-stage. `getPetTypes` (group `properties`) is **not on the key and
is not needed**, since `petType` comes back inline. ⚠️ **`isAssistanceAnimal` is a hard fair-housing
filter: assistance and service animals are not pets and must be excluded from the pet-gift program
and any pet-themed marketing.** Full treatment in `entrata-api-context.md` §4.21.

🚫 **SSN: never ingest, persist, or log one.** `getMitsLeases` r1 is the only method on our key whose
response schema declares an SSN field (`SocialSecurity`); `getMitsCollections` r1 (`SSN`) and
`getVendors` r1 (`taxIdNumber`) also declare one and are not permissioned. **Live data came back with
no SSN-like keys at all**, so Liberty leaves the field empty today, **but a schema field can start
populating without notice.** The read-method allowlist choke point strips `SocialSecurity` / `SSN` /
`taxId` on read, before anything is stored, logged, or shown to a model. Deny by default.
`entrata-api-context.md` §8 item 7.

### `leasingcenter` (2 methods, 2 read / 0 WRITE)

Leasing-center call logs and pick lists.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/leasingcenter`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getCallLogs` | r1 | `propertyIds` | read | NO (not in accessible services) | Retrieves call logs for a specific property, including details about the caller, destination phone number, call type, and result. |
| `getLeasingCenterPickLists` | r1 | none | read | NO (not in accessible services) | Method parameters (no parameters required for this method). |

### `maintenance` (6 methods, 4 read / 2 WRITE)

Work orders and inspections. **The group is now on the API key as of 2026-08-03**, and Liberty granted
exactly two methods out of it: `getWorkOrders` and `getWorkOrderPickLists`. Both are reads.

**Do not read the group grant as a blanket grant.** `getInspections` and `getInspectionTemplates` are
still not on the roster, and **`sendWorkOrders` and `updateWorkOrders` are still NOT permissioned.** The
old explanation for the two writes ("the whole group is absent") no longer applies, but the conclusion
does: they were not granted, and they are banned by policy regardless.

`getWorkOrders` returned 1403 when probed 2026-07-31 and returns real data now. That is the permission
change, not a spec change. **Both granted reads have now been probed live: `getWorkOrders` on
2026-08-03, `getWorkOrderPickLists` on 2026-08-05, both HTTP 200.**

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/maintenance`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getInspections` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves detailed inspection information based on various search criteria. |
| `getInspectionTemplates` | r1 | `propertyIds` | read | NO (not in accessible services) | Retrieves inspection templates based on various search criteria. |
| `getWorkOrderPickLists` | r1 | none | read | YES (verified working), probed 2026-08-05 (r1, no params): HTTP 200. ⚠️ **Limits 1,000/day, 500/hour, 60/minute: the TIGHTEST DAILY bucket on the key** | Retrieves work order picklists based on various search criteria. Property-scoped `Locations` (with nested `unitTypes`), `Priorities`, `StatusTypes`, `Categories`, `Problems`, and `SubMaintenanceProblems`, plus `WorkOrderTypes` (5), `CompanyEmployees` (12, the Liberty staff roster), and `InspectionStatuses` (5). **Cache it. 1,000/day is below `getMarketingPreferencePickList`'s 1,500 and below everything else on the key.** |
| `getWorkOrders` | r1 | `propertyId` | read | YES (verified working), granted 2026-08-03 and probed the same day (r1, `propertyId` `1311115`): HTTP 200, real production work orders. Limits 25,000/day, 1,500/hour, 150/minute | Retrieves work orders based on various search criteria. **Carries `petInfo`**, which is the one operational use of pet data: warning a technician there is an animal in the unit before they enter. |
| `sendWorkOrders` | r1 | `workOrder` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates new work orders. |
| `updateWorkOrders` | r1, r2 | `propertyId`, `workOrder` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates existing work orders. |

### `pricing` (4 methods, 2 read / 2 WRITE)

Revenue-management pricing feeds (insert pricing, budgeted rent).

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/pricing`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getPricingPicklists` | r1 | none | read | NO (not in accessible services) | Gets pricing picklists. |
| `getPropertyFees` | r1 | `propertyId` | read | NO (not in accessible services) | Gets property fees. |
| `insertPricing` | r1, r2 | `pricing`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Inserts pricing. |
| `sendBudgetedRent` | r1 | `pricing`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends budgeted rent. |

### `properties` (18 methods, 13 read / 5 WRITE)

Property master data: properties, websites, phone numbers, fees, announcements, tour calendar.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/properties`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `deletePropertyMedia` | r1 | `id`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Deletes property media associations for the specified property by media IDs. |
| `getAmenityReservations` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves amenity reservations for a property, optionally filtered by amenity IDs and reservation status types. |
| `getCalendarAvailability` | r1, r2 | **r1:** `fromDate`, `propertyId`, `toDate`<br>**r2:** `fromDate`, `propertyId`, `toDate`, `tourType`<br>(dates are `MM/DD/YYYY`, and **the span may not exceed 7 days**) | read | YES (verified working), probed 2026-08-05 (r1): HTTP 200. Limits 48,000/day, 2,000/hour, 120/minute | Returns available tour time slots for a property within a date span for a given tour type. **Max span is 7 days**, an 8-day span returns 400 / code 308 `The date difference should not be more than 7 days` (confirmed on r1). The configuration it returned: 30-minute appointments, 120-minute minimum lead time, agent-guided Mon-Fri 08:00-16:00 MST with no simultaneous limit, self-guided all 7 days 06:00-18:00 MST with a limit of 1. |
| `getFloorPlans` | r1 | `propertyId` | read | YES (verified working) | Retrieves floor plans and related details for a property. |
| `getPetTypes` | r1 | `propertyIds` | read | NO (not in accessible services) | Retrieves default pet types configured for the specified properties. **Not needed, do not ask for it:** `petType` comes back inline on the pet records in `getLeases` and `getLeads`, so the type dictionary buys nothing. |
| `getPhoneNumber` | r1 | `propertyIds` | read | NO (not in accessible services) | Returns phone numbers for properties by lead source switch code or by referring domain. |
| `getProperties` | r1 | none | read | YES (verified working) | Retrieves detailed property information for one or more properties. |
| `getPropertyAddOns` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves add-ons for a property, including visibility, availability, date windows, and rates. |
| `getPropertyAnnouncements` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves published property and company announcements for a property (Resident Portal product). |
| `getPropertyMedia` | r1 | `propertyId` | read | NO (1403, and absent from the roster) | Retrieves property media associations with optional filtering by media type, subtype, and reference IDs. |
| `getPropertyPickLists` | r1, r2 | none | read | NO (not in accessible services) | Retrieves expanded pick lists for one or more properties (R2), including unit types, buildings, floorplans, add-on groups, search areas,. |
| `getRentableItems` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves rentable items for a specific property. |
| `getReservableAmenities` | r1 | `propertyId` | read | NO (not in accessible services) | Retrieves reservable amenities, block days/hours, limits, visibility, and rates for a property. |
| `getWebsites` | r1 | `propertyIds` | read | YES (verified working) | Retrieves websites configured for the given properties, including linked properties and domains. |
| `sendFloorPlans` | r1 | `floorPlans`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates floor plans for the specified property. |
| `sendPropertyMedia` | r1 | `media`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Inserts property media associations for the specified property. |
| `sendRentableItems` | r1 | `propertyId`, `rentableItemTypes` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates rentable item types (groups) and their rentable items for a property. |
| `updatePropertyMedia` | r1 | `media`, `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates existing property media associations for the specified property. |

### `propertyunits` (11 methods, 6 read / 5 WRITE)

Units, unit types, floor plans, amenities, specials, availability and pricing.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/propertyunits`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getAmenities` | r1 | `propertyId` | read | YES (verified working) | Retrieves amenities for a property, including property-level amenities, unit amenities, floorplan amenities, and unit type amenities with their. |
| `getMitsPropertyUnits` | r1 | `propertyIds` | read | NO (not in accessible services) | Retrieves comprehensive MITS-formatted property unit data including floorplans, buildings, amenities, pricing, availability, and pet policies for. |
| `getPropertyUnits` | r1 | `propertyIds` | read | YES (verified working) | Retrieves comprehensive property unit details including unit spaces with lease term pricing, availability status, amenities, custom key data,. |
| `getSpecials` | r1, r2, r3, r4 | `propertyId` | read | YES (verified working) | Retrieves special groups with comprehensive details including specials, rates, associations, conditions, lease terms, space configurations, lead. |
| `getUnitsAvailabilityAndPricing` | r1 | `propertyId` | read | YES (verified working) | Retrieves comprehensive unit availability and pricing information including floorplan details, unit spaces with lease terms, deposits, amenities,. |
| `getUnitTypes` | r1 | `propertyId` | read | YES (verified working) | Retrieves unit types for a property with floorplan associations, bedroom/bathroom counts, square footage ranges, market rent ranges, and lease. |
| `sendAmenities` | r1 | `propertyAmenities`, `propertyId`, `unitAmenities` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates property-level amenities and unit-level amenities with their rate associations for a specified property and unit spaces. |
| `sendPropertyUnits` | r1 | `propertyId`, `units` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates property units with unit spaces, including address, floorplan, building, floor associations, amenities, specials, and lease term. |
| `sendSpecialGroup` | r1 | `propertyId`, `specialGroup` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates a special group with specials, lease terms, associations (property, floorplan, or unit level), conditions, lead sources, and recipient. |
| `updateAmenities` | r1 | `propertyId` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates existing amenities for property, unit type, floorplan, or unit space levels with details including name, description, visibility settings,. |
| `updateSpecialGroup` | r1 | `propertyId`, `specialGroup` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates an existing special group or deletes it if isDelete is set to 1. |

### `queue` (1 method, 1 read / 0 WRITE)

Async queue. Long-running requests return a queueId; poll getResponse for the payload.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/queue`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getResponse` | r1 | `queueId`, `serviceName` | read | NO (not in accessible services) | Retrieves the response for a queued API request using the queueId. |

### `vendors` (14 methods, 7 read / 7 WRITE)

Vendors, AP invoices, purchase orders, PO receiving.

URL: `POST https://apis.entrata.com/ext/orgs/libertyassetgroup/v1/vendors`

| method | version(s) | required params | read/WRITE | permissioned for us? | what it does |
| --- | --- | --- | --- | --- | --- |
| `getInvoices` | r1, r2 | none | read | NO (not in accessible services) | Retrieves invoices for a specific vendor or property. |
| `getPoReceivingRecords` | r1 | none | read | NO (not in accessible services) | Retrieves purchase order receiving records for vendors. |
| `getPurchaseOrders` | r1 | none | read | NO (not in accessible services) | Retrieves purchase orders for vendors. |
| `getTaxFormData` | r1 | `endDate`, `startDate` | read | NO (not in accessible services) | Retrieves tax form data (1099) for vendors by property or owner. |
| `getVendorLocations` | r1 | none | read | NO (not in accessible services) | Retrieves vendor locations with associated details. |
| `getVendorPickLists` | r1 | none | read | NO (not in accessible services) | Retrieves pick list options for vendor-related dropdowns and forms. |
| `getVendors` | r1 | none | read | NO (not in accessible services) | Retrieves detailed vendor information by vendor IDs or vendor codes. |
| `markInvoicesExported` | r1 | `lineItems` | **WRITE** | NO (not in accessible services), BANNED regardless | Marks invoice line items as exported by updating their exported status. |
| `sendInvoices` | r1, r2 | **r1:** `ApBatch`<br>**r2:** `apBatch` | **WRITE** | NO (not in accessible services), BANNED regardless | Sends invoice batch data including headers, details, and optional payments to the system (r2 version with camelCase parameters). |
| `sendPurchaseOrders` | r1 | `apHeaders` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates purchase orders from AP header records. * |
| `sendVendors` | r1 | `vendors` | **WRITE** | NO (not in accessible services), BANNED regardless | Creates vendor records. * |
| `updateInvoices` | r1 | `apHeaders` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates existing AP invoices. * |
| `updateVendors` | r1 | `vendors` | **WRITE** | NO (not in accessible services), BANNED regardless | Updates existing vendor records. * |
| `voidApPayments` | r1 | `apPayments` | **WRITE** | NO (not in accessible services), BANNED regardless | Method parameters containing payment(s) to void with void date, post month, and optional note. |

---

## Group map (which group does a method live in?)

Picking the wrong group is the most common failure mode. The group goes in the URL path.
Ctrl-F the method name here first.

| group | methods |
| --- | --- |
| `status` | `getStatus` |
| `appinfo` | `getAccessibleClients`, `getAccessibleServices` |
| `applications` | `getCompanyApplications`, `sendApplication`, `updateApplication` |
| `arcodes` | `getArCodes` |
| `arpayments` | `getArPayments` |
| `artransactions` | `getArInvoices`, `getLeaseArTransactions`, `getMitsLeaseArTransactions`, `sendLeaseArTransactionReversals`, `sendLeaseArTransactions` |
| `communications` | `getMarketingPreferencePickList`, `getMarketingPreferences` |
| `customers` | `getCustomers`, `getCustomerTestimonials`, `getTestimonialPickLists`, `searchCustomers`, `sendCustomerTestimonials`, `updateCustomers`, `updateCustomerTestimonials`, `updatePropertyResponse` |
| `financial` | `getApCodes`, `getBankAccounts`, `getBudgetActuals`, `getBudgets`, `getFinancialPickList`, `getGlTransactions`, `getGlTrees`, `getJobCategories`, `getJobCostBudgets`, `getJobs`, `getTransactionTagLists`, `markGlTransactionsExported`, `sendBudgets`, `sendJournalEntries`, `updateBudgets` |
| `leads` | `applyQuote`, `generateQuotes`, `getLeadEvents`, `getLeadPickLists`, `getLeads`, `getMitsLeads`, `getQuotes`, `sendLeads`, `sendMitsLeads`, `updateLeads` |
| `leases` | `cancelLease`, `getEvictedLeases`, `getExpiringLeases`, `getLeaseActivities`, `getLeaseDetails`, `getLeaseDocuments`, `getLeaseDocumentsList`, `getLeasePickList`, `getLeases`, `getMitsCollections`, `getMitsLeases`, `getParcelAlerts`, `getRentersInsurancePolicies`, `moveInLease`, `moveOutLease`, `onNoticeLease`, `sendLeaseActivities`, `sendLeaseDocuments`, `sendLeases`, `sendRentersInsurancePolicies`, `sendRoommateGroups`, `sendScheduledCharges`, `updateLease`, `updateScheduledCharges` |
| `leasingcenter` | `getCallLogs`, `getLeasingCenterPickLists` |
| `maintenance` | `getInspections`, `getInspectionTemplates`, `getWorkOrderPickLists`, `getWorkOrders`, `sendWorkOrders`, `updateWorkOrders` |
| `pricing` | `getPricingPicklists`, `getPropertyFees`, `insertPricing`, `sendBudgetedRent` |
| `properties` | `deletePropertyMedia`, `getAmenityReservations`, `getCalendarAvailability`, `getFloorPlans`, `getPetTypes`, `getPhoneNumber`, `getProperties`, `getPropertyAddOns`, `getPropertyAnnouncements`, `getPropertyMedia`, `getPropertyPickLists`, `getRentableItems`, `getReservableAmenities`, `getWebsites`, `sendFloorPlans`, `sendPropertyMedia`, `sendRentableItems`, `updatePropertyMedia` |
| `propertyunits` | `getAmenities`, `getMitsPropertyUnits`, `getPropertyUnits`, `getSpecials`, `getUnitsAvailabilityAndPricing`, `getUnitTypes`, `sendAmenities`, `sendPropertyUnits`, `sendSpecialGroup`, `updateAmenities`, `updateSpecialGroup` |
| `queue` | `getResponse` |
| `vendors` | `getInvoices`, `getPoReceivingRecords`, `getPurchaseOrders`, `getTaxFormData`, `getVendorLocations`, `getVendorPickLists`, `getVendors`, `markInvoicesExported`, `sendInvoices`, `sendPurchaseOrders`, `sendVendors`, `updateInvoices`, `updateVendors`, `voidApPayments` |

### Alphabetical reverse lookup (method to group)

| method | group |
| --- | --- |
| `applyQuote` | `leads` |
| `cancelLease` | `leases` |
| `deletePropertyMedia` | `properties` |
| `generateQuotes` | `leads` |
| `getAccessibleClients` | `appinfo` |
| `getAccessibleServices` | `appinfo` |
| `getAmenities` | `propertyunits` |
| `getAmenityReservations` | `properties` |
| `getApCodes` | `financial` |
| `getArCodes` | `arcodes` |
| `getArInvoices` | `artransactions` |
| `getArPayments` | `arpayments` |
| `getBankAccounts` | `financial` |
| `getBudgetActuals` | `financial` |
| `getBudgets` | `financial` |
| `getCalendarAvailability` | `properties` |
| `getCallLogs` | `leasingcenter` |
| `getCompanyApplications` | `applications` |
| `getCustomers` | `customers` |
| `getCustomerTestimonials` | `customers` |
| `getEvictedLeases` | `leases` |
| `getExpiringLeases` | `leases` |
| `getFinancialPickList` | `financial` |
| `getFloorPlans` | `properties` |
| `getGlTransactions` | `financial` |
| `getGlTrees` | `financial` |
| `getInspections` | `maintenance` |
| `getInspectionTemplates` | `maintenance` |
| `getInvoices` | `vendors` |
| `getJobCategories` | `financial` |
| `getJobCostBudgets` | `financial` |
| `getJobs` | `financial` |
| `getLeadEvents` | `leads` |
| `getLeadPickLists` | `leads` |
| `getLeads` | `leads` |
| `getLeaseActivities` | `leases` |
| `getLeaseArTransactions` | `artransactions` |
| `getLeaseDetails` | `leases` |
| `getLeaseDocuments` | `leases` |
| `getLeaseDocumentsList` | `leases` |
| `getLeasePickList` | `leases` |
| `getLeases` | `leases` |
| `getLeasingCenterPickLists` | `leasingcenter` |
| `getMarketingPreferencePickList` | `communications` |
| `getMarketingPreferences` | `communications` |
| `getMitsCollections` | `leases` |
| `getMitsLeads` | `leads` |
| `getMitsLeaseArTransactions` | `artransactions` |
| `getMitsLeases` | `leases` |
| `getMitsPropertyUnits` | `propertyunits` |
| `getParcelAlerts` | `leases` |
| `getPetTypes` | `properties` |
| `getPhoneNumber` | `properties` |
| `getPoReceivingRecords` | `vendors` |
| `getPricingPicklists` | `pricing` |
| `getProperties` | `properties` |
| `getPropertyAddOns` | `properties` |
| `getPropertyAnnouncements` | `properties` |
| `getPropertyFees` | `pricing` |
| `getPropertyMedia` | `properties` |
| `getPropertyPickLists` | `properties` |
| `getPropertyUnits` | `propertyunits` |
| `getPurchaseOrders` | `vendors` |
| `getQuotes` | `leads` |
| `getRentableItems` | `properties` |
| `getRentersInsurancePolicies` | `leases` |
| `getReservableAmenities` | `properties` |
| `getResponse` | `queue` |
| `getSpecials` | `propertyunits` |
| `getStatus` | `status` |
| `getTaxFormData` | `vendors` |
| `getTestimonialPickLists` | `customers` |
| `getTransactionTagLists` | `financial` |
| `getUnitsAvailabilityAndPricing` | `propertyunits` |
| `getUnitTypes` | `propertyunits` |
| `getVendorLocations` | `vendors` |
| `getVendorPickLists` | `vendors` |
| `getVendors` | `vendors` |
| `getWebsites` | `properties` |
| `getWorkOrderPickLists` | `maintenance` |
| `getWorkOrders` | `maintenance` |
| `insertPricing` | `pricing` |
| `markGlTransactionsExported` | `financial` |
| `markInvoicesExported` | `vendors` |
| `moveInLease` | `leases` |
| `moveOutLease` | `leases` |
| `onNoticeLease` | `leases` |
| `searchCustomers` | `customers` |
| `sendAmenities` | `propertyunits` |
| `sendApplication` | `applications` |
| `sendBudgetedRent` | `pricing` |
| `sendBudgets` | `financial` |
| `sendCustomerTestimonials` | `customers` |
| `sendFloorPlans` | `properties` |
| `sendInvoices` | `vendors` |
| `sendJournalEntries` | `financial` |
| `sendLeads` | `leads` |
| `sendLeaseActivities` | `leases` |
| `sendLeaseArTransactionReversals` | `artransactions` |
| `sendLeaseArTransactions` | `artransactions` |
| `sendLeaseDocuments` | `leases` |
| `sendLeases` | `leases` |
| `sendMitsLeads` | `leads` |
| `sendPropertyMedia` | `properties` |
| `sendPropertyUnits` | `propertyunits` |
| `sendPurchaseOrders` | `vendors` |
| `sendRentableItems` | `properties` |
| `sendRentersInsurancePolicies` | `leases` |
| `sendRoommateGroups` | `leases` |
| `sendScheduledCharges` | `leases` |
| `sendSpecialGroup` | `propertyunits` |
| `sendVendors` | `vendors` |
| `sendWorkOrders` | `maintenance` |
| `updateAmenities` | `propertyunits` |
| `updateApplication` | `applications` |
| `updateBudgets` | `financial` |
| `updateCustomers` | `customers` |
| `updateCustomerTestimonials` | `customers` |
| `updateInvoices` | `vendors` |
| `updateLeads` | `leads` |
| `updateLease` | `leases` |
| `updatePropertyMedia` | `properties` |
| `updatePropertyResponse` | `customers` |
| `updateScheduledCharges` | `leases` |
| `updateSpecialGroup` | `propertyunits` |
| `updateVendors` | `vendors` |
| `updateWorkOrders` | `maintenance` |
| `voidApPayments` | `vendors` |

---

## Totals

- **128 methods** across **18 groups**, **146 method+version combinations**
- **78** read, **50** WRITE
- **24 of the 128 are permissioned:** 22 reads + 2 WRITEs (`sendLeads`, `updateLeads`, both **BANNED**).
  **All 22 reads are verified working** (16 probed 2026-07-31, `getWorkOrders` probed 2026-08-03, and the
  last 5 probed 2026-08-05: `getWorkOrderPickLists`, `getMitsLeases`, `getCalendarAvailability`,
  `getMarketingPreferences`, `getMarketingPreferencePickList`). **None is granted-but-unprobed.**
- **The write count did not move on 2026-08-03.** It was 2 and it is still 2. All six new grants are reads.
- **104 of the 128 are not permissioned.** Three of those were also probed live and returned 1403
  (`getCustomers`, `getExpiringLeases`, `getPropertyMedia`); the rest are known unpermissioned because
  they are absent from the 28-service roster
- **Nothing is "unprobed" any more, in either sense.** The roster settles permission for every method in
  the spec, and as of the 2026-08-05 third pass **every one of the 28 services on the key has been
  called at least once**, including `getStatus`, `getAccessibleClients` and the four that always error.
- The key also carries **4 services this spec does not document**: `getAccessToken`,
  `getJwtAccessToken`, `getUserInfo` (oauth, unused) and `getAppAdditionalServices` (OAuth-only).
  22 + 2 + 4 = the 28 on the roster. **All four were probed 2026-08-05 and all four error**, so the
  **usable surface is 24**, not 28.

## Methods Entrata exposes that this spec does not document

- **`getAppAdditionalServices`** appears nowhere in this spec (grep it, zero hits), but it is a real endpoint.
  Probed live 2026-07-31 and re-probed 2026-08-05, same result both times: HTTP 400, code 107,
  `Auth type 'apikey' is not supported`. It needs OAuth, so it is out of reach on the current key
  regardless. Do not go hunting for it in the YAML.
- **`getAccessToken`, `getJwtAccessToken`, `getUserInfo`** (group `oauth`) are on the accessible-services
  roster and are likewise absent from this spec. This integration authenticates with `X-Api-Key`, so all
  three are unused. Do not switch auth modes without a reason. **Probed live 2026-08-05: all three
  return HTTP 403, code 1403, `You're not allowed to access this resource.`** ⚠️ **Note that is 1403,
  NOT the 107** you would expect from an OAuth-only method, so the error code alone does not tell you
  which of the two problems you have. They are on the roster and unusable on this key either way.
- If you hit any other method name that is not in the tables above, the spec is a 2026-07-10 snapshot and
  Entrata ships changes between snapshots. Check `getAccessibleServices` against reality before assuming
  a method does not exist.

### Classification notes

- The read/WRITE split follows the prefix rule: anything starting with `send`, `update`, `insert`, `delete`, `post`, `create`, `assign`, `cancel`, `move`, `mark`, `apply`, `generate`, or `void` is WRITE.
- **`onNoticeLease` is the one method the prefix rule misses.** It does not start with a write verb, but it puts a lease on notice with a move-out date and reason. It is a WRITE and is marked as one here.
- `searchCustomers` reads despite the unusual verb. `getResponse` (queue) also reads, it just fetches a previously queued payload.
- `applyQuote` and `generateQuotes` are marked WRITE by the prefix rule and genuinely are: they attach a priced quote to a live application.

### Where the spec was thin

- **17 methods** ship only the placeholder description `"Method parameters"` (13 of the `leases` group, plus `sendPurchaseOrders`, `updateInvoices`) or no description at all (`sendVendors`, `updateVendors`). Their required params are still explicit in the spec and are accurate here. Only the prose is inferred, and those rows carry a `*`.
- `getInvoices` r2 has no description but r1 does, so the r1 text is used. No other method has descriptions that go missing between versions.
- `updateLeads` r1 and r2 have no `version` enum in their request schema. The version is taken from the schema name and confirmed by the request examples, which send `"version": "r1"` and `"version": "r2"`.
- **Param casing is not consistent and it is not a typo here.** `updateLeads` r1 uses PascalCase (`PropertyId`, `ApplicationId`, `Prospects`) while r2 uses camelCase (`propertyId`, `prospects`). `sendInvoices` is `ApBatch` in r1 and `apBatch` in r2. `sendMitsLeads` mixes both in one call (`Prospects` capitalized, `propertyId` not). `sendRoommateGroups` r1 wants `propertyId` and r2 does not. Copy the case exactly as written in the required-params column.
- `getStatus`, `getAccessibleClients`, `getAccessibleServices`, and `getPricingPicklists` define no `params` object at all. Send `"params": {}`.
- `getAccessibleClients` is called with `rsync` as the orgs value in the URL, not `libertyassetgroup`. The spec calls this out explicitly.

