VRPlatformVRPlatform
Integrate & Migrate Data

Team Setup

Discover, create, and initialize a team for an integration

Use a partner API key for the partner-scoped routes on this page. Partner API keys are issued by VRPlatform during partner onboarding — see Authentication and Credentials. Collection routes like list teams are partner-scoped and take no x-team-id header. Singleton team routes use x-team-id.

Discover Teams

curl 'https://api.vrplatform.app/teams' \
  -H 'x-api-key: <partner-api-key>'

Store the returned team ID. Use it for team-scoped product requests and embedded sessions.

Each listed team includes isBillable, a non-nullable effective billingPartnerId, and matching billingPartner metadata. The effective billing partner is the explicit billing partner when present, otherwise the managing partner, otherwise VRPlatform. The billingPartnerId query filter uses that same effective relation.

status is the derived lifecycle state. It is active only when both the team and its effective billing partner have active calculated subscription state. There is no separate administrative status in team responses. The status query parameter uses the same calculation, so a returned row always matches the requested status.

Team rows returned by GET /partner/billing use the same status and capability contract.

Before presenting an activation action, inspect capabilities.activate. It contains enabled and typed disabledReasons. Disable activation when it is not enabled and show the corresponding reason. Deactivation remains available. PUT /team rechecks the same condition and returns 400 BAD_REQUEST with the requested and current status plus the disabled reasons in structured context if state changed after the read.

Add includeAggregates=true for partner-dashboard summaries:

curl 'https://api.vrplatform.app/teams?includeAggregates=true' \
  -H 'x-api-key: <partner-api-key>'

That opt-in adds active-listing, non-owner member, active-connection, current connection-issue, and direct child-team counts. Omitting the parameter omits aggregates entirely and keeps the default request lightweight. Partner listing totals include the partner's direct listings and listings belonging to clients billed through that partner.

The singleton get team response always includes isBillable and aggregates; it does not require includeAggregates.

Team resolution uses the control plane for identity, placement, billingPartnerId, and billingPlan. Hyperline customer identity, subscription, payment-method, trial, cancellation, and accounting state remain regional. If you need billingCustomerId, call GET /team at the apiBaseUrl returned by GET /teams/resolve; the resolve response does not include this regional field.

Team administration views can filter with billingPartnerId, isOnboarding, billingSubscriptionStatus, billingPlan, product, and comma-separated featureIds. Subscription filters support missing, viaPartner, and pendingCancellation; plan filters support other and none; product accepts vrtrust or vrintegrations. Filters are applied before pagination, so pagination.total describes the complete filtered regional result. Request each portfolio region separately with x-data-region.

Read Monthly Partner Billing

Use list partner billing to load the property-manager teams billed by the authenticated partner for one month:

curl 'https://api.vrplatform.app/partner/billing?month=2026-06' \
  -H 'x-api-key: <partner-api-key>' \
  -H 'x-data-region: us'

For a completed month, each team uses its latest retained listings_reported count explicitly attributed to the authenticated partner through the legacy date-only month-end cutoff. Attribution is filtered before the latest event is selected. A currently billed team without an attributed event uses its live count only when another listing report exists in that historical window; teams without any report in the window are excluded. The current month always uses live counts. Live non-GL counts use calculated listing status, including manual and PMS status, while live GL counts use current ownership-period deactivation.

Deleted teams remain as historical rows. They keep the original team ID and monthly listing count, use status: deleted, and return unavailable live-team fields as null. Consumers must disable actions that require a live team.

The endpoint supports team/company search, lifecycle, accounting partner, product, and billing-plan filters plus deterministic sorting and standard pagination. Sort by name, created, partnerName, product, activeListings, or billingPlan; prefix the value with - for descending order. The default is sort=-created. Filtering happens before totals and page selection. One request reads one regional partition; request each portfolio region separately and retain region identity when combining results or exporting CSV.

Export Active Listings

Use list partner listings to export active property-manager listings for the current partner or VRP-admin dashboard:

curl 'https://api.vrplatform.app/partner/listings?partnerId=<partner-id>' \
  -H 'x-api-key: <partner-api-key>' \
  -H 'x-data-region: us'

The endpoint accepts the dashboard's team IDs, team/company search, lifecycle, onboarding, accounting-partner, effective billing-partner, subscription, billing-plan, product, and enabled-feature filters. Filters run before pagination.total and page selection. Only listings that pass the same live active-listing calculation as partner billing are returned: non-GL listings use calculated listing status, while GL listings use ownership-period deactivation.

Each row contains the listing ID and calculated display name, owning team ID and name, structured address fields, and the full stored address. Rows are ordered by team name and calculated listing name with stable ID tie-breakers, so clients can combine every page directly into the existing Listings CSV. Request each advertised portfolio region separately. When explicit team IDs are supplied, any ID outside the authorized selected region returns 403 instead of producing an incomplete export.

Create A Team

curl 'https://api.vrplatform.app/teams' \
  -X POST \
  -H 'x-api-key: <partner-api-key>' \
  -H 'content-type: application/json' \
  --data '{
    "name": "Example Team",
    "email": "team@example.com",
    "generalLedger": false
  }'

The generated operation defines all optional billing, address, portal, and member fields. generalLedger: false creates the team without accounting setup. When generalLedger is omitted, true, or a configuration object, the API runs team initialization as part of the create request: it provisions the chart of accounts, tax rates, statement layouts, recurring fees, and line mappings from the default template (or from copyFromTeamId in the configuration object). Create team does not support dry run.

When defaultCurrency is provided, it must be present in the target region's supported currency catalog. An unsupported value returns 400 BAD_REQUEST with context.defaultCurrency, and no team is created.

In the Hostaway data region, omitting copyFromTeamId selects the approved Hostaway default. Its 54 concrete line mappings include a non-posting processing-fee reference account and a posting VAT-collected revenue account. Discounts map to rents and retain their negative source amounts. guestChannelFee and airbnbTransientOccupancyTax are excluded. Standard tax types are excluded only for the exact Airbnb booking channel, while airbnbPassThroughTax remains posted. hostChannelFee uses the general channel-commission reference account except for its Airbnb expense-account override. Custom Hostaway fee names are mapped after their concrete type is known.

When provisioning with a partner API key, uniqueRef is required: send your own stable identifier for the customer. Exactly repeating a completed create fails with 409; the error's context.existingTeamId identifies the existing team. A changed payload for the same key fails without a resumable id. Load the existing team with lookup team instead of re-posting. Retrying a create request that failed before completing is safe; a request that succeeded must not be repeated.

New teams are placed in the data region of the API host you call, so omit dataRegion unless you deliberately target another region from a multi-region host. A region that has no provisioned cell is rejected with 400.

Duplicate A Team

Use POST /team/duplicate to create an asynchronous test-team copy of a partner-managed property-manager team. Select the source with x-team-id and send a partner API key that has the partner:provisioning:v1 bundle. A restricted key also needs partner:audit:v1 to poll completion.

curl 'https://api.vrplatform.app/team/duplicate' \
  -X POST \
  -H 'x-api-key: <partner-api-key>' \
  -H 'x-team-id: <source-team-id>' \
  -H 'content-type: application/json' \
  --data '{
    "name": "Blue Crush Demo",
    "uniqueRef": "blue-crush-demo-001",
    "anonymize": true
  }'

The response identifies the deterministic target and the audit action:

{
  "actionId": "c8e5e122-e568-4b10-959e-ca88aa6778ce",
  "anonymized": true,
  "name": "Blue Crush Demo",
  "sourceTeamId": "277698df-a242-4f8d-b2f7-af69b79d85be",
  "status": "queued",
  "targetTeamId": "b8c49c19-3528-5c10-8b67-f3b72ad525df",
  "uniqueRef": "blue-crush-demo-001"
}

anonymize defaults to false. When enabled, the worker deterministically replaces visible guest, owner, listing, contact, address, bank-display, and free-text data while preserving amounts, dates, and relationships.

The target is always a test team assigned to the same partner. The supported business and accounting graph includes listings, ownership periods, reservations, payments, transactions, bank records, journals, statement layouts, recurring fees, and owner statements. Users, tokens, audit history, files, webhooks, automations, tasks, live credentials, and sync runtime state are not copied. Connections are copied only as disabled shells with empty credentials and persistent state.

Treat uniqueRef as the idempotency key. An exact retry returns the same targetTeamId and safely resumes the audit work. Changing the name or anonymize value for that key returns 409; use a new uniqueRef for a different clone. A key already used by another team for the partner also returns 409.

Poll GET /audit/actions/{actionId} with the source x-team-id. The initial response means the work was queued; use the action's effect counts to decide when the duplicate is complete or failed. Polling requires audit:read, which is included in partner:audit:v1.

Completion includes the target's control-plane identity and connection routes. If the background runtime cannot access separate regional and control-plane databases, the effect fails instead of returning a regional-only duplicate.

Initialize Later

Use initialize team only when the selected team still needs GL initialization or a specific copy/include plan. Send the selected team in x-team-id. The operation supports dry run.

Initialization can copy selected accounts, tax rates, mappings, fees, or statement layouts. Treat it as an accounting setup operation, not a repeated idempotent bootstrap call.

Manage the Onboarding Guide

Use GET /team/guides/onboarding to read the selected team's VRPilot onboarding checklist. Every response contains the fixed step set with status and the server-owned updatedAt timestamp.

Use PUT /team/guides/onboarding with exactly one guide or step key. A step can be set to completed, skipped, or null. These are manual checklist choices: the API does not require the step's normal product action to exist before it accepts completed. Sending null records an explicit incomplete choice, so a live completion signal does not immediately complete that step again.

PUT /team/guides/onboarding
Content-Type: application/json

{
  "openingBalances": "completed"
}

Automatic completion still applies to untouched steps when the related setup is detected. Reopening a required step also reopens a completed guide. Optional steps can be reopened without changing the guide-level completion status.

Guide-level status: completed remains valid only after every required step is either completed or skipped. This is the overall checklist gate; it does not prevent manual status changes on individual steps.

Verify

Load the selected team and inspect ID, status, type, GL state, books-closing date, partner relationship, and available connection capabilities. Then continue to Connections.

Update Team Branding

Use update team with the selected team in x-team-id to set logo or colorPrimary. Both fields support explicit clearing: send null to remove the stored logo or primary color. Omitting either field leaves its current value unchanged.

List Managed-Team Users

Use list partner users to build a user directory across managed child teams. The collection excludes anyone who has a direct membership on the partner team itself, even when that person also has a managed child-team membership. Search, user views, team filters, totals, and pagination all operate after this exclusion.

When the portfolio spans regions, request each region advertised by GET /me with x-data-region; one response contains only the selected regional partition.

List Partner-Team Members

Use list partner members to build the partner team's own member directory. Each root row includes the member's role, status, and lastInvitedAt from the partner-team membership. Its memberships array contains only managed child-team memberships.

Invite A Team Member

Use invite team member with the selected team in x-team-id. Set sendEmail: false to create a copyable link instead of sending the email immediately. The endpoint does not support dry run because it creates an invite token and dispatches notification work.

An email already used by an owner account cannot also be invited as a team member. That request returns 400 BAD_REQUEST; use the structured error code for behavior and display its message to explain the conflict.

If the email provider has suppressed the address after a bounce, complaint, or manual suppression, the request also returns 400 BAD_REQUEST. Offer sendEmail: false to create a copyable invite link, or ask for another email address. The response uses a static message and does not expose provider or recipient diagnostics.

Delete A Team

DELETE /team?confirm=true queues deletion of the team selected by x-team-id. This administrative operation requires an authenticated active VRPlatform member. Partner API keys, service tokens, and ordinary tenant users receive 403 and must contact VRPlatform support. force=true bypasses active resource checks, but it does not bypass the active-subscription guard.

Deletion runs asynchronously after validation. A successful response confirms that the deletion task was queued, not that every cleanup step has completed.

API Reference

On this page