Step-by-Step Guide to Consume CubeMaster API with C#

This guide walks you through integrating the CubeMaster API (https://api.cubemaster.net) using C# and RestSharp, focusing on the /loads endpoint with POST method.

To use the CubeMaster API, you need an API key (TokenID) for authentication. Here's how to get started:

  1. Visit the CubeMaster website: https://cubemaster.net.
  2. Locate the "Sign In" option (typically found in the top-right corner).
  3. Fill out the registration form with your details (e.g., name, email, password, company information).
  4. After signing up, log in to your account dashboard.
  5. Navigate to the "Settings" - "Integration" section to generate your API key (TokenID).
  6. Generate an API key. Once generated, you’ll receive a unique TokenID (e.g., abc123xyz789). Copy this key and store it securely, as it will be used in the HTTP headers of your API requests.
  7. Copy the TokenID and store it securely (e.g., in a configuration file or environment variable in your C# project).

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 applications to communicate over the internet using standard HTTP methods like GET, POST, PUT, and DELETE. Here’s a simple breakdown:

  • Endpoints: URLs (e.g., https://api.cubemaster.net/loads) that represent resources (like "loads" in this case).
  • HTTP Methods: Actions you can perform:
    • POST: Create a new resource (e.g., build a load).
    • GET: Retrieve data.
  • JSON: A lightweight data format used to send and receive data (like the request and response in this guide).
  • Headers: Extra info sent with the request (e.g., your TokenID for authentication).

In this guide, we’ll use the POST method to send a JSON payload to /loads to create a load plan, authenticated via a TokenID in the headers.

Create a new C# project and add RestSharp:

  1. Open Visual Studio (e.g., 2022).
  2. Click File > New > Project.
  3. Select Console App (.NET Framework) or Console App (.NET Core), name it (e.g., "CubeMasterClient"), and click Create.
  4. Install RestSharp via NuGet:
    • Go to Tools > NuGet Package Manager > Package Manager Console.
    • Run: Install-Package RestSharp.
  5. Install Newtonsoft.Json for JSON handling:
    • Run: Install-Package Newtonsoft.Json.

Your project is now ready with RestSharp for API calls and Newtonsoft.Json for JSON serialization.

Assume your customer’s legacy database stores order/shipment data (e.g., items, dimensions, quantities). Here’s how to fetch it:

using System.Data.SqlClient;
using System.Collections.Generic;

public class CargoItem
{
    public string Name { get; set; }
    public double Length { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public double Weight { get; set; }
    public int Qty { get; set; }
    public string ColorKnownName { get; set; }
}

public List<CargoItem> GetCargoFromDatabase()
{
    var cargoItems = new List<CargoItem>();
    string connectionString = "Server=your_server;Database=your_db;User Id=your_user;Password=your_pass;";
    
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        string query = "SELECT ItemName, Length, Width, Height, Weight, Quantity, Color FROM Orders";
        using (SqlCommand cmd = new SqlCommand(query, conn))
        {
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    cargoItems.Add(new CargoItem
                    {
                        Name = reader["ItemName"].ToString(),
                        Length = (double)reader["Length"],
                        Width = (double)reader["Width"],
                        Height = (double)reader["Height"],
                        Weight = (double)reader["Weight"],
                        Qty = (int)reader["Quantity"],
                        ColorKnownName = reader["Color"].ToString()
                    });
                }
            }
        }
    }
    return cargoItems;
}

This code connects to a SQL Server database and maps order data to a CargoItem class, which we’ll use in the API request.

Build the request with data from the database and the provided JSON structure:

using RestSharp;
using Newtonsoft.Json;
using System;

public class Program
{
    static void Main(string[] args)
    {
        string apiKey = "your_token_id_here"; // Replace with your TokenID
        var client = new RestClient("https://api.cubemaster.net");
        var request = new RestRequest("/loads", Method.Post);

        // Add authentication header
        request.AddHeader("TokenID", apiKey);
        request.AddHeader("Content-Type", "application/json");

        // Get cargo data from legacy database
        var cargoItems = new Program().GetCargoFromDatabase();

        // Build request payload
        var payload = new
        {
            Title = "New Mixed Truck Load",
            Description = "Hello Web API",
            Cargoes = cargoItems.Select(item => new
            {
                item.Name,
                item.Length,
                item.Width,
                item.Height,
                item.Weight,
                OrientationsAllowed = "OrientationsAll",
                TurnAllowedOnFloor = false,
                item.Qty,
                item.ColorKnownName
            }).ToList(),
            Containers = new[]
            {
                new
                {
                    VehicleType = "Dry",
                    Name = "53FT-Intermodal",
                    Length = 630,
                    Width = 98,
                    Height = 106,
                    ColorKnownName = "Blue"
                }
            },
            Rules = new
            {
                IsWeightLimited = true,
                IsSequenceUsed = false,
                FillDirection = "FrontToRear",
                CalculationType = "MixLoad"
            }
        };

        // Serialize to JSON
        string jsonPayload = JsonConvert.SerializeObject(payload);
        request.AddParameter("application/json", jsonPayload, ParameterType.RequestBody);

        // Execute the request
        var response = client.Execute(request);

        // Handle response (next step)
        new Program().HandleApiResponse(response);
    }

    // Reuse GetCargoFromDatabase from Step 4
    public List<CargoItem> GetCargoFromDatabase() { /* Implementation from Step 4 */ }

    public void HandleApiResponse(RestResponse response) { /* Implementation in Step 6 */ }
}

Request JSON:

{
    "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 RestClient and RestRequest objects from RestSharp handle the HTTP request, with the TokenID added to the headers for authentication.

Process the API response to display or log results:

public void HandleApiResponse(RestResponse response)
{
    if (response.IsSuccessful)
    {
        var responseData = JsonConvert.DeserializeObject<dynamic>(response.Content);
        Console.WriteLine("Status: " + responseData.status);
        Console.WriteLine("Message: " + responseData.message);

        // Extract key details
        var loadSummary = responseData.loadSummary;
        Console.WriteLine($"Cargoes Loaded: {loadSummary.cargoesLoaded}");
        Console.WriteLine($"Volume Loaded: {loadSummary.volumeLoaded}");
        Console.WriteLine($"Weight Loaded: {loadSummary.weightLoaded}");

        // Display image links if available
        var images = responseData.filledContainers[0].graphics.images;
        Console.WriteLine("3D Diagram: " + images.path3DDiagram);
    }
    else
    {
        Console.WriteLine($"Error: {response.StatusCode} - {response.ErrorMessage}");
        Console.WriteLine($"Response Content: {response.Content}");
    }
}

Response JSON:

{
    "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"
                }
            }
        }
    ]
}

This step checks if the response is successful (HTTP 200), deserializes the JSON, and extracts key fields like status, message, and load summary. Errors are logged with status codes and content for debugging.

Use these techniques to monitor and debug your API integration:

  1. Logging: Add logging with a library like Serilog:
    using Serilog;
    
    Log.Logger = new LoggerConfiguration()
        .WriteTo.Console()
        .WriteTo.File("logs/api.log")
        .CreateLogger();
    
    Log.Information("Request sent: {JsonPayload}", jsonPayload);
    Log.Information("Response received: {ResponseContent}", response.Content);
    
  2. Visual Studio Debugger:
    • Set a breakpoint (F9) on var response = client.Execute(request);.
    • Press F5 to start debugging, then step through (F10/F11) to inspect variables.
  3. RestSharp Debugging: Enable request/response logging:
    client.RestClientOptions.ThrowOnAnyError = true; // Throw exceptions on errors
    Console.WriteLine("Request Headers: " + string.Join(", ", request.Parameters.Where(p => p.Type == ParameterType.HttpHeader)));
    Console.WriteLine("Response Headers: " + string.Join(", ", response.Headers));
    
  4. Postman: Test the API separately by sending the JSON request to https://api.cubemaster.net/loads with the TokenID header to verify behavior.

These tools help you track requests, responses, and errors effectively.