Using Azure Functions & Logic Apps (C# & .NET)
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 programs to talk to each other over the internet using standard HTTP methods, like POST, GET, PUT, and DELETE. Here’s a simple breakdown:
https://api.cubemaster.net/loads) where the API listens for requests.POST: Send data to create something (e.g., building a load in CubeMaster).GET: Retrieve data.In this guide, we’ll use the POST method to send load data to the CubeMaster API and get a response with the calculated load plan.
We’ll use Azure Functions to call the CubeMaster API. Here’s how to set it up:
CubeMasterIntegration) or use an existing one.CubeMasterFunction)..NET or Node.js (we’ll use .NET in this guide).Assume your customer’s legacy database stores orders or shipments data (e.g., in SQL Server). We’ll fetch this data to build the API request.
BuildLoad), and set Authorization level to Function. Click Create.LegacyDBConnection) with the value: Server=your-server;Database=your-db;User Id=your-user;Password=your-password;.using System.Data.SqlClient;
string connString = Environment.GetEnvironmentVariable("LegacyDBConnection");
using (SqlConnection conn = new SqlConnection(connString)) {
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT ItemName, Length, Width, Height, Weight, Quantity FROM Orders", conn);
SqlDataReader reader = cmd.ExecuteReader();
// Process data into JSON structure (see Step 5)
}
ItemName to Name, Quantity to Qty, etc., to match the CubeMaster API request format.Now, construct the POST request to https://api.cubemaster.net/loads using the data from the legacy database and the provided JSON structure.
BuildLoad), add the following C# code to send the request:
using System.Net.Http;
using System.Text;
[FunctionName("BuildLoad")]
public static async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
ILogger log)
{
var client = new HttpClient();
client.BaseAddress = new Uri("https://api.cubemaster.net/");
client.DefaultRequestHeaders.Add("TokenID", Environment.GetEnvironmentVariable("CubeMasterTokenID"));
string jsonRequest = @"{
""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""
}
}";
var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync("loads", content);
string responseContent = await response.Content.ReadAsStringAsync();
return new OkObjectResult(responseContent);
}
CubeMasterTokenID with your API key from Step 1.The CubeMaster API returns a detailed JSON response. Here’s how to process it:
using Newtonsoft.Json;
[FunctionName("BuildLoad")]
public static async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
ILogger log)
{
var client = new HttpClient();
client.BaseAddress = new Uri("https://api.cubemaster.net/");
client.DefaultRequestHeaders.Add("TokenID", Environment.GetEnvironmentVariable("CubeMasterTokenID"));
string jsonRequest = @"..."; // Same as Step 5
var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync("loads", content);
string responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode) {
dynamic result = JsonConvert.DeserializeObject(responseContent);
string status = result.status;
string message = result.message;
int cargoesLoaded = result.loadSummary.cargoesLoaded;
double volumeLoaded = result.loadSummary.volumeLoaded;
string diagramLink = result.filledContainers[0].graphics.images.path3DDiagram;
log.LogInformation($"Status: {status}, Message: {message}, Cargoes Loaded: {cargoesLoaded}, Volume: {volumeLoaded}");
return new OkObjectResult(new { Status = status, Message = message, Diagram = diagramLink });
} else {
log.LogError($"API Error: {response.StatusCode} - {responseContent}");
return new BadRequestObjectResult($"Error: {responseContent}");
}
}
{
"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
},
"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"
}
}
}
]
}
status, message, cargoesLoaded, and path3DDiagram for further use (e.g., display in a UI or store in a database).Ensure your integration works smoothly by monitoring and debugging:
log.LogInformation messages).InvalidCargoSize in the response), review the calculationError field and adjust the request JSON (e.g., verify cargo dimensions).Tip: Regularly check logs for issues like authentication failures (invalid TokenID) or network errors.