# API Report Card: Rentvine Open API

## Run metadata
- Methodology version: 1.1
- Evaluating model: Claude Opus 5 (claude-opus-5)
- Date run: 2026-09-02
- Provisional evidence-packet version or ID: RV-2026-09-02-p1
- Final evidence-packet version or ID: RV-2026-09-02-final (frozen before scoring)
- Evidence-discovery mode: tool-enabled discovery
- Evidence tier: **Baseline verified**
- Live-write method and safety: controlled live — one operator-provisioned inert fixture in the live `[account]` account (maintenance-materials catalog entry, sentinel name `APITEST-DELETE-2026-09-02`); operator authorization recorded 2026-09-02; create, read-back, update, and delete performed and cleanup verified (record soft-deleted `isDeleted: 1`, absent from all listings, materials total returned to its pre-test value of 0). No money-moving, notifying, bulk, or irreversible operation ran against any real record.
- Minimum live-test battery: Steps 1–6 complete. Step 7 (idempotency) **N-A** — the API documents no idempotency mechanism (`idempoten*` occurs zero times in the published specification). Step 8 (webhooks) **not completed** — Rentvine webhooks are created only through the account UI, no webhook-registration endpoint exists in the API, and no operator-controlled receiver was authorized.
- Live tests performed: authentication (valid, invalid, and absent credentials); core-resource read and multi-page traversal; page-order stability re-request; incremental `dateTimeModifiedMin` filtering; `isActive` and `search` filtering; the four bulk export endpoints; deliberate error triggering (unknown ID, unknown path, malformed query parameter, POST with missing required fields, rejected field value); full response-header survey; cross-endpoint and cross-operation type comparison; create, read-back, update, duplicate-retry, and delete on an inert fixture with verified cleanup; undocumented-endpoint existence probe for bank accounts. 57 observations in total, all captured verbatim.
- Live tests not possible: webhook registration and delivery observation (no API surface, no authorized receiver); rate-limit behaviour (not deliberately triggered — doing so would risk disrupting a production account).
- Documentation-graded checks (baseline verified): **C1.2** (the critical ledger-charge, ledger-payment, and lease create/update writes — excluded from live testing by the protocol's money-movement prohibition; the inventory write path within C1.2 *was* live-verified), **C1.3** (lifecycle actions other than delete, which was live-verified), **C2.4** (duplicate prevention on financially consequential writes), **C2.8** (webhook signing, retry, and replay behaviour).
- Independent grading runs: **three**, all against the same final frozen packet (see "Three-run reconciliation"). Runs 1 and 2 published 70/C−; run 3 published 69/D+. Three check-level disagreements were resolved against the frozen evidence, not averaged. The reconciled result is **69/100, D+**.

## Final evidence packet manifest
- https://docs.rentvine.com/ — "Rentvine API Docs", public and login-free. Redoc rendering with a complete **OpenAPI 3.1.0** specification embedded in page state (`__redoc_state.spec.data`): **143 paths, 205 operations** (109 GET, 78 POST, 18 DELETE; no PUT, no PATCH). `hideDownloadButton: false`, so the specification is downloadable by any visitor. Page is 7,397,081 bytes. Accessed 2026-09-02.
- https://www.rentvine.com/open-api — "Open API, Rentvine's RESTful API"; links to docs.rentvine.com; contains no pricing, rate-limit, webhook, sandbox, or SDK detail.
- https://www.rentvine.com/pricing — single plan; "All features included"; "as low as $1.50 per unit"; "Fully Open API & Integrations".
- https://www.rentvine.com/features/mcp — first-party MCP server; "Not an add-on. Included for every Rentvine customer as part of your plan."; "90+ governed tools"; "Read-only by design."; "The MCP is in beta now and going live later this year."; "Every connection runs under your Rentvine roles and permissions."
- https://www.rentvine.com/terms — Terms of Service; uptime/SLA disclaimer and API-modification reservation (quoted under C2.10 and C2.12).
- https://www.rentvine.com/release-notes — 57 entries; ten most recent reviewed.
- https://www.rentvine.com/llms.txt — HTTP 200, 8,675 bytes, "_Last updated: 2026-06-10_"; product/marketing corpus.
- https://www.rentvine.com/llms-full.txt — **HTTP 404** (does not exist).
- https://docs.rentvine.com/llms.txt, /llms-full.txt, /openapi.json, /openapi.yaml, /spec.json, /sitemap.xml — **all HTTP 403**; only the documentation index page is publicly served from that host.
- https://www.rentvine.com/sitemap.xml — 60,015 bytes; contains `/open-api`, `/features/mcp`, `/integrations`; contains **no** status, uptime, SLA, trust, changelog, or developer-portal URL.
- https://help.rentvine.com/en/articles/16575275-tip-of-the-week-30-guide-to-rentvines-open-api — API key creation, role binding, secret regeneration, key deletion, pod association. Updated 2026-08-26.
- https://help.rentvine.com/en/articles/16574157-user-roles — role permission categories and per-action toggles. Updated 2026-08-31.
- https://help.rentvine.com/en/articles/16574284-how-to-add-webhooks — webhook creation, Post URL, signing key and key reset. Updated 2026-08-26.
- https://help.rentvine.com/en/articles/16603326-integration-with-aptly — webhook event enumeration: "specific events (Create or Update) for Properties, Units, Leases, and Work Orders". Updated 2026-08-26.
- https://help.rentvine.com/en/articles/16573975-how-do-i-integrate-my-listings-with-tenant-turner — multiple named API keys. Updated 2026-09-01.
- https://status.rentvine.com/ — **rendered in a real browser** 2026-09-02 (a plain fetch returned only a client-rendered shell); returns "Authorization Failure — You do not have access to this portal", i.e. an application portal, not a status page.
- https://api.rentvine.com/v1/... — HTTP 404 `{"code":"404","error":"Not Found",...}`; not the API host. The documented host is the customer's own account subdomain.
- Live API observations, https://[account].rentvine.com/api/manager — [operator account] production account, HTTP Basic, 2026-09-02 19:57–20:10 UTC; 57 requests with full request/response bodies and headers captured.

Third-party materials located during discovery (a Ruby gem wrapper published by "Launch-Engine"; a Supergood API listing) were **excluded** as non-first-party. No official Rentvine SDK is evidenced in any first-party source.

## Evidence-amendment log
- **C1.4, C2.8** — Provisionally `no` and `N-A` respectively: the published specification contains zero occurrences of "webhook" and no `webhooks` object. The controlled verification pass located first-party help-centre documentation establishing that Rentvine webhooks exist, are signed, and cover four object types. Both marks raised (C1.4 → `partial`; C2.8 → `partial`). Sources added: help articles 16574284, 16603326.
- **C1.1** — Provisionally at risk of `no`: "bank accounts" is a critical object in the fixed classification and no bank-account path appears in the specification. A live probe found `GET /accounting/bank-accounts` returns HTTP 200 with two trust-account records. Capability credited in C1.1; the documentation gap penalized in C4.1. Source added: live observation.
- **C4.2** — Provisionally `partial` on the specification alone. A first-party MCP server was discovered via `www.rentvine.com/sitemap.xml`. Mark remained `partial` (beta status, read-only design). Source added: www.rentvine.com/features/mcp.
- **C2.12** — `status.rentvine.com` returned HTTP 200 to a plain fetch but served only a client-rendered shell. Per methodology rule 9 the page was rendered in a real browser before being treated as absent; it proved to be an application portal. No mark was assigned on the basis of an unreadable page.
- **C3.1, C3.2, C3.4** — Help-centre URLs returned by search were stale (HTTP 404). Current `/en/articles/` URLs were located through the first-party help-centre search rather than settling the dependent checks as unverified.
- **C1.3 (correction during reconciliation)** — The provisional packet asserted that "no void/reverse/refund/cancel operation exists." Independent run 3 challenged this and was correct: `DELETE /accounting/{billID}` is summarised **"Void Bill"** and `DELETE /accounting/deposits/{depositID}` is **"Void Deposit"**. The claim was corrected to its precise form — no void or reverse exists for a posted **lease-ledger transaction** (charge or payment). The mark is unchanged (`no`, on which all three runs agreed) and the finding is now stronger: Rentvine plainly has the void concept and exposes it for bills and deposits but not for the ledger entries the API can create.
- **C2.1, C2.7 (corrections during reconciliation)** — Independent run 3 surfaced two verified facts that runs 1 and 2 had not weighed: the bills resource sits at the malformed path `/accounting/{billID}`, and work orders, bills, deposits, invoices and inspections have **neither** an export path nor an updated-since filter. Both marks were lowered from `yes` to `partial` on that evidence.
- **C2.3 (correction during reconciliation)** — Run 1 marked this `no`; runs 2 and 3 independently marked `partial`. Resolved to `partial` on the written definitions (see "Three-run reconciliation").
- **Factual corrections to the packet summary, none affecting a mark** — `info.description` is **absent**, not empty-length. **6** of 20 tags carry descriptions (Authentication, Object Types, and four Resident Experience tags), not 2; the core tags (Properties, Units, Screening, Custom Fields, all four Export tags) remain empty. Invalid JSON-Schema `type` strings number **3 distinct across 5 occurrences** (`date-time`×2, `date`×2, `search`×1); a sixth apparent hit, `securitySchemes.basicAuth.type: "http"`, is valid OpenAPI and was a false positive. Additional defects found during reconciliation and verified: **324** `type` arrays contain a literal JSON `null` instead of the string `"null"`; **4** `$ref`s point to unpublished external YAML files; and the documentation's own "Related Endpoints" sections cite **26 distinct endpoints that do not exist**.
- **Credential note (no score effect)** — The first credential pair tried was rejected (HTTP 401); a second first-party pair for the same account authenticated successfully. This is an artifact of the operator's local configuration, not a property of the API.

## API eligibility
- Qualifying API: **yes**
- API operator: Rentvine — the interface is served from the customer's own Rentvine account subdomain and documented on Rentvine's own domain [docs.rentvine.com, `servers`: `https://{account}.rentvine.com/api/manager`].
- Access or credential issuer: Rentvine, self-serve inside the product [help.rentvine.com 16575275: "Generate API keys directly inside Rentvine" via "Global Settings under User Roles and API"].
- Eligibility basis: A public OpenAPI 3.1.0 specification documents 205 operations across Rentvine's own property, unit, lease, tenant, accounting, maintenance, and screening functions; credentials are issued by Rentvine to its own customers; and all of the above was exercised live against a production Rentvine account on 2026-09-02. The interface exposes the evaluated vendor's own product functions, not a third party's.

## Context
- Software category: **Accounting/PMS**
- What the API is for and its core objects and workflows: The Rentvine Open API is the programmatic interface to a property manager's own Rentvine account, intended for integrations, internal automations, and data synchronisation. Its core objects are the portfolio → property → unit → lease → tenant hierarchy plus the trust-accounting layer (ledgers, chart of accounts, transactions, bills, deposits, bank accounts) and the operational layer (work orders, inspections, vendors, screening applications). Its central workflows are reading those records, posting charges and payments to a lease ledger, creating and updating leases, and driving maintenance and screening status transitions.

## Provider and property-management fit
- What this product is: Cloud property management software for professional property managers, built around trust accounting [www.rentvine.com/llms.txt: "Cloud-based property management software for professional property managers, with trust-accounting-first design across accounting, leasing, maintenance, and reporting."].
- Bank status, when relevant: **not a bank**. No first-party evidence identifies Rentvine as a bank or as a provider of regulated banking services.
- Who provides any bank account or regulated banking service: **a named provider — the property manager's own financial institution**. Rentvine does not hold the funds. In the evaluated account the bank records name an external institution (`GET /accounting/bank-accounts`, 2026-09-02: `"name": "[trust account name withheld]", "bankName": "Enterprise Bank & Trust"`). The Terms of Service reference Plaid for bank connectivity. Rentvine's own materials make no claim to provide the deposit account.
- What the customer actually receives: A software subscription that records, reconciles, and reports on money held in bank accounts the property manager opens and controls in its own name — a ledger and reconciliation system, not a deposit account.
- Property-management fit: **PM-specialized** — property management is the product's entire purpose and the API's object model is the property-management domain model [www.rentvine.com/pricing; llms.txt].
- Documented PM-specific workflows: trust accounting and three-way reconciliation; lease lifecycle including move-in/move-out and status transitions [`POST /leases/{leaseID}/status`]; lease ledger charges and payments [`POST /accounting/leases/{leaseID}/charges`, `/payments`]; owner statements and distributions [`/portfolios/statements/*`, `/portfolios/{portfolioID}/owners/{portfolioOwnerID}/ach-details`]; maintenance work orders with vendor and technician assignment; inspections; applicant screening and decisions [`POST /screening/applications/{applicationID}/status`]; resident benefit packages.
- Trust or fiduciary workflow support, when relevant: **documented**. Not generic accounting functionality — the API exposes escrow flags on bank accounts and chart-of-accounts entries (`isEscrow`), dedicated trust-integrity diagnostics (`GET /accounting/diagnostics/escrow-mismatch`, `/manager-ledger-balance`, `/negative-bank-accounts`, `/bank-account-reconciliation-lapse`, `/prepayment-mismatch`, `/reserve-not-met`), and reconciliation operations (`POST /accounting/deposits/{depositID}/reconcile` and `/unreconcile`). Live-verified: `/accounting/accounts` returned 92 chart-of-accounts entries carrying `isEscrow`, `isDeposit`, and `depositTypeID` flags.
- Operational role and dependencies: Rentvine is the system of record for the portfolio and its trust ledger. A property manager still needs a bank for the accounts themselves, a payment processor for rent collection, and — because the API cannot void a posted lease-ledger transaction or post a journal entry — continued use of the Rentvine web application for accounting corrections.

## Coverage classification (fixed before inspection)

Default Accounting/PMS classification, adopted without deviation and recorded before the API surface was inspected. Lifecycle items inherit the class and weight of the object they belong to.

| Object or workflow | Class | Weight | Present / read-only / absent |
|---|---|---|---|
| Properties | critical | 3 | Present (create, update, delete, activate/deactivate) |
| Units | critical | 3 | Present (create, update, delete, activate/deactivate) |
| Leases | critical | 3 | Present (create, update, delete, status change) |
| Tenants | critical | 3 | Present (create, update, delete, activate/deactivate) |
| Lease ledgers / transactions | critical | 3 | Present (read; create via charges and payments; **no void or reverse**) |
| General ledger | critical | 3 | **Materially read-only** (no journal-entry posting, no chart-of-accounts writes) |
| Bank accounts | critical | 3 | Present, read-only — **undocumented endpoint** |
| Owners | important | 2 | Present (create, update, delete, activate/deactivate) |
| Bills | important | 2 | Present (create, update, approve, void) |
| Payments | important | 2 | Present (create) |
| Applicants | important | 2 | Read, screening-report request, decision status; **no application create** |
| Work orders / tasks | important | 2 | Present (create, update, delete, status transitions) |
| Reconciliation | important | 2 | Deposit-level reconcile/unreconcile only |
| Files | optional | 1 | Upload only; no list or delete |
| Communications | optional | 1 | Present (email conversations, chat, SMS send) |
| Custom fields | optional | 1 | Present (read and write values) |
| Associations | optional | 1 | Present (create, update, delete, activate/deactivate) |
| Inventory (materials, labor rates) | optional | 1 | Present — **create/update/delete live-verified** |
| *Workflow:* read core records | critical | 3 | Present — live-verified |
| *Workflow:* post ledger charges and payments | critical | 3 | Present (documentation-graded) |
| *Workflow:* create and update leases | critical | 3 | Present (documentation-graded) |

## Functional coverage map
- **Core objects:** All seven critical objects are present. Five are fully operable. General ledger is materially read-only — `/accounting/journal-entries/search` and `/accounting/recurring-journal-entries/search` are GET-only and there is no `POST /accounting/accounts`, so an integration can read the books but cannot post a journal entry or add a GL account. Bank accounts are readable, but only through an endpoint absent from the published specification. Among important objects, applicants cannot be created and reconciliation is limited to deposit-level actions; among optional objects, files can be uploaded but not listed or deleted.
- **Primary operational workflows:** Read core records (live-verified across eleven object types). Post ledger charges and payments — `POST /accounting/leases/{leaseID}/charges`, `/payments`, `/accounting/other-payments` (documentation-graded; excluded from live testing as money-moving). Create and update leases — `POST /leases`, `POST /leases/{leaseID}`, `/tenants`, `/recurring-charges` (documentation-graded). Create, update, and delete an inventory record — live-verified end to end.
- **Principal lifecycle changes:** Present — lease status change and move-out (`POST /leases/{leaseID}/status` with `noticeDate`, `expectedMoveOutDate`, `moveOutDate`, `closedDate`); bill approve and **void** (`POST /accounting/bills/{billID}/approve`; `DELETE /accounting/{billID}` "Void Bill"); deposit **void**, reconcile, unreconcile; work-order status transition; application decision; activate/deactivate across properties, units, portfolios, tenants, owners, vendors, associations, and maintenance technicians; delete across 18 resources (live-verified on materials). Absent — **void or reverse of a posted lease-ledger transaction**. No path or request body exposes it: `isVoided` appears only as a response field on the `transaction`, `transaction_entry`, `transaction_detail`, `bill`, `deposit`, and `reconciliation` schemas and as the read-only query filter `components.parameters.is_voided`, and in **no request body of any of the 78 POST operations**. Also absent — payment refund or return (`payoutReturnID` is read-only), and file and custom-field deletion.

## Category 1: Functional Coverage and Usefulness: 9.4/15
- **C1.1 Object coverage: yes** — weighted coverage **85.5%** (32.5 of 38 weight), no critical object absent. Critical: properties 1.0, units 1.0, leases 1.0, tenants 1.0, lease transactions 1.0, general ledger 0.5, bank accounts 0.5 (present and readable but undocumented and carrying no balance field). Important: owners 1.0, bills 1.0, payments 1.0, applicants 0.5 (no create), work orders 1.0, reconciliation 0.5 (deposit-level only). Optional: files 0.5 (upload only), communications 1.0, custom fields 1.0, associations 1.0, inventory 1.0. [Live 2026-09-02: `/accounting/bank-accounts` → 200 with 2 records; `/accounting/accounts` → 200 with 92; `/accounting/transactions/search` → 200 with `Pagination-Total-Items: 36328`; `/maintenance/work-orders` → 1534; `/tenants` → 363; `/owners` → 156]
- **C1.2 Core operational actions: yes** — weighted coverage **86.8%** (33 of 38 weight), no critical write workflow absent. All three critical workflows present. General ledger writes 0.0 (absent); applicants 0.5; reconciliation 0.5. [docs.rentvine.com `POST /accounting/leases/{leaseID}/charges`, `/payments`, `POST /leases`, `POST /leases/{leaseID}`; live-verified write 2026-09-02: `POST /maintenance/materials` → 200 `{"material":{"materialID":"1",...}}`, then `POST /maintenance/materials/1` → 200 with `description` changed and `dateTimeModified` advanced from `20:07:17` to `20:07:19`] — *ledger and lease writes documentation-graded.*
- **C1.3 Delete or lifecycle actions: no** — weighted coverage 86.2% (25 of 29 weight), **but a critical lifecycle action is absent**, which the check scores as `no` irrespective of the percentage. Eleven of thirteen lifecycle changes are present, including void for bills and deposits — but voiding or reversing a posted lease-ledger charge or payment is not exposed, and neither is payment refund/return. [Verified by exhaustive search: no path or request body exposes transaction void; contrast `DELETE /accounting/{billID}` "Void Bill" and `DELETE /accounting/deposits/{depositID}` "Void Deposit", which establish that the platform has the concept. Live-verified: `DELETE /maintenance/materials/1` → 200, record `isDeleted: 1` and absent from listings.]
- **C1.4 Change notification: partial** — push coverage is **33.3%** (11 of 33 weight), below the 0.50 push floor, so `partial` is earned on the polling branch rather than the push branch. Webhooks fire on Create or Update for four object types only — Properties, Units, Leases, Work Orders — so no event exists for the money-side changes (transactions, charges, payments, bills, deposits, statements) or for screening applications. Incremental polling is genuinely efficient and covers the critical changes: `dateTimeModifiedMin`/`Max` are offered on 17 operations including `/accounting/transactions/search`, `/accounting/transactions/entries/search`, and `/accounting/journal-entries/search`. [help.rentvine.com 16603326; 16574284; `components.parameters.date_time_modified_min`. Live-verified: `/properties/search` returned 175 unfiltered, 127 with `dateTimeModifiedMin=2026-08-01T00:00:00`, and 0 with `2030-01-01T00:00:00` — the filter is honoured.]

Score math: earned 2.5 of 4 applicable checks; unrounded fraction = 0.625000; category points = 0.625000 × 15 = 9.3750 → **9.4/15**; verification coverage = 4/4 = **100%**

What this means for you: This is the strongest part of Rentvine's API and the reason it is worth building on. Essentially everything your business runs on is reachable — properties, units, leases, tenants, owners, work orders, bills, screening, and the full trust ledger — and most of it can be created and changed, not just read. Three gaps matter. First and most important: **the API can post money to a lease but cannot take it back.** There is no way to void or reverse a charge or payment, even though Rentvine can void a bill or a deposit — so any automation that posts charges needs a human in Rentvine to fix mistakes. Second, you cannot post a journal entry or add a general-ledger account through the API, so pure accounting corrections stay manual. Third, change notifications are lopsided: you get instant alerts when a property, unit, lease, or work order changes, and nothing at all when money moves, so anything financial has to be polled on a schedule.

## Category 2: API Design, Reliability, and Operability: 2.5/10
- **C2.1 Modern API conventions: partial** — Resource-oriented JSON REST over HTTPS, live-verified, and entirely interoperable in practice, but the conventions are mixed. **The exact limitations:** there is no PUT or PATCH anywhere in 205 operations — POST does double duty as update (`POST /leases/{leaseID}` is summarised "Update Lease"); DELETE is semantically overloaded to mean *void* rather than delete for financial objects (`DELETE /accounting/{billID}` = "Void Bill", `DELETE /accounting/deposits/{depositID}` = "Void Deposit"); the bills resource sits at the malformed path `/accounting/{billID}` — a bare account-level path — while bills are created at `/accounting/bills`, so read, update, and void of a bill live outside the collection that creates it; and two declared paths (`/leases/{leaseID}/pets`, `/leases/{leaseID}/pets/{id}`) carry no operations at all because their `$ref`s point to unpublished files.
- **C2.2 Consistent typing: no** — Core fields are stringly typed **and** types vary across endpoints, across operations on the same record, and against the published schema. Live 2026-09-02: identifiers, booleans, money, and coordinates all return as JSON strings — `"propertyID":"69"`, `"portfolioID":"76"`, `"isActive":"1"`, `"isMultiUnit":"0"`, `"leaseID":"117"`, `"rent":"3100.00"`, `"beds":"4"`, `"latitude":"33.84332090"`. The specification contradicts this: `components.schemas.lease.leaseID` and `lease.propertyID` are declared `"type": "integer"` while the live API returns `"117"` and `"180"` as strings, so generated clients mis-parse the core object. The same field is typed differently in different schemas — `propertyID` is `integer` in `lease` but `string` in `unit`. Within a single resource, the same field changes type between operations: `material.isDeleted` returned `"0"` (string) from `POST /maintenance/materials` and `1` (integer) from `DELETE /maintenance/materials/1`. Even the error `code` field varies: integer `401` on one path, string `"404"` on another. Timestamps are not ISO-8601: `"dateTimeCreated":"2025-07-22 16:01:03"` (space separator, no timezone).
- **C2.3 Structured errors: partial** — Failures return a JSON body with a human-readable message and, in the common cases, a correct HTTP status, which an integration can act on. **The exact limitations:** there is **no populated stable machine-readable error code** — the specification defines only `{"error": string}` (three error responses, `error_400/401/403`), and where a `code` field does appear it merely mirrors the HTTP status and its type is inconsistent (integer `401` vs string `"404"`); **error shapes vary across endpoints**, with five distinct shapes observed live — `{"code":401,"error":"Access Denied"}`, `{"code":"404","error":"Not Found","message":"..."}`, `{"error":"Property 99999999 not found"}`, `{"error":"invalid input."}`, and the field-keyed `{"sellPrice":["Sell Price cannot equal to 0.00"]}`; status semantics are wrong in at least one case (**HTTP 400 returned for a not-found** property); and two responses were not parseable at all — the documented endpoint `GET /accounting/ledgers` returned HTTP 400 with the bare JSON string `"Search Failed"`, and `GET /properties?page=notanumber&pageSize=abc` returned **HTTP 500 with a completely empty body**. No 429, 409, or 5xx response is documented on any of the 205 operations. *(Run 1 graded this `no` on the strength of the two unparseable responses; resolved to `partial` — see "Three-run reconciliation".)*
- **C2.4 Duplicate prevention: no** — No idempotency mechanism is documented: `idempoten*` occurs zero times in the specification, and no unique-request-identifier convention exists. Live 2026-09-02, an `Idempotency-Key` request header had no effect on behaviour. The consequential writes — `POST /accounting/leases/{leaseID}/charges`, `/payments`, `/accounting/other-payments`, and the bill and deposit creates — carry no documented duplicate protection, so a retried or double-submitted charge risks posting twice to a real trust ledger with no API-side way to void it (C1.3). The one protection observed was incidental natural uniqueness on a catalog record: a second identical `POST /maintenance/materials` returned `{"name":["A material already exists with this name"]}` — an undocumented name constraint on one optional resource that does not extend to the financial writes this check concerns. *Consequential-write behaviour documentation-graded.*
- **C2.5 Graceful handling under load: no** — No 429 response is documented on any operation, no rate limit is described in any first-party source, and a full header survey of live 200 responses returned no rate-limit, quota, or `Retry-After` header of any kind. No numeric backoff guidance is published. The only throttling language in first-party materials concerns Plaid's own practices, not the Rentvine API. Rate limits were not deliberately exceeded, as doing so would risk disrupting a production account; the mark rests on documented absence, not on an untested limit.
- **C2.6 Pagination for large collections: partial** — Pagination is well built and live-verified. Eight pagination response headers are documented and populated: live 2026-09-02, `GET /properties?page=1&pageSize=5` returned `Pagination-Total-Items: 128`, `Pagination-Total-Pages: 26`, `Pagination-Next-Page: 2`, plus page-size, current-, before-, first-, and last-page. Pages 1 and 2 were fully disjoint and a repeated request for page 1 returned an identical order, so an entire large collection is traversable in practice. **The exact limitations:** ordering is documented on only 11–13 GET operations and is *not* documented for `/properties`, `/leases`, `/tenants`, or `/accounting/transactions/search` (36,328 rows), so a consumer of the core collections has an observed but unguaranteed ordering, with the attendant risk of skipped or duplicated rows during concurrent writes; the page-size cap is stated only as "Maximum page size is enforced server-side" with no number; and `components.parameters.page_size_25` declares `default: 25` while the `GET /properties` description that uses it says "Default page size is 15."
- **C2.7 Bulk or incremental export: partial** — Dedicated export endpoints exist and work, but coverage is incomplete. `GET /leases/export`, `/properties/export`, `/properties/units/export`, and `/screening/applications/export` all accept `dateTimeModifiedMin`/`Max` plus pagination, and were live-verified (190, 175, and 175 total items respectively); incremental sync is additionally available on 13 further `/search` endpoints including the transaction and journal-entry searches. **The exact limitation:** export covers only some resources. **Work orders (1,534 rows in the evaluated account), bills, deposits, invoices, and inspections have neither an export path nor an updated-since filter** — verified against every GET operation — so those datasets can only be kept in sync by re-paging the entire collection on every run. *(Runs 1 and 2 graded this `yes`; resolved to `partial` — see "Three-run reconciliation".)*
- **C2.8 Webhook security and delivery reliability: partial** — Payload verification is present; delivery reliability is not documented. Rentvine issues a signing key: "This key is used to sign all HTTP payloads that we send to your webhook receivers. This is used to confirm that the data is being sent from Rentvine", and the key can be reset, which "will invalidate the old key". **The exact limitations:** no retry policy, delivery-failure behaviour, replay guidance, or consumer-side idempotency guidance is documented anywhere in first-party materials, and no payload format or signature-verification algorithm is published — so a consumer cannot implement verification from the documentation alone or know whether a missed delivery will be retried. [help.rentvine.com 16574284] *Documentation-graded — battery step 8 not run: webhooks are UI-created with no registration endpoint, and no operator-controlled receiver was authorized.*
- **C2.9 Concurrency and conflict control: no** — Neither optimistic concurrency nor documented conflict semantics exist. No `ETag`, `If-Match`, or version field appears anywhere in the specification, and none was present in the live response headers surveyed. No operation documents a 409 — the only documented status codes across all 205 operations are 200, 400, 401, 403, and 404. No concurrency limit or behaviour is described. Updates are partial-body POSTs that merge silently with no precondition mechanism (live-verified: `POST /maintenance/materials/1` sent only `description` and the other fields were silently preserved), so two integrations updating the same lease will overwrite one another undetectably. The `token` field returned on list rows is documented as "a server-generated `token` (Unix timestamp) used as a cache-busting key", not as a concurrency control, and no operation accepts it.
- **C2.10 Versioning and backward compatibility: no** — There is no version contract at all. The base path `https://{account}.rentvine.com/api/manager` contains no version segment, no version header was present on any live response, the specification's `info.version` is `"1.0.0"` but is not expressed in any request, and no deprecation policy, breaking-change definition, or deprecation window is published — `deprecat*` occurs zero times. First-party terms take the opposite position explicitly: "Rentvine reserves the right to modify, enhance, suspend, or discontinue any API or related integration functionality at any time, with or without notice, and shall have no liability to Client or any third party for any resulting impact." [www.rentvine.com/terms]
- **C2.11 Request traceability: partial** — A unique per-request identifier is present on essentially every response, but it is the CDN's rather than Rentvine's, and it is undocumented. Live 2026-09-02, responses carried `X-Amz-Cf-Id` (for example `zj7Aco2GwHgSh6oP4Vf67rYYSrnJzVYHZ0nttyoFWElQBN8CnDVRFw==`) and `X-Amz-Cf-Pop`. **The exact limitations:** no Rentvine-issued request or correlation identifier exists (`x-request`, `request-id`, and `correlation` occur zero times in the specification), `X-Amz-Cf-Id` is an Amazon CloudFront artifact that Rentvine does not document, and no first-party material establishes that it can be quoted to Rentvine support to trace a request. Notably the identifier is absent from exactly the case where it is most needed: the HTTP 500 empty-body response recorded under C2.3.
- **C2.12 Service availability and status transparency: no** — There is no public availability signal. `https://status.rentvine.com` resolves but is an application portal, not a status page: rendered in a browser 2026-09-02 it returned "Authorization Failure — You do not have access to this portal", with links to the owner, resident, vendor, and applicant portals. No status, uptime, incident-history, or trust page appears in `www.rentvine.com/sitemap.xml`. First-party terms disclaim the underlying commitment: "Rentvine does not guarantee any specific uptime or service level unless expressly set forth in a separate written service level agreement executed by the parties", and service interruptions "do not constitute a breach of this Agreement." No incident history and no uptime figures are published in any form.

Score math: earned 3.0 of 12 applicable checks (yes: none; partial: C2.1, C2.3, C2.6, C2.7, C2.8, C2.11 = 3.0; no: C2.2, C2.4, C2.5, C2.9, C2.10, C2.12 = 0); no N-A and no unverified checks; unrounded fraction = 0.250000; category points = 0.250000 × 10 = 2.5000 → **2.5/10**; verification coverage = 12/12 = **100%**

What this means for you: This is where Rentvine's API is weakest, and it is the part that decides how much maintenance your automations need. The good news is real: paging through big lists works properly and tells you how many records there are, and four export endpoints let you pull leases, properties, units, and applications and then fetch only what changed since last time. The problems are the unglamorous kind that cause 2 a.m. failures. Every number and yes/no value arrives as text — `"1"` rather than `1` — and Rentvine's own published blueprint says some of these are numbers when they are not, so code generated from it mis-reads your core records. Failures come back in five different formats, one is a bare sentence, one malformed request returned a blank server error, and a missing property returns the wrong kind of error, so your code cannot reliably tell *why* something failed. There is no published rate limit, so you cannot know how hard is too hard until something breaks. Nothing stops a retried charge from posting twice, and nothing stops two of your tools from silently overwriting each other's edits to the same lease. Work orders, bills, and deposits have no "what changed since yesterday" filter, so syncing them means re-downloading everything every time. There is no version number, and the contract explicitly lets Rentvine change or switch off the API without telling you. And there is no status page, so when something looks broken you cannot tell whether it is you or them.

## Category 3: Access Control and Safe Automation: 5.0/5
- **C3.1 Read-only credentials: yes** — An API key inherits a role, and role permissions separate view from edit, so a non-writing integration identity can be issued. The role documentation is explicit that disabling a modify toggle preserves read access: "If this toggle is off, they will still be able to view all of the deposits they will not be able to edit them." The specification reinforces this by naming a required write permission on each mutating operation. [help.rentvine.com 16574157; 16575275: "If you want to limit access to certain data, you can assign a restricted role."]
- **C3.2 Scoped credentials: yes** — Scoping is fine-grained at the action level, not all-or-nothing. Roles span some fifteen permission categories (Administration, Accounting, Leasing, Properties, Contacts, Accounting Reports, Maintenance, Portfolios, Screening, Notifications, Portfolio Groups, Rentsign, System and others) with distinct action-level permission types including **Manage**, **Modify**, **Void**, **Post/Charge**, and **Print**, plus a specific "Manage Webhooks" permission. The specification names the exact permission each operation requires (for example `POST /accounting/leases/{leaseID}/charges` — "Requires the **Add Charge** permission"; `/accounting/bills/{billID}/approve` — "Requires **ApproveBill**"), and portfolio-level restriction is enforced on top ("Results are automatically restricted to the portfolios the authenticated account has access to"). Keys can further be associated "with a pod if your account uses pods", scoping a credential to a subset of portfolios. [help.rentvine.com 16574157, 16575275; operation descriptions]
- **C3.3 Multiple keys: yes** — Multiple named keys coexist, each with its own role: "Click the API tab > New API Key … If you have created other Api keys before, you will see them listed on this page"; keys are created with a reference name (for example "Create New API Key with name 'tt-integration' and Role"). [help.rentvine.com 16573975; docs.rentvine.com "Obtaining API Keys"]
- **C3.4 Rotation and revocation: yes** — Both are self-serve in the product, with no support ticket: "You can update the key name, change the assigned role, regenerate the secret, associate it with a pod if your account uses pods, or delete the key entirely." The secret is shown once at creation ("You will not be able to view the Secret again after closing this form"). [help.rentvine.com 16575275; docs.rentvine.com Authentication tag]
- **C3.5 Test and production isolation: N-A** — No sandbox or separate test environment is evidenced in any first-party source: the specification defines a single `servers` entry parameterised only by the customer's own account subdomain, and no first-party material references a test, sandbox, staging, or demo environment. With no test environment to isolate, the check does not apply and is excluded from the math. The consequence is captured where it belongs — under the evidence tier, which required the controlled live-data protocol for this run.

Score math: earned 4 of 4 applicable checks; 1 check N-A and excluded; unrounded fraction = 1.000000; category points = 1.000000 × 5 = 5.0000 → **5.0/5**; verification coverage = 4/4 = **100%**

What this means for you: This is Rentvine's best category and it is genuinely good news for anyone pointing an AI agent at their data. You can create a separate key for every tool you connect, give each one only the permissions it actually needs — including view-only — and restrict it to part of your portfolio. The permissions are specific enough that Rentvine's own documentation names which one each operation needs, right down to "Add Charge." If a vendor relationship ends or a key leaks, you can regenerate the secret or delete the key yourself in seconds without calling support. That is exactly the control you want before letting outside software or an AI assistant touch tenant and owner records. The one real absence is a practice environment: there is no sandbox, so any testing happens in your live account — which is why the write testing in this evaluation was confined to a single throwaway record that was created and then deleted.

## Category 4: Documentation and AI-Agent Readiness: 2.5/5
- **C4.1 Complete self-serve reference: partial** — The reference is public, requires no login, and is unusually rich per endpoint, but it is materially incomplete and in places contradicts the API it documents. Strengths: a complete OpenAPI 3.1.0 document covering 205 operations across 143 paths, with authentication instructions and a worked `curl` example, per-endpoint summaries, "Use Cases", "Business Rules", "Available Includes", "Related Endpoints", generated `curl` samples, named permission requirements, and response examples on the large majority of operations. **The exact limitations:** (1) it omits working endpoints — `GET /accounting/bank-accounts` returned 200 with real trust-account data but appears nowhere in the specification, and bank accounts are a critical object; (2) it omits webhooks entirely, which are documented only in the customer help centre, so a developer reading the API reference would conclude Rentvine has no events; (3) its own "Related Endpoints" sections cite **26 distinct endpoints that do not exist**, including `GET /bills/{billID}` (cited 7 times), `POST /bills` (5), `DELETE /bills/{billID}` (4), `PUT /bills/{billID}` (3), and `GET /accounting/ledgers/{ledgerID}` (2); (4) two declared paths carry no operations because their `$ref`s point to unpublished files; (5) there is no overview material on errors, rate limits, versioning, or pagination semantics — `info.description` is absent and only 6 of 20 tags carry any prose, with the core tags (Properties, Units, Screening, Custom Fields, all four Export tags) empty; and (6) documented behaviour is contradicted live — `GET /accounting/ledgers` is documented as "supplying neither returns an empty result set" but returned HTTP 400 `"Search Failed"`, `page_size_25` declares default 25 while its own description says 15, and declared field types contradict the live payloads as detailed in C2.2.
- **C4.2 Reliable machine-consumable integration path: partial** — Two first-party mechanisms exist; neither is complete and maintained to the standard this check requires. The OpenAPI 3.1.0 specification is the strongest available path — it is published, downloadable from the docs page, and covers all 205 operations — but it requires substantial manual correction before code generation: **324** `type` arrays contain a literal JSON `null` instead of the string `"null"` (invalid JSON Schema, including inside the `POST /accounting/leases/{leaseID}/payments` request body on `bankAccountID` and `prepaymentAccountID`); three distinct invalid `type` strings appear across five occurrences (`date-time`, `date`, `search`) on the incremental-sync and search parameters; seven `array` schemas declare no `items`; four `$ref`s dangle to unpublished external YAML files; some properties declare no type at all; and declared integer types contradict live string responses across the core object model. It is also served only inside a 7.4 MB Redoc HTML page — `docs.rentvine.com/openapi.json` returns 403 — so there is no stable machine-fetchable URL. Rentvine additionally ships a first-party MCP server with "90+ governed tools" spanning "Portfolios Properties Units Leases Residents Owners Vendors Work Orders Inspections", included for every customer and running "under your Rentvine roles and permissions" — but it is not generally available ("The MCP is in beta now and going live later this year") and is "Read-only by design", so it is not an operations-capable path to the write operations that make this API useful. No official SDK is evidenced in any first-party source.
- **C4.3 AI-readable documentation: partial** — A first-party AI-oriented resource exists but does not represent the API. `www.rentvine.com/llms.txt` is present, well-formed, and current ("_Last updated: 2026-06-10_", 8,675 bytes), but it is a product and marketing corpus — about, value proposition, audience, capabilities, core pages, FAQ — whose entire API content is three bullet lines, one link, and one FAQ pair, with no endpoint, parameter, schema, authentication, or error information. `llms-full.txt` returns HTTP 404. The documentation host serves no AI-oriented resource at all: `docs.rentvine.com/llms.txt`, `/llms-full.txt`, `/openapi.json`, `/openapi.yaml`, and `/sitemap.xml` all return HTTP 403, and there is no per-endpoint Markdown or downloadable documentation corpus. The API's only machine-retrievable representation is the OpenAPI JSON embedded in the single 7.4 MB HTML bundle — comprehensive in coverage, but carrying the schema defects recorded in C4.2 and requiring extraction from page state rather than retrieval as documentation.
- **C4.4 Kept current: partial** — Currency information exists and the underlying materials are actively maintained, but there is no reliable signal for *API* changes specifically. Rentvine publishes 57 release-note entries, and the API-relevant help-centre articles are demonstrably fresh (the Open API guide and webhooks article updated 2026-08-26; User Roles 2026-08-31; an integration article 2026-09-01). Webhooks were announced through a dated release note in November 2024, establishing that developer-facing changes do sometimes appear there. **The exact limitations:** none of the ten most recent release notes mentions the API, endpoints, or developer-facing changes; the release-note index shows no dates; there is no API changelog, no specification version history, and no deprecation notices; the specification contains no `deprecated` markers; and the terms clause permitting API changes "at any time, with or without notice" (C2.10) removes any commitment to notify at all.

Score math: earned 2.0 of 4 applicable checks (four partials at 0.5); unrounded fraction = 0.500000; category points = 0.500000 × 5 = 2.5000 → **2.5/5**; verification coverage = 4/4 = **100%**

What this means for you: The documentation is better than most property management software offers and it is completely public — no sales call, no login, no NDA, and each endpoint explains what it is for, when to use it, and which permission it needs. That is a real advantage. But it is not something you can hand to an AI coding tool and trust blindly. Parts of the API are missing from it entirely: bank accounts work but are undocumented, and webhooks — a genuinely useful feature — are described only in the customer help articles. Some of what it does say is wrong: it points developers at 26 endpoints that do not exist, declares certain fields as numbers when the API returns text, and documents one endpoint as returning nothing when it actually returns an error. Rentvine's own AI connector is promising and included in your plan, but it is still in beta and read-only, so it cannot do write work. The practical upshot: expect a developer or AI assistant to get roughly 80% of the way from the docs and to discover the rest by testing against your live account.

## Category 5: Accessibility and Cost: 15.0/15
- **C5.1 Self-serve API key: yes** — An entitled operator creates credentials unaided, in the product, with no sales call, support ticket, or approval step. The documented sequence is Settings → Users, Roles and API → API tab → New API Key → name and role → copy the access key and secret. [docs.rentvine.com "Obtaining API Keys"; help.rentvine.com 16575275: "Generate API keys directly inside Rentvine"; independently corroborated by integration guides instructing customers to self-issue keys. Live-verified 2026-09-02: a self-issued key authenticated successfully against the production account, and a bogus credential was correctly rejected with HTTP 401.]
- **C5.3 Not commercially gated: yes** — API access is included, not tiered or sold as an add-on. Rentvine sells a single plan — "Universal pricing. One simple plan." — at "as low as $1.50 per unit" with "All features included", listing "Fully Open API & Integrations" among them and stating "Other platforms charge extra for core functionality … Rentvine keeps it simple: one plan, every feature, full support." The MCP server is likewise "Not an add-on. Included for every Rentvine customer as part of your plan." No premium tier, add-on fee, integration fee, or per-call charge for API access is evidenced in any first-party source. [www.rentvine.com/pricing; /open-api; /features/mcp]

Score math: earned 2 of 2 applicable checks; unrounded fraction = 1.000000; category points = 1.000000 × 15 = 15.0000 → **15.0/15**; verification coverage = 2/2 = **100%**

What this means for you: Full marks, and this is the check that most property management vendors fail. You are already paying for the API — it is in the one plan, at no extra cost, with no premium tier to unlock and no integration fee. You can issue your own key today, in about two minutes, without asking anyone's permission or talking to a salesperson. For an operator who wants to build their own tools, being able to get in the door immediately and at no marginal cost is worth a great deal, and it is the single strongest argument for building on Rentvine despite the reliability gaps in Category 2.

## Three-run reconciliation

Three independent grading runs were performed against the identical final frozen packet. Runs 2 and 3 were conducted by separate evaluators with no access to any other run's marks, no web access, and no live API access — they graded only the frozen packet, as the methodology requires of independent runs.

| | Run 1 | Run 2 | Run 3 | **Reconciled** |
|---|---|---|---|---|
| Category 1 /15 | 9.3750 | 9.3750 | 9.3750 | **9.3750** |
| Category 2 /10 | 2.9167 | 3.3333 | 2.5000 | **2.5000** |
| Category 3 /5 | 5.0000 | 5.0000 | 5.0000 | **5.0000** |
| Category 4 /5 | 2.5000 | 2.5000 | 2.5000 | **2.5000** |
| Category 5 /15 | 15.0000 | 15.0000 | 15.0000 | **15.0000** |
| Raw /50 | 34.7917 | 35.2083 | 34.3750 | **34.3750** |
| Normalized | 69.5833 | 70.4167 | 68.7500 | **68.7500** |
| Published | 70 | 70 | 69 | **69** |
| Grade | C− | C− | D+ | **D+** |

**The three runs agreed on 24 of 27 checks**, including every check in Categories 1, 3, 4, and 5. All three independently reached `yes` on C1.1 and C1.2, `no` on C1.3, `partial` on C1.4, `no` on C2.2/C2.4/C2.5/C2.9/C2.10/C2.12, `partial` on C2.6/C2.8/C2.11, `yes` on all four applicable Category 3 checks, `N-A` on C3.5, `partial` on all four Category 4 checks, and `yes` on both Category 5 checks.

The three disagreements, all in Category 2, were resolved against the frozen evidence rather than averaged:

1. **C2.1 Modern API conventions — runs 1 and 2 `yes`, run 3 `partial`. Resolved: `partial`.** Run 3 identified a fact the other two had not weighed and which was verified during reconciliation: the bills resource sits at the malformed path `/accounting/{billID}` — a bare account-level path — while bills are created at `/accounting/bills`. Combined with the total absence of PUT/PATCH, DELETE being semantically overloaded to mean "void" for financial objects, and two declared paths carrying no operations, this is "REST-like or mixed conventions" under the check's own wording rather than "REST with standard verbs." Runs 1 and 2 had reasoned by analogy to APIs that use POST for updates, which understates the path-level inconsistency.
2. **C2.3 Structured errors — run 1 `no`, runs 2 and 3 `partial`. Resolved: `partial`.** Run 1 graded `no` because two observed failures were genuinely unparseable (a bare JSON string `"Search Failed"` and an HTTP 500 with an empty body). On re-reading the definitions, the `no` band requires "unstructured errors, or success codes that hide failures", and neither squarely characterizes this API: errors are predominantly structured JSON objects with actionable messages, and no success code hides a failure. The `partial` band, by contrast, describes the observations literally — "no populated stable machine code" and "error shapes that vary across endpoints" are both exactly true. Run 1's mark was the stricter outlier and is corrected here.
3. **C2.7 Bulk or incremental export — runs 1 and 2 `yes`, run 3 `partial`. Resolved: `partial`.** Run 3 checked resource-by-resource coverage rather than merely confirming that export endpoints exist. Verified during reconciliation: work orders (1,534 rows), bills, deposits, invoices, and inspections have **neither** an export path nor a `dateTimeModified` filter on any GET operation. The `partial` band's "export covers only some resources" is therefore literally satisfied. Runs 1 and 2 credited the four working export endpoints without testing the completeness of coverage.

In each case the resolution was driven by a verifiable fact in the packet, and in each case the resolution moved the score **down**, against the vendor. The reconciled result is identical to run 3's independent result.

## Total
- Raw: **34.38 / 50** (9.3750 + 2.5000 + 5.0000 + 2.5000 + 15.0000)
- Normalized before rounding: **68.75 / 100**
- Published numeric score: **69 / 100**
- Letter grade: **D+**
- Evidence tier: **Baseline verified** — controlled live; fixtures used, operator authorization recorded, cleanup verified
- Overall verification coverage: **100%** (26 of 26 applicable checks verified; 0 unverified; 1 N-A excluded). Gate satisfied: no category Unable to verify (all five at 100%, well above the 0.70 floor); overall coverage ≥ 80%; minimum battery complete with step 7 N-A and step 8 disclosed as not run.
- Partial-result flag: **yes** — four write-dependent checks were graded from first-party documentation rather than observation (C1.2's ledger and lease writes, C1.3's non-delete lifecycle actions, C2.4's consequential writes, C2.8's webhook delivery). Resolving them would require either a Rentvine sandbox or an operator-authorized webhook receiver plus a test lease on which charges could be posted and reversed. Because C1.3 rests on a demonstrated *absence* in the specification rather than an untested presence, live write testing would be unlikely to change it; C2.8 could plausibly rise to `yes` if retry behaviour proved reliable, which would move the published score to 70 and the grade to C−.
- Unresolved evaluator disagreements: **two remain after reconciliation, both threshold-sensitive and both in Category 1.** (1) **C1.1** scored 85.5% against an 85% bar. Scoring bank accounts 0.0 instead of 0.5 — defensible, since the object is absent from the documented API and the live response carries no balance field — drops coverage to 81.6% and the mark to `partial`, lowering the published score to about 65 (grade D). (2) **C1.2** scored 86.8% against the same bar; downgrading both applicants and reconciliation to 0.0 drops it to 84.2% and the mark to `partial`, with a similar effect. Independently, one evaluator noted that classifying lease-ledger transaction void as *important* rather than *critical* would lift C1.3 from `no` to `yes` and raise the published score to about 76 (grade C); this evaluation holds it critical, because the API posts charges and payments to a live trust ledger, the platform demonstrably has the void concept and exposes it for bills and deposits, and the API does not expose it for ledger entries — which is precisely the failure C1.3 is written to catch. These disagreements are recorded rather than hidden inside an average; every mark and all arithmetic are auditable above.

## Bottom line for a property manager
Rentvine's API is genuinely open in the way that matters most: it is included in the one plan at no extra cost, you can issue your own key in two minutes without a sales call, and the permission controls are excellent — a separate, least-privilege key for every tool or AI agent, revocable in seconds. Its functional reach is real, too: properties, units, leases, tenants, owners, work orders, bills, screening, and the full trust ledger are all reachable, and most of it is changeable. What you can build today is substantial: nightly portfolio syncs, custom dashboards and reporting, renewal and delinquency tracking, maintenance automation, and AI assistants that read your live data. What you cannot build safely today is anything that posts money unattended — the API will post a charge or payment to a lease but offers no way to void or reverse one (even though Rentvine can void a bill or a deposit), no protection against a retried request posting twice, and no journal-entry posting for corrections; that work belongs in the web application with a human. The score is held down not by what the API can do but by the guarantees it does not make: text-typed numbers that contradict the published schema, five error formats including two that cannot be parsed, no published rate limit, no way to stop two tools overwriting each other, no export or change-filter for work orders and bills, no API version contract, and no status page — so integrations need more babysitting than the feature list suggests. Rentvine is a property-management-specialized system of record with documented trust-accounting and fiduciary workflows, and it is not a bank: it accounts for money held in trust accounts you open in your own name at your own institution, so you still need that bank, a payment processor for rent collection, and the Rentvine web application for corrections the API cannot make. A D+ is a grade for API engineering discipline, not a verdict on the product — on openness and cost of entry, where most competitors fail outright, Rentvine scores full marks.
