Let me provide a complete solution covering device registry schema, CSV format, and custom attribute definition:
Device Registry Schema:
Watson IoT Platform requires explicit schema definition before bulk import:
- Define Device Type Schema:
Navigate to Device Types → [Your Type] → Schema and define the structure:
{
"customAttributes": {
"type": "object",
"properties": {
"location": {
"type": "object",
"properties": {
"lat": {"type": "number", "minimum": -90, "maximum": 90},
"lng": {"type": "number", "minimum": -180, "maximum": 180},
"altitude": {"type": "number"},
"accuracy": {"type": "number"}
},
"required": ["lat", "lng"]
},
"deploymentDate": {"type": "string", "format": "date-time"},
"firmwareVersion": {"type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$"}
}
}
}
- Schema Validation Rules:
- All custom attributes must be pre-defined in device type schema
- Nested objects require explicit property definitions
- Use JSON Schema validation syntax for data types and constraints
- Required fields must be marked in schema
- Pattern validation available for string types
- Schema Update Process:
If modifying existing device type:
- Schema changes are versioned automatically
- Existing devices aren’t retroactively validated
- New imports validate against current schema version
- Test schema changes with small batch before bulk import
Bulk Import CSV Format:
Proper CSV structure for nested attributes:
- Header Row Format:
deviceId,deviceType,authToken,deviceInfo.description,customAttributes.location.lat,customAttributes.location.lng,customAttributes.location.altitude,customAttributes.deploymentDate,customAttributes.firmwareVersion
- Data Row Example:
DEV-2401,AssetTracker,auto-generated,"Warehouse sensor, Zone A",40.7128,-74.0060,15.5,2025-07-01T10:00:00Z,1.2.3
- Formatting Rules:
- Use dot notation for nested objects: parent.child.grandchild
- Enclose string values with commas/quotes in double quotes
- Use ISO 8601 format for date-time values
- Boolean values: true/false (lowercase)
- Null values: leave cell empty or use explicit null
- UTF-8 encoding without BOM
- Unix line endings (LF) preferred
- Special Cases:
# Array values (comma-separated in quotes)
customAttributes.tags,"sensor,warehouse,zone-a"
# Escaped quotes within strings
deviceInfo.description,"Device ""Alpha"" - Zone A"
# Optional fields (leave empty)
customAttributes.location.altitude,
Custom Attribute Definition:
Best practices for defining custom attributes:
- Supported Data Types:
- string: Text values (use pattern for validation)
- number: Floating point (use minimum/maximum for ranges)
- integer: Whole numbers
- boolean: true/false
- object: Nested structure
- array: List of values (define item type)
- date-time: ISO 8601 timestamps
- Validation Constraints:
{
"firmwareVersion": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
"description": "Semantic version format"
},
"signalStrength": {
"type": "integer",
"minimum": -120,
"maximum": 0,
"description": "RSSI in dBm"
},
"tags": {
"type": "array",
"items": {"type": "string"},
"maxItems": 10,
"uniqueItems": true
}
}
- Naming Conventions:
- Use camelCase for attribute names
- Avoid special characters except underscore
- Keep names descriptive but concise
- Group related attributes under parent objects
- Don’t exceed 5 nesting levels
- Schema Design Tips:
- Plan for future extensibility
- Use required fields sparingly (allows partial updates)
- Include description fields for documentation
- Define sensible default values where applicable
- Consider index requirements for searchable fields
For your specific import issue:
- Update Device Type Schema:
PUT /api/v0002/device/types/AssetTracker
{
"customAttributes": {
"type": "object",
"properties": {
"location": {
"type": "object",
"properties": {
"lat": {"type": "number"},
"lng": {"type": "number"}
}
}
}
}
}
- Format CSV Correctly:
deviceId,deviceType,customAttributes.location.lat,customAttributes.location.lng
DEV-0001,AssetTracker,40.7128,-74.0060
DEV-0002,AssetTracker,34.0522,-118.2437
- Validate Before Import:
Test with a 10-device subset first:
curl -X POST https://platform.ibm.com/api/v0002/bulk/devices/import \
-H "Authorization: Bearer $TOKEN" \
-F "file=@test_devices.csv"
- Monitor Import Progress:
The API returns a job ID - poll for completion:
GET /api/v0002/bulk/devices/import/{jobId}
Check for detailed error messages if validation fails. The response includes the specific row and field causing issues.