VRPlatformVRPlatform
Getting Started

Authentication and Credentials

Select the credential and team-context contract for each surface

Keep credentials on a trusted backend. Never place a team API key, partner API key, or webhook secret in browser code.

Getting Credentials

Team and partner API keys use the same API-token management surface. A signed-in admin creates them for the selected team through the dashboard or POST /api-tokens. Contact VRPlatform to register a team as a partner.

A signed-in team admin can list, create, reveal, or revoke API keys. Global VRPlatform admins may perform the same operations for any selected team without joining that team. API-key-authenticated requests cannot manage credentials, including keys linked to an admin user. VRPlatform generates the token secret and returns it in the create response; callers never supply secret material. The dashboard list exposes only metadata and a four-character hint; opening one key reveals its full value. Revocation takes effect on the next authenticated request.

CredentialHeaderUse
Team API keyx-api-key: <team-api-key>Direct backend calls for one or more teams
Partner API keyx-api-key: <partner-api-key>Partner backend and managed-team calls
Embedded sessionAuthorization: Bearer <token>Short-lived iframe product calls
Interactive sessionAuthorization: Bearer <token>Signed-in or OAuth user calls

API Keys

Use x-api-key on backend product API requests. A key that can access more than one team must select the target with x-team-id. A single-team key can omit the header when the route can resolve its only accessible team.

Treat the full value shown by the dashboard as a secret. Audit records include the token record ID and non-secret metadata, never the token value.

API tokens may include up to 32 allowedIpCidrs entries. Individual IPv4 and IPv6 addresses are normalized to /32 and /128; networks are normalized to their CIDR boundary. When the list is non-empty, every x-api-key request must originate from a matching Cloudflare CF-Connecting-IP. Omit the field or send an empty array for no IP restriction. X-Forwarded-For is never trusted for this decision.

Partner-scoped collections such as GET /teams operate across managed teams and need no managed-team selection. When the portfolio spans regions, use x-data-region on supported collection reads to select one regional slice; the partner API key remains the authorization context. Team-scoped routes (for example GET /team, GET /transactions) require a selected team and ignore x-data-region.

New keys owned by a partner team may declare reviewed, versioned capability bundles. When bundles are present, the server expands them into exact primitive scopes and exposes both on token metadata. Omitting bundles creates an unrestricted partner token (scope: "*") with every partner API scope. The partner authorization boundary still rejects bearer-only, internal, and explicitly denied routes.

For restricted tokens, a route must be explicitly available to partner credentials and the key must contain every required scope. Write access does not imply delete, publish, pay, execute, import, or journal-posting access.

Available partner bundles:

  • partner:accounting-data:v1: listings, contacts, ownerships, reservations, transactions, accounts, tax rates, and line mappings.
  • partner:audit:v1: team audit actions, effects, mutations, journal deltas, and timeline reads.
  • partner:banking:v1: bank accounts, account connections, Plaid configuration, bank records, and bank rules.
  • partner:calendar:v1: calendar-block reads and writes.
  • partner:files:v1: team-file reads, downloads, uploads, and metadata writes.
  • partner:general-ledger:v1: opening balances, opening trial balance, and historical GL or statement imports.
  • partner:integrations:v1: apps, connections, flows, mappings, settings, syncs, booking channels, imports, and source downloads.
  • partner:onboarding:v1: team onboarding guide and issue operations.
  • partner:provisioning:v1: partner/team discovery, provisioning, initialization, and embedded-session issuance.
  • partner:recurring-fees:v1: recurring-fee and listing-period reads, previews, and writes.
  • partner:reports:v1: report reads and exports plus metric reads.
  • partner:statement-layouts:v1: statement-layout reads, creates, updates, and listing assignments.
  • partner:statements:v1: statement reads, layout reads, and exports.
  • partner:team-members:v1: selected-team member reads, invites, role updates, and removals.
  • partner:webhooks:v1: webhook subscription, delivery, test, rotation, and replay operations.

Destructive calendar, file, recurring-fee, and statement-layout operations remain outside their standard bundles. An unrestricted partner key can use their separate delete scopes; restricted keys cannot acquire those scopes through another bundle. Credential management, self-service, internal, demo, and legacy routes remain unavailable to partner API keys.

GET /me is a bearer-user bootstrap route for interactive and embedded sessions. An interactive user can update their own trimmed first and last name through PUT /me or send touchLastSeen: true to record the server's current time as their latest activity. The server does not accept a caller-provided timestamp. The session supplies the user identity, so the request cannot select another user or team. The mutation persists before returning the same user shape exposed by GET /me; lastSeen is not added to that response.

Scoped bearer sessions need self:write for PUT /me. The current embedded bundles are read-only and do not grant that scope. Partner API keys resolve their partner or managed-team context through the partner and team endpoints; they cannot call either /me operation.

Embedded Sessions

A partner backend sends its API key to POST /partner/embed-sessions. It receives a 60-second, single-use embed URL, not the bearer token. The iframe exchanges the fragment code directly and keeps its 15-minute reports session in memory. The token is bound to one user, team, audience, embed origin, parent origin, lifecycle channel, and read-only bundle set; a conflicting team header or an unclassified route is rejected.

The partner and selected managed team may be stored in different data regions. With autoProvision: true, VRPlatform records the embedded identity centrally and routes each persistent team membership to the region that owns that team; the partner backend does not need to select or coordinate those regions.

Failed Authentication

Branch on the HTTP status and the structured API error code (see the Error contract). Do not parse the human-readable message. When 401 or 403 responses repeat, send the user back to credential, access-scope, and team-context checks; do not fall back to another credential automatically.

On this page