VRPlatformVRPlatform
Integrate & Migrate Data

Connections

Discover apps, create source identity, complete OAuth, and monitor sync

A connection relates one team to a PMS, booking channel, bank provider, or other external system. It scopes source identity and synchronization; it does not replace VRPlatform resource IDs.

Discover The App

Call GET /apps, choose the exact returned id, and inspect its category, flows, extractors, importers, and connection requirements. Do not use the display name as identity.

Create With Credentials

Call POST /connections with partner or team API-key authentication and the selected x-team-id. Provide appId, optional name, and the credential shape declared by that app's generated contract.

Creation can queue PMS initialization or provider work. Read the returned connection and sync state instead of assuming all external setup completed in the request.

Browser Extension Credentials

Apps whose authentication.extension is true or an extension settings object use the browser-extension credential flow. A connect request without credentials returns ISSUE_EXTENSION so the client can collect them.

Submit extension credentials through params.credentials together with stable account identity from params.uniqueRef, credential email, or credential username. The API completes these credentials directly; do not forward them through any intermediary OAuth flow or treat the issue response as an OAuth prompt.

OAuth Flow

Use POST /connections/connect as the normal OAuth entry point.

When redirectTo is omitted, the API uses the registered production callback https://portal.vrplatform.app/callback/. The legacy production value without the final slash is canonicalized to that registered callback. Other explicit callback targets are preserved exactly because OAuth providers require an exact redirect URI match.

  1. Send appId, setup params, and your real callback redirectTo.
  2. If the API returns ISSUE_REQUEST_OAUTH, redirect to action.value, the provider authorization URL.
  3. The provider redirects back to redirectTo with state and other params.
  4. Send those callback params unchanged to POST /connections/connect.
  5. Read the success response and resulting connection.

An ISSUE_REQUEST_OAUTH response looks like this:

{
  "type": "issue",
  "code": "ISSUE_REQUEST_OAUTH",
  "message": "Please provide the missing details to connect this app.",
  "state": { "expiresIn": 180000 },
  "action": {
    "type": "oauth",
    "value": "https://provider.example.com/oauth/authorize?client_id=...&state=..."
  }
}

Callback params go into the request body under params — copy everything the provider appended to your callback URL, including state, as-is. The state value resolves the app, so appId may be omitted on the callback request. To reconnect an existing connection, send the same body to POST /connections/{id}/connect; a first-time connect uses POST /connections/connect:

POST /connections/11111111-2222-3333-4444-555555555555/connect
{
  "params": {
    "state": "<state param exactly as received on the callback>",
    "code": "<provider authorization code>"
  }
}

A completed connect returns type: "success" with the connection id and the connection resource.

Provider account identity is case-insensitive during connection completion. Create and reconnect normalize the returned identity to lowercase, so a casing-only provider change does not make the same login look like a different account. A genuinely different provider identity still blocks reconnecting the selected connection.

redirectTo is your callback; action.value is the provider page. Do not redirect to the callback before the provider authorizes.

state is a signed token that binds the app, team, setup params, callback, and optional connection; during the flow it can come back wrapped in an outer envelope that embeds the signed token. The API verifies the signature and the team binding, so pass the callback state back exactly as received — a rebuilt or edited value is rejected. If state is missing, malformed, expired, or completed under another team, restart the flow.

Synchronization

Use GET /connections, GET /connections/{id}, and Sync connection to render status, enabled flows, last fetch, and current failure. Provider sync is an external side effect and has no generic dry-run guarantee.

For production monitoring and team issues, continue to Operate.

Webhook Reconciliation

Subscribe to connection.changed for committed public connection changes and sync.status.changed for actual sync status transitions. Credential-only updates and sync subtask-only changes do not emit. Compare resourceVersion per resource and fetch the event's href; webhook bodies never contain credentials or provider response data.

API Reference

On this page