VRPlatformVRPlatform

Changelog

Current public contract changes and migration links

2026-08-06

  • Reservation list and detail responses now share one materialized issue snapshot and expose issuesComputedAt plus issuesStale. A stale response keeps the prior issue set while a bounded background evaluation runs; clients should re-read until freshness advances and must not recalculate issues.
  • Corrected Airbnb extractor metadata so Payout is the visible ranged capability, Reservation remains hidden but available to supported connections, and disabled Listing, Metric, and Review capabilities remain hidden. GET /apps and GET /apps/{id} return only validated full and cursor capabilities; stored none values are not client actions.
  • Owner statement reads now invalidate when the team's payout_distribution account assignment changes. Selected manual or Ramp bank accounts remain funding accounts only and do not need that assignment; their owner distribution entries continue to use the separately assigned payout account.

2026-08-04

  • GET /reports/trial-balance and /reports/trial-balance/csv now validate every comma-separated classification value at the request boundary. The case-insensitive supported values are asset, liability, revenue, and expense; unsupported values return 400 BAD_REQUEST with a query issue.
  • POST /reservations/{reservationId}/adjustments documentation now states that active bookings require either type or recurringFeeId. A selected accountId alone does not classify the line; canceled bookings remain exempt from this existing rule.

2026-08-01

  • PUT /transactions/{transactionId}/lines/{id} now permits a reconciled deposit line to move between reservation and non-reservation items when the bank match is its only lock. The bank-record link is preserved. Source and destination saved statement periods, books closing, and an attached owner statement still reject the move; locks on unrelated lines do not.
  • GET /teams/lookup can now authenticate an interactive bearer user before a team is selected, without x-team-id. The response remains limited to teams the user can access in the selected regional partition. Use GET /teams?search= for general team-list search.

2026-07-31

  • Breaking: team responses now expose the derived lifecycle state as status; the separate effectiveStatus field was removed. GET /teams and GET /teams/lookup apply the same derived semantics to the status filter, and /partner/billing uses the same contract for its team rows. capabilities.activate reports whether activation can be requested, and PUT /team returns 400 BAD_REQUEST with structured disabled reasons when the team cannot be activated. Deactivation remains available.
  • Flow contact mapping creates and updates now reject unavailable contacts with 400 BAD_REQUEST and context.contactId before persistence. Refresh stale contact selections before retrying.
  • POST /teams now rejects a defaultCurrency absent from the target region's supported currency catalog with 400 BAD_REQUEST and context.defaultCurrency, before creating any team data.
  • The audit events API is marked work in progress: its contract is not yet frozen and can change in ways that are not backward compatible. Read audit events on demand rather than mirroring them into your own store, and contact us if you need a local copy. See Audit Events.
  • Added the generated Audit Catalog: every public audit subject with its field paths, value types, and entity-reference targets, plus the action-code format. The Audit Events guide now leads with reading history directly and documents the 429 rate-limit response.
  • Breaking: statement payment is now per owner. POST /statements/pay requires one selection (contactId, provider, bankAccountId) per ownership member; provider is the sole ACH trigger and provider: null never dispatches, even on a Ramp-backed bank account. For provider: "ramp" the selected bank account's Ramp account connection is the funding account; the former statement-level provider, bankAccountId, fundingAccountId, and selections fields were removed. Results now associate every payout transaction and dispatch syncId with its owner contact and add a recorded status for book-only payments.
  • Breaking: POST /statements/{id}/pay was removed. Pay a single statement through POST /statements/pay with one statement entry; per-statement amount covers additional partial payments and owner receipts.
  • Breaking: POST /statements/pay/preview now accepts the per-owner statements shape and returns authoritative owner allocations after rounding, default bank accounts, ACH readiness, and typed blockers. Omit payouts to receive server-computed defaults.
  • GET /contacts search now matches secondary emails on linked owner users. Contact access and GET /contacts/{id}/viewers responses now include secondaryEmails.
  • Audit-event collection cursors now preserve PostgreSQL's full timestamp precision, preventing duplicate ascending pages and skipped descending rows when a projection batch shares one timestamp. Cursors issued before this repair return 400; restart the walk without the old cursor.
  • Audit-event requests with updatedFrom before the retained-history watermark now return the same 410 and earliestAvailableAt recovery context as an expired cursor.

2026-07-30

  • Breaking pre-consumer change: public audit-event collections now expose typed entity values and accountingImpact.netEffect. The former affected, changedDimensions, postingChanges, and include=postingChanges contracts were removed.
  • GET /audit/events/{id} now returns revision-bound, paginated entryChanges with observed journal-entry identity, typed snapshots, and safe cause attribution. Continue with entryCursor; restart from page one after 409 AUDIT_EVENT_REVISED.
  • Audit-event collections add hasChanges, changedEntityType, and changedPath filters. accountId now matches observed before and after entry sides even when the account/currency net effect is zero.
  • Active team administrators can read their team's public audit events. Ordinary members, owners, and embedded sessions remain denied. Recurring fees, bank records, and account connections are now reviewed root entities.
  • GET /teams/resolve no longer returns billingCustomerId. Integrations that need the regional Hyperline customer ID must call GET /team at the returned apiBaseUrl.

2026-07-29

  • POST /accounts/{id}/banking-init now commits account state, the opening transaction, and the feed checkpoint atomically and returns the complete opening transaction from that operation. Concurrent account cleanup can no longer turn an otherwise successful initialization into an invalid response.
  • POST /teams requests sent to the generic API gateway now route an explicit body dataRegion to the matching regional cell. The creator remains authorized through x-team-id; omitted placement continues to use the receiving cell.
  • Concurrent duplicate DELETE /transactions/{id} requests now return the standard NOT_FOUND response after the winning request removes the row, instead of exposing an internal database no result error.
  • GET /team and GET /teams/resolve now return effective billing-partner metadata when the selected team and partner are homed in different regions. Team application data remains regional; partner identity and lifecycle status come from the control plane.
  • Error message values are now static per condition across the production API. UUIDs, refs, emails, indexes, raw values, provider diagnostics, causes, and lock data are returned in structured context instead. Integrations should continue branching on code and reading context, not parsing display messages.
  • GET /teams/issues now includes a stable feature on every issue for partner-native queue grouping. Issue state remains source-controlled: fixed conditions disappear and later recurrence reuses the issue ID with a higher version. Snooze and application navigation remain partner UI concerns.
  • Audit events (GET /audit/events, GET /audit/events/{id}, GET /partner/audit-events) are now the only audit surface available to external callers, and the partner:audit:v1 bundle grants exactly that family. VRPlatform's internal forensic reads — /audit/actions, /audit/actions/{id}, /audit/effects, /audit/journal-deltas, /audit/mutations, and /audit/timeline — are no longer reachable with partner API keys or ordinary first-party users. They return raw change records, effect retry mechanics, and journal-row identity that the public event contract deliberately aggregates and redacts.
  • Audit change records now record that a sensitive field changed without storing its value. Credential, secret, token, and password fields are reduced to the changed key names.
  • GET /apps and GET /apps/{id} now return category: null for legacy apps that do not have a category. This aligns the response with the existing nullable app data and prevents one uncategorized app from failing the full app collection.
  • Reconnect-created provider syncs now change to failed when their asynchronous dispatch fails instead of remaining indefinitely queued without a Trigger run. Effect retries preserve the sync and its idempotency key.
  • VRI-to-VRT migration is now a supported Partner API workflow under /partner/vri-to-vrt. Bootstrap requires partner:provisioning:v1; account and listing previews plus historical statement import require partner:general-ledger:v1. Requests use sourceTeamId and targetTeamId, and both teams must be managed by the calling partner. The former /internal/migrate-vri-to-vrt routes have been removed.
  • Added partner-only POST /team/duplicate for asynchronous test-team copies. The source comes from x-team-id; uniqueRef provides deterministic exact retries; and optional anonymization preserves accounting amounts, dates, and relationships while replacing visible PII. Cloned connections are disabled and contain no credentials or sync state. Poll the returned audit action for completion; restricted keys need partner:audit:v1 for that read.

2026-07-27

  • Partner API keys can use every documented public partner workflow for a selected managed team. New restricted-key bundles cover audit, calendar, files, general ledger, integrations, recurring fees, statement layouts, and team members. Destructive operations remain outside standard bundles. Credential management, self-service, internal, demo, and legacy routes stay unavailable to partner API keys.

2026-07-25

  • Team responses now return billingPartner metadata for the same effective partner represented by billingPartnerId: the explicit billing partner, otherwise the accounting partner, otherwise VRPlatform.
  • GET /teams now accepts excludeTestTeams=true to exclude the demo tenant and teams assigned to the demo accounting or billing partner while retaining VRPlatform and its direct customers.
  • Team responses began exposing the now-retired effectiveStatus alongside the administrative status. See the 2026-07-31 breaking replacement.

2026-07-24

  • GET /team and GET /teams/resolve now return the effective non-nullable billingPartnerId, falling back to the accounting partner and then VRPlatform when no explicit billing partner is stored. Their partner metadata uses the same VRPlatform fallback when no accounting partner is stored.
  • Embedded members in GET /team and GET /teams/resolve now include lastName alongside the existing firstName, matching the member name fields returned by GET /team/members.
  • Added bearer-only PUT /me so an authenticated user can synchronously update their own first and/or last name. Supplied values are trimmed, blank names and target identifiers are rejected, and the response uses the same user shape as GET /me. API keys and current read-only embedded bundles cannot call the mutation.
  • Plaid sandbox completion no longer treats shared test account masks as GL account duplicates when returning configuration suggestions, issues, and action capabilities. Production sessions continue to reserve last four digits across active and inactive GL accounts.

2026-07-24

  • Added public audit events for synchronizing who or what changed a business entity, which public fields changed, and what the action did to accounting. GET /audit/events lists upsertable events for the selected team and GET /audit/events/{id} returns one event with signed posting-bucket before and after totals. Regional GET /partner/audit-events reads all managed teams in one data region. First-party access is administrator-only; partner API keys need the audit:read scope from the new partner:audit:v1 bundle; owner users and embedded sessions are denied.
  • Audit events cover account, listing, listingOwnershipPeriod, ownerStatement, reservation, and transaction roots with event-time actor, team, and account snapshots and allowlisted field changes. For synchronization, request order=asc, persist nextCursor, and upsert by id when revision increases; accounting revisions reappear on the same event ID. Ascending reads trail real time by a short visibility lag so concurrently committed revisions are never skipped. Online history is guaranteed for at least 180 days; a cursor pointing before the earliest retained event returns 410 with earliestAvailableAt.

2026-07-23

  • DELETE /accounts/{id}/connections/{accountConnectionId} now returns the detached connection ID with status: "deleted".
  • Global VRPlatform admins can now list, create, reveal, and revoke API tokens for any selected team without joining that team. Team admins retain their existing inherited access; API-key and ordinary-user callers remain denied.
  • Expanded the pre-release embed:reports:v1 bundle with read access to GET /accounts, GET /listings, and GET /contacts for embedded report filters. Their detail, CSV, and mutation routes remain unavailable to embedded sessions, and every request remains bound to the session team.
  • Added regional GET /partner/listings for the partner dashboard Listings CSV. It returns active property-manager listings with owning-team identity, calculated display names, structured/full addresses, the existing dashboard team filters, deterministic team/listing ordering, and standard pagination. Explicit team IDs outside the authorized regional slice return 403.
  • Added partner-only GET /partner/connections for regional connection inventory. It returns managed VRI and VRT teams, including empty teams, with active connection app metadata, error state, and current sync state. Team, company, lifecycle, app, and app-scoped error-state filters run before team totals and pagination.
  • Standardized sorting on GET /bank-records, /bank-records/csv, /files, /internal/feature-flags, /partner/billing, /partner/connections, /partner/owner-statements, /partner/users, /syncs, and /teams on one signed sort parameter. An unprefixed field sorts ascending and -field sorts descending. Generated schemas explicitly list both variants and each endpoint's default.
  • This is a breaking change: sortBy, sortDirection, and direction-suffix values are no longer accepted. Migrate sortBy=date&sortDirection=desc, sortBy=-date, or sort=created_desc to sort=-date. Text ordering is case-insensitive, nullable fields place nulls last, and deterministic ID tie-breakers keep pagination stable.

2026-07-21

  • Added VRP-admin message-overwrite administration under /internal/message-overwrites. The collection supports pagination, total counts, deterministic ordering, and case-insensitive partial search across patterns and replacement messages; create, replace, and delete operations reject blank fields and return not found for missing resources.
  • Owner statement summary list, detail, and exports now allocate manual listing payouts tagged to a non-owner payee across the ownership-period percentages. Payouts tagged directly to an owner still belong fully to that owner.

2026-07-19

  • POST /plaid/connect now accepts optional environment=sandbox|production. New Items default to production, and the returned connectId owns the environment for completion and configuration.
  • PRO-16794: added team-name search, pagination, and status-count ordering to GET /partner/owner-statements. Partner dashboards can traverse regional VRT teams with page and limit, or offset and limit, use pagination.total for the complete matching count, and order by draft, inReview, or published counts. Search is a case-insensitive partial match.
  • Added GET /partner/owner-statements for regional partner dashboards. It returns VRT child teams with persisted owner-statement counts for draft, inReview, and published; VRI and manager statements are excluded.
  • GET /me now includes the resolved team's dataRegion and apiBaseUrl. When the resolved team is a partner, it also includes partnerContext.managedTeamRegions with regional API URLs and active/inactive managed-team counts.
  • Regional partner portfolio reads now accept x-data-region. The header selects one storage partition without changing the authenticated partner or team context. Initial support covers team lists/lookups, team issues, and partner-user reads.
  • Portfolio pages and cursors remain regional. Clients that combine a multi-region portfolio call each advertised region independently.

2026-07-18

  • Renamed the external banking identity resource from BankAccount to AccountConnection. Use /account-connections, POST /accounts/{id}/connections, and DELETE /accounts/{id}/connections/{accountConnectionId}.
  • BankRecord contracts now use accountConnectionId, accountConnectionRef, and accountConnection for the optional external identity. accountId remains the canonical posting Account.
  • CSV bank-record imports remain valid with only accountId; they do not need an AccountConnection. CSV exports now label the external identity as Account Connection.
  • Statement payout bankAccountId continues to mean a canonical bank Account and is validated accordingly.

2026-07-17

  • Added compact, source-versioned connection.changed, sync.status.changed, reservation.changed, listing.changed, statement.status.changed, and transaction.changed webhook contracts. Current authenticated API reads remain the source of truth.
  • Webhook creation now requires an explicit verification test after the receiver stores its secret. URL/event-set changes and reactivation require a test of the current subscription revision.
  • Secret rotation now emits signatures from the new and previous secrets for a 24-hour overlap. Added webhook administration quotas, 90-day terminal delivery retention, and one-minute delivery recovery.
  • Outbound delivery now uses private resolve-and-pin egress. Every attempt rejects mixed or non-public DNS answers, dials one validated numeric address, preserves the original TLS hostname, and never follows redirects. Public enablement remains gated on pre-release failure drills.
  • Embedded-session bearer tokens now authenticate on GET /me and preserve their issued team binding when x-team-id is omitted.
  • GET /me now returns user.email: null for embedded identities, which use the partner-provided sub instead of an email address. Email remains required for ordinary authenticated users.
  • Team-member reads no longer fail for users created with an empty secondary email list; stored values are constrained to JSON arrays.
  • Added onLocked=nextOpen to reservation adjustment creation. It resolves books-closed and statement-period conflicts to the earliest valid concrete posting date; onLocked=error remains the default.
  • Reservation adjustment dry runs now return the resolved generalLedgerPostingAt without saving the adjustment.
  • Clarified that reservation line exclusion is set through a mapping with accountId: null; status=excluded and line isExcluded are derived.

2026-07-16

  • Retired partner edge hosts; the public API is served only at https://api.vrplatform.app.
  • Removed machine-to-machine credential references from public documentation; public authentication is x-api-key and Authorization: Bearer as listed in the Authentication summary.
  • Documented the webhook signature headers and HMAC-SHA256 signed-string format in Webhooks.
  • Documented the rate-limit policy in the Error contract: no enforced limits currently, and the API never emits 429.

2026-07

  • Added materialized, versioned GET /teams/issues snapshots.
  • Added team-owned outbound webhook subscriptions, delivery history, retries, secret rotation, testing, and replay.
  • Added team.issues.changed as the first subscribable public event.
  • Published generated issue and webhook catalogs from typed runtime registries.

Exact endpoint schemas are generated from current OpenAPI. Historical design context remains in repository RFCs and version logs rather than in current behavior pages.

Documentation

  • 2026-07: Consolidated UI business rules, concepts, partner setup, imports, and operations into task-oriented journeys while preserving old documentation URLs with permanent redirects.

On this page