Using AWS Lambda & API Gateway (Node.js & Python)
To use the CubeMaster API, you need an API key (TokenID) for authentication. Here's how to get started:
TokenID (e.g., abc123xyz789). Copy this key and store it securely, as it will be used in the HTTP headers of your API requests.Note: The TokenID will be used in the HTTP headers of your POST request for authentication.
A RESTful API (Representational State Transfer) is a way for systems to communicate over the internet using standard HTTP methods like GET, POST, PUT, and DELETE. Here’s a quick breakdown:
https://api.cubemaster.net/loads) where the API can be accessed.POST: Create a new resource (e.g., build a load in CubeMaster).GET: Retrieve data.In this guide, we’ll use the POST method to send a JSON payload to https://api.cubemaster.net/loads to build a load.
You’ll use AWS Lambda to make the API call. Here’s how to set it up:
Assume your customer’s orders or shipments data is stored in a legacy database (e.g., MySQL on AWS RDS). Here’s how to fetch it:
my-db-instance.xxx.us-east-1.rds.amazonaws.com) and Port.npm install mysql (for Node.js).const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'my-db-instance.xxx.us-east-1.rds.amazonaws.com',
user: 'admin',
password: 'yourpassword',
database: 'legacy_db'
});
exports.handler = async (event) => {
return new Promise((resolve, reject) => {
connection.query('SELECT name, length, width, height, weight, qty FROM shipments', (err, results) => {
if (err) reject(err);
resolve(results); // e.g., [{name: "ITEM001", length: 72, width: 30, height: 75, weight: 1002.45, qty: 16}, ...]
});
});
};
Cargoes array format in the next step.Now, integrate the database data into the API request and send it to CubeMaster:
axios package for HTTP requests:
npm install axios
const axios = require('axios');
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'my-db-instance.xxx.us-east-1.rds.amazonaws.com',
user: 'admin',
password: 'yourpassword',
database: 'legacy_db'
});
exports.handler = async (event) => {
const shipments = await new Promise((resolve, reject) => {
connection.query('SELECT name, length, width, height, weight, qty FROM shipments', (err, results) => {
if (err) reject(err);
resolve(results);
});
});
const requestBody = {
"Title": "New Mixed Truck Load",
"Description": "Hello Web API",
"Cargoes": shipments.map(item => ({
"Name": item.name,
"Length": item.length,
"Width": item.width,
"Height": item.height,
"Weight": item.weight,
"OrientationsAllowed": "OrientationsAll",
"TurnAllowedOnFloor": false,
"Qty": item.qty,
"ColorKnownName": "Brown"
})),
"Containers": [
{
"VehicleType": "Dry",
"Name": "53FT-Intermodal",
"Length": 630,
"Width": 98,
"Height": 106,
"ColorKnownName": "Blue"
}
],
"Rules": {
"IsWeightLimited": true,
"IsSequenceUsed": false,
"FillDirection": "FrontToRear",
"CalculationType": "MixLoad"
}
};
const response = await axios.post('https://api.cubemaster.net/loads', requestBody, {
headers: {
'TokenID': 'abc123xyz789', // Replace with your actual TokenID
'Content-Type': 'application/json'
}
});
return response.data;
};
{
"Title": "New Mixed Truck Load",
"Description": "Hello Web API",
"Cargoes": [
{
"Name": "ITEM001",
"Length": 72,
"Width": 30,
"Height": 75,
"Weight": 1002.45,
"OrientationsAllowed": "OrientationsAll",
"TurnAllowedOnFloor": false,
"Qty": 16,
"ColorKnownName": "Brown"
},
{
"Name": "ITEM002",
"Length": 27.31,
"Width": 37.5,
"Height": 76.67,
"Weight": 521.45,
"OrientationsAllowed": "OrientationsAll",
"TurnAllowedOnFloor": false,
"Qty": 28,
"ColorKnownName": "Aqua"
},
{
"Name": "SKU0005",
"Length": 27.31,
"Width": 9.5,
"Height": 75.67,
"Weight": 501.45,
"OrientationsAllowed": "OrientationsAll",
"TurnAllowedOnFloor": true,
"Qty": 24,
"ColorKnownName": "Beige"
},
{
"Name": "SKU0005",
"Qty": 23
},
{
"Name": "SKU0008",
"Qty": 34
}
],
"Containers": [
{
"VehicleType": "Dry",
"Name": "53FT-Intermodal",
"Length": 630,
"Width": 98,
"Height": 106,
"ColorKnownName": "Blue"
}
],
"Rules": {
"IsWeightLimited": true,
"IsSequenceUsed": false,
"FillDirection": "FrontToRear",
"CalculationType": "MixLoad"
}
}
The API will return a detailed response. Here’s how to process it:
status field:
"succeed", proceed to extract data.message and calculationError for debugging.loadSummary (e.g., cargoesLoaded, volumeLoaded) and filledContainers (e.g., volumeUtilization).const AWS = require('aws-sdk');
const s3 = new AWS.S3();
exports.handler = async (event) => {
// ... (previous code for API call)
const responseData = response.data;
if (responseData.status === 'succeed') {
await s3.putObject({
Bucket: 'cubemaster-responses',
Key: `load-${Date.now()}.json`,
Body: JSON.stringify(responseData),
ContentType: 'application/json'
}).promise();
} else {
console.error('Error:', responseData.message, responseData.calculationError);
}
return responseData;
};
{
"status": "succeed",
"message": "Engine created. 5 cargoes. 1 empty containers. Calculation started. Calculation ended. The load built successfully. The load saved to the cloud database.",
"calculationError": "InvalidCargoSize",
"document": {
"title": "New Mixed Truck Load",
"description": "Hello Web API",
"isShared": true,
"isAutoSaved": true,
"isPending": false,
"calculationTimeInSeconds": 0.6152743,
"processId": "",
"batchId": "",
"createdBy": "CHANG@LOGEN.CO.KR",
"createdAt": "2023-02-11T01:17:01.7392204+09:00",
"updatedAt": "0001-01-01T00:00:00"
},
"loadSummary": {
"cargoesLoaded": 68,
"piecesLoaded": 68,
"cargoesLeft": 0,
"piecesLeft": 57,
"unitloadsLoaded": 0,
"volumeLoaded": 5261723.4606,
"weightLoaded": 42674.59999999999,
"priceLoaded": 0,
"containersLoaded": 1
},
"filledContainers": [
{
"name": "#1 53FT-Intermodal",
"sequence": 1,
"loadSummary": {
"cargoesLoaded": 68,
"piecesLoaded": 68,
"unitloadsLoaded": 0,
"volumeLoaded": 5261723.4606,
"volumeUtilization": 80.39990374424703,
"vollumeUtilizationToLoadHeight": 81.03441853085657,
"floorLoaded": 57090.75,
"floorUtilization": 92.46963070942662,
"weightLoaded": 42674.59999999999,
"weightTotal": 42674.59999999999,
"weightUtilization": 0,
"dimWeight": 39424.33734939759,
"priceLoaded": 0,
"pricetUtilization": 0,
"cargoesPerLayer": 14,
"layersPerUnitload": 0
},
"actualSize": {
"length": 630,
"width": 98,
"height": 106
},
"loadSize": {
"length": 625.6499999999999,
"width": 97.5,
"height": 105.17
},
"graphics": {
"images": {
"path3DDiagram": "https://api.cubemaster.net/runtimes/b28413ca_51ed_44c9_b92e_13147363fd61.PNG",
"pathComposite": "https://api.cubemaster.net/runtimes/7eb09974_2f1d_41bc_9371_2002658dce07.PNG"
}
}
}
]
}
Use AWS CloudWatch to monitor and debug your API calls:
/aws/lambda/CubeMasterLoadBuilder.InvalidCargoSize from calculationError).Invocations, Errors, and Duration.{}), and run it.