Importación masiva de activos desde un CSV
Esta guía muestra cómo crear RealityAssets de forma masiva en un twin a partir de un archivo CSV. Cada fila define el nombre de un activo y un cuadro delimitador orientado en el espacio del twin. El flujo de trabajo usa el flujo de Client Credentials y el ámbito write:asset.
Requisitos previos
Sección titulada «Requisitos previos»- Una aplicación OAuth configurada para Client Credentials
- Ámbitos:
read:basic,read:hierarchy,write:asset - Tu
client_idyclient_secret - Acceso al contenido y permisos de edición sobre el twin de destino
- El ID del twin donde deben crearse los activos
Cuándo usar este patrón
Sección titulada «Cuándo usar este patrón»Usa una importación basada en CSV cuando ya tengas definiciones de activos fuera de Prevu3D, por ejemplo:
- Listas de equipos exportadas desde un sistema CMMS o ERP con coordenadas 3D
- Resultados de inspección o etiquetado desde una herramienta externa
- Migración desde otra plataforma donde los activos se posicionaron en coordenadas del twin
Cada llamada a la API crea un activo. Un script recorre las filas del CSV y llama a POST /v1/twin/{twinId}/assets por cada entrada.
Formato del CSV
Sección titulada «Formato del CSV»La hoja de cálculo debe incluir una fila de encabezado. Columnas obligatorias:
| Columna | Se asigna a | Descripción |
|---|---|---|
Description | name del activo | Nombre para mostrar del RealityAsset |
Manual_X | x del centro del cuadro | Coordenada X del centro del cuadro en el espacio del twin |
Manual_Y | y del centro del cuadro | Coordenada Y del centro del cuadro en el espacio del twin |
Manual_Z | z del centro del cuadro | Coordenada Z del centro del cuadro en el espacio del twin |
Manual_Box_X | x del tamaño del cuadro | Ancho del cuadro delimitador |
Manual_Box_Y | y del tamaño del cuadro | Profundidad del cuadro delimitador |
Manual_Box_Z | z del tamaño del cuadro | Altura del cuadro delimitador |
Ejemplo:
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.69Las coordenadas deben estar en el mismo sistema de coordenadas que el twin. Si posicionaste los activos manualmente en RealityTwin, exporta o registra los valores en el espacio del twin. La rotación adopta por defecto la identidad; la API acepta un cuaternión rotation opcional en cada cuadro si necesitas volúmenes orientados.
Flujo integral
Sección titulada «Flujo integral»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"]
| Paso | Endpoint | Qué obtienes |
|---|---|---|
| Autenticar | POST /oauth/token | Token de acceso |
| Resolver la URL de la API | GET /oauth/api-info | apiUrl regional |
| Crear activo | POST /v1/twin/{twinId}/assets | Un nuevo ID de activo por fila |
Forma de la carga útil del activo
Sección titulada «Forma de la carga útil del activo»Cada fila se convierte en un activo con una workingStructure que contiene un único cuadro orientado:
{ "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 } } ] }}Para asignar un tipo de activo en el momento de la creación, añade assetTypeId con el UUID de un tipo configurado en tu organización. Consulta Tipos de activo para saber cómo se definen los tipos en RealityPlatform.
Paso 1 — Autenticar
Sección titulada «Paso 1 — Autenticar»Obtén un token de acceso con 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}Paso 2 — Crear activos desde el CSV
Sección titulada «Paso 2 — Crear activos desde el 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 } } ] }}Una respuesta correcta devuelve el activo creado, incluido su id. Repite para cada fila del CSV.
Ejemplo completo
Sección titulada «Ejemplo completo»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)}")Encontrar el ID del twin
Sección titulada «Encontrar el ID del twin»El ID del twin es el UUID del nodo del twin en tu jerarquía de contenido. Puedes:
- Copiarlo de la URL de RealityPlatform cuando el twin está abierto
- Explorar la jerarquía con
GET /v1/nodes/{organizationId}/browsey localizar un nodo contype: "Twin"
Consejos para importaciones grandes
Sección titulada «Consejos para importaciones grandes»- Agrupa de forma responsable. La API crea un activo por solicitud. Para cientos de filas, añade un breve retraso o backoff si alcanzas los límites de tasa.
- Valida las coordenadas primero. Importa una única fila de prueba antes de ejecutar el archivo completo.
- Usa el modo borrador en RealityTwin cuando quieras revisar los activos antes de que otros usuarios los vean. Los activos creados a través de la API aparecen en el twin de inmediato, salvo que tu integración apunte a un flujo de borrador.
- Adjunta metadatos más tarde. Después de la creación, usa
PATCH /v1/twin/{twinId}/assets/{assetId}/metadatapara añadir valores de propiedades. Consulta los endpoints de activos en la referencia de la API.
¿Qué sigue?
Sección titulada «¿Qué sigue?»- Configura la autenticación en la guía del flujo de Client Credentials.
- Aprende cómo funcionan los activos en el espacio de trabajo del twin: Trabajar con RealityAssets.
- Explora los endpoints de activos en la referencia de la API.