Bulk Import Assets from CSV
This guide shows how to bulk-create RealityAssets in a twin from a CSV file. Each row defines an asset name and an oriented bounding box in twin space. The workflow uses the Client Credentials flow and the write:asset scope.
Prerequisites
Section titled “Prerequisites”- An OAuth application configured for Client Credentials
- Scopes:
read:basic,read:hierarchy,write:asset - Your
client_idandclient_secret - Content access and edit permissions on the target twin
- The twin ID where assets should be created
When to use this pattern
Section titled “When to use this pattern”Use a CSV-driven import when you already have asset definitions outside Prevu3D, for example:
- Equipment lists exported from a CMMS or ERP system with 3D coordinates
- Survey or tagging results from an external tool
- Migration from another platform where assets were positioned in twin coordinates
Each API call creates one asset. A script loops over the CSV rows and calls POST /v1/twin/{twinId}/assets for each entry.
CSV format
Section titled “CSV format”The spreadsheet must include a header row. Required columns:
| Column | Maps to | Description |
|---|---|---|
Description | Asset name | Display name for the RealityAsset |
Manual_X | Box center x | X coordinate of the box center in twin space |
Manual_Y | Box center y | Y coordinate of the box center in twin space |
Manual_Z | Box center z | Z coordinate of the box center in twin space |
Manual_Box_X | Box size x | Width of the bounding box |
Manual_Box_Y | Box size y | Depth of the bounding box |
Manual_Box_Z | Box size z | Height of the bounding box |
Example:
Description,Manual_X,Manual_Z,Manual_Y,Manual_Box_X,Manual_Box_Z,Manual_Box_YPump A,6.27,-5.10,187.12,0.35,0.64,0.33Valve B,8.84,-3.14,189.41,2.99,1.11,4.69Coordinates must be in the same coordinate system as the twin. If you positioned assets manually in RealityTwin, export or record values in twin space. Rotation defaults to identity; the API accepts an optional rotation quaternion on each box if you need oriented volumes.
End-to-end flow
Section titled “End-to-end flow”flowchart LR A["1. Authenticate"] --> B["2. Read CSV rows"] B --> C["3. Build workingStructure"] C --> D["4. POST asset per row"] D --> E["5. Review results"]
| Step | Endpoint | What you get |
|---|---|---|
| Authenticate | POST /oauth/token | Access token |
| Resolve API URL | GET /oauth/api-info | Regional apiUrl |
| Create asset | POST /v1/twin/{twinId}/assets | New asset ID per row |
Asset payload shape
Section titled “Asset payload shape”Each row becomes one asset with a workingStructure containing a single oriented box:
{ "name": "Pump A", "workingStructure": { "boxes": [ { "center": { "x": 6.27, "y": 187.12, "z": -5.10 }, "size": { "x": 0.35, "y": 0.33, "z": 0.64 }, "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 } } ] }}To assign an asset type at creation time, add assetTypeId with the UUID of a type configured in your organization. See Asset Types for how types are defined in RealityPlatform.
Step 1 — Authenticate
Section titled “Step 1 — Authenticate”Obtain an access token with Client Credentials:
POST https://cloud-api.prevu3d.com/oauth/tokenAuthorization: Basic base64(client_id:client_secret)Content-Type: application/x-www-form-urlencoded
grant_type=client_credentialsGET https://cloud-api.prevu3d.com/oauth/api-infoAuthorization: Bearer {access_token}Step 2 — Create assets from CSV
Section titled “Step 2 — Create assets from CSV”POST {api_url}/v1/twin/{twinId}/assetsAuthorization: Bearer {access_token}Content-Type: application/json
{ "name": "Pump A", "workingStructure": { "boxes": [ { "center": { "x": 6.27, "y": 187.12, "z": -5.10 }, "size": { "x": 0.35, "y": 0.33, "z": 0.64 }, "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 } } ] }}A successful response returns the created asset, including its id. Repeat for each CSV row.
Complete example
Section titled “Complete example”import base64import csvfrom pathlib import Path
import requests
CLIENT_ID = "your-client-id"CLIENT_SECRET = "your-client-secret"CLOUD_API_BASE = "https://cloud-api.prevu3d.com"TWIN_ID = "your-twin-id"CSV_FILE = Path("assets.csv")
credentials = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()token_response = requests.post( f"{CLOUD_API_BASE}/oauth/token", data={"grant_type": "client_credentials"}, headers={"Authorization": f"Basic {credentials}"},)token_response.raise_for_status()access_token = token_response.json()["access_token"]headers = {"Authorization": f"Bearer {access_token}"}
api_info = requests.get(f"{CLOUD_API_BASE}/oauth/api-info", headers=headers).json()api_url = api_info["apiUrl"].rstrip("/")
def api_post(path: str, body: dict) -> dict: response = requests.post(f"{api_url}{path}", json=body, headers=headers) response.raise_for_status() return response.json()
def oriented_box(cx: float, cy: float, cz: float, sx: float, sy: float, sz: float) -> dict: return { "center": {"x": cx, "y": cy, "z": cz}, "size": {"x": sx, "y": sy, "z": sz}, "rotation": {"x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0}, }
with CSV_FILE.open(newline="", encoding="utf-8") as handle: rows = list(csv.DictReader(handle))
created = []errors = []
for row in rows: name = row["Description"].strip() body = { "name": name, "workingStructure": { "boxes": [ oriented_box( cx=float(row["Manual_X"]), cy=float(row["Manual_Y"]), cz=float(row["Manual_Z"]), sx=float(row["Manual_Box_X"]), sy=float(row["Manual_Box_Y"]), sz=float(row["Manual_Box_Z"]), ) ] }, }
try: asset = api_post(f"/v1/twin/{TWIN_ID}/assets", body) print(f"[OK] {name} -> {asset['id']}") created.append(asset) except requests.HTTPError as error: print(f"[ERR] {name} -> {error.response.status_code} {error.response.text}") errors.append(name)
print(f"\nCreated: {len(created)} / Errors: {len(errors)}")Finding the twin ID
Section titled “Finding the twin ID”The twin ID is the UUID of the twin node in your content hierarchy. You can:
- Copy it from the RealityPlatform URL when the twin is open
- Browse the hierarchy with
GET /v1/nodes/{organizationId}/browseand locate a node withtype: "Twin"
Tips for large imports
Section titled “Tips for large imports”- Batch responsibly. The API creates one asset per request. For hundreds of rows, add a short delay or backoff if you hit rate limits.
- Validate coordinates first. Import a single test row before running the full file.
- Use Draft Mode in RealityTwin when you want to review assets before other users see them. Assets created through the API appear in the twin immediately unless your integration targets a draft workflow.
- Attach metadata later. After creation, use
PATCH /v1/twin/{twinId}/assets/{assetId}/metadatato add property values. See the asset endpoints in the API reference.
What’s next?
Section titled “What’s next?”- Set up authentication in the Client Credentials Flow guide.
- Learn how assets work in the twin workspace: Working with RealityAssets.
- Browse asset endpoints in the API reference.