...
Table of Contents | ||
---|---|---|
|
Required Headers
Authorization: Bearer <your_auth_token>
Content-Type: application/json
Content-Encoding: gzip
X-File-Content-Classification: Insights.UnityProjects
X-File-Content-Length: <original_file_size_in_bytes>
X-File-Content-MD5: <MD5_hash_of_original_file>
X-File-Name: <original_file_name.json>
Valid Header Values
...
X-File-Content-Classification: Insights.UnityProjects - A classification to help us track the source of this data.
...
X-File-Content-Length: A positive integer representing the size of the original (uncompressed) JSON file in bytes
...
X-File-Content-MD5: The MD5 hash of the original (uncompressed) JSON file
...
Overview
The File Upload API enables secure transmission of structured data files to our platform. It supports various file formats including JSON, CSV, XML, and YAML in both raw and compressed (gzip) formats. This API is designed for data migration and integration, providing an efficient pathway for transferring data into our system.
API Endpoint
Code Block |
---|
POST https://api.[opsera-org].opsera.io/data-migration-file/data/upload |
Opsera API Token Generation
From within the Opsera portal, follow these steps to generate an API token if you don't already have one.
Login to the HW Sandbox Portal: https://portal.honeywell-sandbox.opsera.io/ Opsera portal.
Access User Profile: Click on your user avatar or profile picture at the top-right corner of the dashboard.
Navigate to API Tokens: Select "API Tokens" or "Personal Access Tokens" from the profile settings menu.
Create a New API Token: Click on the "Create New Token" button and provide a name for the token.
Define Permissions: Choose the appropriate permissions or scopes for the token.
Generate and Save the Token: Click "Generate Token" and securely store the displayed token.
For more information please see: https://docs.opsera.io/api-platform-and-integration/opsera-api-platform/personal-access-tokens
Steps to Test Using cURL
Prepare your JSON file (e.g., "data.json").
Compress the file using gzip:
Code Block |
---|
gzip -c data.json > data.json.gz |
Calculate the MD5 hash and file size of the original JSON file:
Code Block |
---|
original_md5=$(md5sum data.json | cut -d ' ' -f 1)
original_size=$(wc -c < data.json) |
Use the following curl command to upload the file (replace placeholders with your actual values):
...
Authentication
All requests require authentication using a bearer token.
Obtain an API token from the Opsera portal
Include the token in the
Authorization
headerCode Block Authorization: Bearer <your_token>
Required Headers
Header | Description | Required | Example |
---|---|---|---|
| Bearer token for authentication | Yes |
|
| Media type of the file being uploaded | Yes |
|
| Size of the file in bytes | Yes |
|
| MD5 hash of the file for integrity verification | Yes |
|
| Name of the file being uploaded | Yes |
|
| Classification category for the uploaded content | Yes |
|
| Encoding of the file content (for compressed files) | Only for compressed files |
|
Content Classification
The X-File-Content-Classification
header specifies the category of data being uploaded. Please contact your Opsera account representative for the appropriate classification value for your use case.
Supported File Types
File Type | Content-Type Header |
---|---|
JSON |
|
CSV |
|
XML |
|
YAML |
|
Gzipped JSON |
|
Gzipped CSV |
|
Gzipped XML |
|
Gzipped YAML |
|
Request Body
The request body should contain the raw file content as binary data.
File Validation
The API performs the following validations:
The content type is checked against supported formats
The file size is validated against the provided
X-File-Content-Length
The MD5 hash is verified against the provided
X-File-Content-MD5
The file content is validated for correctness based on the content type
Response
A successful upload will return a 200 OK response with the following JSON structure:
Code Block | ||
---|---|---|
| ||
{
"id": "artifactId",
"contentLength": 42768,
"contentMD5": "d41d8cd98f00b204e9800998ecf8427e"
} |
Description of Response Attributes
id: A string representing the unique identifier (artifactId) assigned to the uploaded file. This ID can be used for future references or operations related to this file.
contentLength: A number indicating the size of the original (uncompressed) file in bytes. This should match the value you provided in the X-File-Content-Length header.
contentMD5: A string containing the MD5 hash of the original (uncompressed) file. This should match the value you provided in the X-File-Content-MD5 header.
Error Codes
Status | Description |
---|---|
200 | Successful upload |
400 | Bad request - invalid content type, content length, MD5, or payload |
403 | Forbidden - invalid authentication |
500 | Server error |
Examples
Uploading a JSON File
Code Block | ||
---|---|---|
| ||
curl -X POST "https://api.opsera-test.opsera.io/data-migration-file/data/upload" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "X-File-Content-Classification: Insights.UnityProjects" \
-H "X-File-Content-Length: 2048" \
-H "X-File-Content-MD5: b5d4ee21f9d850e1358744c1ea0434bb" \
-H "X-File-Name: project_data.json" \
--data-binary "@/path/to/project_data.json" |
Uploading a CSV File
Code Block | ||
---|---|---|
| ||
curl -X POST "https://api.opsera-test.opsera.io/data-migration-file/data/upload" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: text/csv" \
-H "X-File-Content-Classification: Insights.UnityProjects" \
-H "X-File-Content-Length: 1536" \
-H "X-File-Content-MD5: 7a11e1cadbcd6c44c7a2d20fd440c1b0" \
-H "X-File-Name: metrics.csv" \
--data-binary "@/path/to/metrics.csv" |
Uploading a Compressed JSON File
Code Block | ||
---|---|---|
| ||
curl -X POST "https://api.honeywellopsera-sandboxtest.opsera.io/data-migration-file/data/upload" \ -H "Authorization: Bearer YOUR_AUTHAPI_TOKEN" \ -H "Content-Type: application/json" \ -H "Content-Encoding: gzip" \ -H "X-File-Content-Classification: Insights.UnityProjects" \ -H "X-File-Content-Length: $original_size4096" \ # Original uncompressed size -H "X-File-Content-MD5: $original_md5a3e75a566f32c4d542c9f71a15c15a6c" \ # MD5 of uncompressed content -H "X-File-Name: datalarge_dataset.json.gz" \ --data-binary "@data@/path/to/large_dataset.json.gz" |
Expected API Response
...
Code Block |
---|
{
"id": "string",
"contentLength": number,
"contentMD5": "string"
} |
Description of Response Attributes
id: A string representing the unique identifier (artifactId) assigned to the uploaded file. This ID can be used for future references or operations related to this file.
contentLength: A number indicating the size of the original (uncompressed) file in bytes. This should match the value you provided in the X-File-Content-Length header.
contentMD5: A string containing the MD5 hash of the original (uncompressed) file. This should match the value you provided in the X-File-Content-MD5 header.
Example Response
Code Block |
---|
❯ export AUTH_TOKEN="{auth token}"
❯ ./testGzippedJSONFileUpload.sh
Original JSON file size: 17934041
Original JSON file MD5 hash: d5ce63f2310d40ce14d7044764725e1a
Gzipped file size: 970511
Gzipped file MD5 hash: 1a0f877a9efb97d010d52155e0dd3778
Sending file: HCE-full.json.gz
Content-Length: 970511
X-File-Content-Length: 17934041
X-File-Content-MD5: d5ce63f2310d40ce14d7044764725e1a
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 947k 100 106 100 947k 40 363k 0:00:02 0:00:02 --:--:-- 363k
Response status code: 0
Response body:
{"id":"66cd1b866f255a5904fffed9","contentLength":17934041,"contentMD5":"d5ce63f2310d40ce14d7044764725e1a"}
ID: 66cd1b866f255a5904fffed9
Expected File Size: 17934041
Expected MD5: d5ce63f2310d40ce14d7044764725e1a
Upload successful! |
...
Uploading a Compressed CSV File
Code Block | ||
---|---|---|
| ||
curl -X POST "https://api.opsera-test.opsera.io/data-migration-file/data/upload" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: text/csv" \
-H "Content-Encoding: gzip" \
-H "X-File-Content-Classification: Insights.UnityProjects" \
-H "X-File-Content-Length: 3072" \ # Original uncompressed size
-H "X-File-Content-MD5: 1f4e6b8a2d0c3f5e7a9b1c8d2e5f6a7b" \ # MD5 of uncompressed content
-H "X-File-Name: historical_data.csv.gz" \
--data-binary "@/path/to/historical_data.csv.gz" |
Important Notes for All Uploads
The
X-File-Content-Length
header should represent the size in bytes of the original file contentThe
X-File-Content-MD5
should be the MD5 hash of the original file contentFor compressed files, these values should represent the uncompressed data
Important Notes for Compressed Files
When uploading compressed files:
The
Content-Type
header should reflect the type of the uncompressed content (e.g.,application/json
for a gzipped JSON file)Always include the
Content-Encoding: gzip
headerX-File-Content-Length
should be the size of the original uncompressed fileX-File-Content-MD5
should be the MD5 hash of the original uncompressed content
Sample Code
Node.js Example
Code Block | ||
---|---|---|
| ||
const axios = require('axios');
const fs = require('fs');
const crypto = require('crypto');
const zlib = require('zlib');
async function uploadFile(filePath, apiToken, isCompressed = false) {
// Read file content
const fileContent = fs.readFileSync(filePath);
const fileName = filePath.split('/').pop();
// Determine if we need to compress the data
let uploadContent = fileContent;
let originalContent = fileContent;
if (isCompressed) {
// If we're uploading a pre-compressed file, decompress it for MD5 calculation
if (fileName.endsWith('.gz')) {
originalContent = zlib.gunzipSync(fileContent);
} else {
// Compress the file for upload
uploadContent = zlib.gzipSync(fileContent);
originalContent = fileContent;
}
}
// Calculate MD5 hash of the original (uncompressed) content
const md5Hash = crypto.createHash('md5').update(originalContent).digest('hex');
// Determine content type based on file extension
let contentType;
if (fileName.endsWith('.json') || fileName.endsWith('.json.gz')) {
contentType = 'application/json';
} else if (fileName.endsWith('.csv') || fileName.endsWith('.csv.gz')) {
contentType = 'text/csv';
} else if (fileName.endsWith('.xml') || fileName.endsWith('.xml.gz')) {
contentType = 'application/xml';
} else if (fileName.endsWith('.yaml') || fileName.endsWith('.yml') ||
fileName.endsWith('.yaml.gz') || fileName.endsWith('.yml.gz')) {
contentType = 'application/yaml';
}
// Set headers
const headers = {
'Authorization': `Bearer ${apiToken}`,
'Content-Type': contentType,
'X-File-Content-Classification': 'Insights.UnityProjects',
'X-File-Content-Length': originalContent.length.toString(),
'X-File-Content-MD5': md5Hash,
'X-File-Name': fileName
};
// Add Content-Encoding header for compressed uploads
if (isCompressed || fileName.endsWith('.gz')) {
headers['Content-Encoding'] = 'gzip';
}
try {
// Upload file
const response = await axios.post(
'https://api.opsera-test.opsera.io/data-migration-file/data/upload',
uploadContent,
{ headers }
);
console.log('Upload successful:', response.data);
return response.data;
} catch (error) {
console.error('Upload failed:', error.response ? error.response.data : error.message);
throw error;
}
}
// Example usage
uploadFile('./data/project_data.json', 'YOUR_API_TOKEN', false)
.then(result => console.log('Done!'))
.catch(err => console.error('Error:', err)); |
Getting Help
If you encounter any issues not covered in this documentation, please contact our support team or open a ticket in the customer support portal.