VRPlatformVRPlatform
Integrate & Migrate Data

Batch Imports

Submit source data through the product API batch endpoints

Submit source data through the normal product API batch endpoints. There is no separate ingest surface: batches use the same host, credentials, validation, locks, and dry-run behavior as every other operation.

POST https://api.vrplatform.app/reservations/batch
x-api-key: <team-api-key>
x-team-id: <team-uuid>

Available Batch Operations

The exact request schema and per-entity fields live on each generated page.

Identity and Idempotency

Send a stable uniqueRef per item. Resubmitting the same uniqueRef updates the existing record instead of creating a duplicate, so to retry safely, resend the batch. The rules for stable identity, conflict handling, and irreversible side effects live in Integration-sourced data.

Outcomes

A batch responds with per-item results and structured issues:

{
  "data": [
    {
      "id": "11111111-1111-4111-8111-111111111111",
      "uniqueRef": "pms-res-1042",
      "sourceId": null
    }
  ],
  "issues": []
}

Process data and issues item by item; a batch is not all-or-nothing. Validate risky batches first with dry run where the operation declares the dryRun parameter.

Asynchronous Operations

Long-running endpoints return after VRPlatform durably records the work. Each endpoint documents its request and returns the same operation envelope:

{
  "operationId": "op_dQyc6IHtQbmwTn-TMMWD7Q",
  "type": "csv-import",
  "status": "queued",
  "resource": {
    "type": "connection",
    "id": "11111111-1111-4111-8111-111111111111",
    "role": "target"
  }
}

operationId is the stable, opaque status identifier. New identifiers use an op_ or act_ prefix. Existing UUID identifiers remain valid during the compatibility period. Store and return the complete value without parsing its prefix. type identifies the public operation category. resource identifies its primary source, target, or result when one exists; it can be null for multi-resource work.

Read one operation

GET /operations/{id}

Replace {id} with the operationId returned by the initiating endpoint.

curl \
  -H "x-api-key: $VRPLATFORM_API_KEY" \
  "https://api.vrplatform.app/operations/op_dQyc6IHtQbmwTn-TMMWD7Q"
{
  "id": "op_dQyc6IHtQbmwTn-TMMWD7Q",
  "type": "csv-import",
  "status": "running",
  "resource": {
    "type": "connection",
    "id": "11111111-1111-4111-8111-111111111111",
    "role": "target"
  },
  "resources": [
    {
      "type": "connection",
      "id": "11111111-1111-4111-8111-111111111111",
      "role": "target"
    }
  ],
  "failure": null,
  "createdAt": "2026-08-15T13:45:10.123Z",
  "startedAt": "2026-08-15T13:45:12.456Z",
  "finishedAt": null
}
StatusMeaning
queuedThe operation is durably recorded and waiting for execution.
runningA worker is executing the operation.
completedAll work owned by the operation completed.
failedThe operation reached an unsuccessful terminal state.

createdAt is always present. startedAt records the first start and can stay set during recovery. finishedAt is set only for completed or failed. Operations with several required sources remain non-terminal until every source settles. The API does not expose child progress.

Poll until the operation reaches completed or failed. Start with a short interval and back off while the status remains non-terminal. This API exposes observation only; it does not provide public retry or cancellation controls.

Track reservation journal recalculation

A journal-relevant PUT /recurring-fees/{id} returns the accepted operation inside the recurring fee response:

{
  "id": "3cb5eb9e-c5d7-4268-8f40-2d4df2819702",
  "name": "Management fee",
  "operation": {
    "operationId": "act_VQ6EAOKbQdSnFkRmVUQAAA",
    "type": "reservation-journal-refresh",
    "status": "queued",
    "resource": {
      "type": "recurring-fee",
      "id": "3cb5eb9e-c5d7-4268-8f40-2d4df2819702",
      "role": "source"
    }
  }
}

operation is null when the update queues no reservation journal work. Dry runs also return operation: null.

Reservation, recurring fee, and owner statement reads include the same operation in their operations summary while the recalculation is queued or running. They also include journalStatus:

StateMeaning
currentEvery known journal change in the resource scope is applied.
recalculatingAt least one outstanding change has queued or running work.
failedOutstanding work reached a terminal failure.
staleThe journal has outstanding change without active recovery work.

Poll GET /operations/{id} instead of repeatedly refetching the heavier domain resource. Refetch the visible resource once the operation becomes completed or failed, then trust the returned journalStatus; operation completion alone does not prove that every scoped journal change is applied. Share one poll when several visible resources contain the same operation ID.

Authenticated owners can poll a reservation-journal-refresh operation only when an affected reservation is within their owner access. Operations outside that access return the standard not-found response.

Find operations after refresh

Use GET /operations to filter retained history by resource, type, status, or creation time. The response includes cursor-paged items, the retained match total, and queued, running, completed, and failed counts.

Completed operation history is retained for 90 days. An unresolved failed journal refresh remains available until later work applies its outstanding journal change; the normal 90-day window starts after that recovery completes.

Pass type=reservation-journal-refresh&initiatedBy=me to show refresh work attributed to the authenticated user. Omit initiatedBy for the team-wide support view. Each operation returns either a user initiator with userId or a system initiator.

Supported team, connection, contact, listing, reservation, recurring fee, statement, transaction, flow, bank-rule, recurring-template, and webhook reads also include an operations summary. Its counts cover retained history. Its items contain queued, running, and latest unresolved failed work, so a refreshed UI does not need a saved operation ID or one request per resource.

Read import and export results

CSV preview and import result endpoints use the operationId in their normal typed result path after completion. They do not read execution-provider state.

Use a documented generating GET route when the selected export is bounded to finish within one minute. It returns a signed download URL when generation finishes and does not create an operation.

Use the matching POST route for durable background work, larger supported selections, or whenever the caller needs status that survives the initiating request. The queued operation uses a file result resource. After it completes, read its resources and download the file through:

GET /files/{fileId}/download

If a GET selection exceeds its awaited budget, the API returns EXPORT_REQUIRES_POST. Send the same selector to POST and follow the returned operation instead.

Authorization and privacy

Operation detail and history require operations:read. Every Partner or embedded bundle that can start queued work and every UI permission bundle grants that scope; no separate polling credential is required.

An operation belongs to the requesting tenant resolved when it was created, not to a target entity named in its request. For example, a VRI import created with a Partner credential belongs to that Partner tenant; a token belonging to the target team receives 404 for its id. Unknown identifiers, unsupported internal action types, and identifiers owned by another requesting tenant all return 404.

The response never exposes request payloads, raw errors, effects, attempts, provider steps, or runtime identifiers. Failed operations can expose only a stable code and static safe message. Internal, non-allowlisted work is not readable through these endpoints.

Poll through MCP

Use vrt_api_read; Partner paths do not require teamId:

{
  "path": "/operations/op_dQyc6IHtQbmwTn-TMMWD7Q"
}

For API-key authentication, MCP preserves the credential tenant and does not send x-team-id for this read. OAuth users supply the team that initiated the operation through teamId or the MCP connection's team_id.

On this page