Midnight.SOAP.SDK 2.2.7

dotnet add package Midnight.SOAP.SDK --version 2.2.7
                    
NuGet\Install-Package Midnight.SOAP.SDK -Version 2.2.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Midnight.SOAP.SDK" Version="2.2.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Midnight.SOAP.SDK" Version="2.2.7" />
                    
Directory.Packages.props
<PackageReference Include="Midnight.SOAP.SDK" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Midnight.SOAP.SDK --version 2.2.7
                    
#r "nuget: Midnight.SOAP.SDK, 2.2.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Midnight.SOAP.SDK@2.2.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Midnight.SOAP.SDK&version=2.2.7
                    
Install as a Cake Addin
#tool nuget:?package=Midnight.SOAP.SDK&version=2.2.7
                    
Install as a Cake Tool

Midnight.SOAP.SDK

Overview

Midnight.SOAP.SDK is a .NET 8 library that provides a modern, strongly-typed interface for integrating with PrintReach's Midnight SOAP API. It simplifies authentication, request construction, and XML response parsing for all SOAP operations currently exposed. The SDK is designed for developers who need to interact with the Midnight API in a robust and maintainable way.

The SOAP API documentation from PrintReach can be found here in PDF format.


Features

  • Full Midnight SOAP API Wrapper: Retrieve, update, and insert any data supported by the Midnight SOAP API, including orders, inventory, customers, and more.
  • Strongly-Typed Requests: Uses strongly-typed request objects to ensure type safety and reduce runtime errors caused by string concatenated XML inputs.
  • Strongly-Typed Responses: Converts Midnight API XML response strings into strongly-typed C# models.
  • User-Defined Fields Support: The SDK provides a flexible UserDefinedFields class, where each UDF property (UDF1 to UDF30) is implemented using the UDFValue class. This allows each field to accept and serialize values as string, decimal, integer, date, or time, ensuring correct XML formatting for both requests and responses. The UDFValue class handles type conversion and serializes the value as the text content of the corresponding <UDF*> XML tag.
  • Testing : Includes comprehensive unit tests for all services and request/response objects, ensuring reliability and correctness.
  • Logging: Integrated logging for diagnostics and debugging using Serilog.

XML Serialization and Null Properties

Important:
To ensure correct XML serialization with the .NET XmlSerializer, nearly all properties in request objects are decorated with XmlElement(IsNullable=true). This approach ensures that when a property is not explicitly set, it will be serialized as xsi:nil="true" in the XML payload, except for Update requests. Update request bodies now implement the ShouldSerializeX method for XmlSerializer, which excludes fields from the rendered XML where the value was not explicitly set. This prevents unintended data from being sent to the Midnight SOAP API.

Disclaimer: In the past, particularly with Update methods of the Midnight SOAP API, we have found instances where even when not passing a field in the XML payload, that field's value can still be wiped out. We know for sure this happens with VendorUpdate.Terms, but if you experience any issues like this while using this SDK, please create an Issue in the GitHub repo and we will reach out to PrintReach for resolution.


Setup Instructions

Prerequisites

  • PrintReach Midnight MIS API access (developer token)
  • .NET 8 SDK
  • Visual Studio 2022 or later (recommended)
  • Serilog v4.3.0 or later for logging

Installation

Install-Package Midnight.SOAP.SDK

Usage

0. Soap Client Configuration

using Midnight.SOAP.SDK.Utilities;

var soapClient = SoapClient.Configure();

1. Service Initializations

using Midnight.SOAP.SDK;

var authService = new AuthenticationService(soapClient);
var customerService = new CustomerService(soapClient);
var customerContactService = new CustomerContactService(soapClient);
var djbService = new DJBService(soapClient);
var estimateService = new EstimateService(soapClient);
var inventoryItemService = new InventoryItemService(soapClient);
var inventoryService = new InventoryService(soapClient);
var jobCostingService = new JobCostingService(soapClient);
var orderService = new OrderService(soapClient);
var orderVersionService = new OrderVersionService(soapClient);
var orderVersionDetailService = new OrderVersionDetailService(soapClient);
var orderVersionDropService = new OrderVersionDropService(soapClient);
var orderVersionInventoryService = new OrderVersionInventoryService(soapClient);
var orderVersionPostageService = new OrderVersionPostageService(soapClient);

// ProofingService is the wrapper for "Request" api calls, making it clearer what the service is used for.
var proofingService = new ProofingService(soapClient);

var purchaseOrderService = new PurchaseOrderService(soapClient);
var settingsService = new SettingService(soapClient);
var venderService = new VendorService(soapClient);
var vendorContactService = new VendorContactService(soapClient);

2. Authentication

IMPORTANT: Never expose your developer token in client-side code or public repositories. Use a secrets manager or json configuration files that are in the .gitignore file

  • So long as your team has purchased API access from PrintReach for Midnight MIS, you can find your dev token in Admin Settings > Global Settings > Site Token.
var validationHeader = await authService.AuthenticateAsync("your-dev-token");

3. User Defined Fields Example

User Defined Fields (UDFs) are supported in all services that accept or return UDFs. The UserDefinedFields class contains properties for UDF1 to UDF30, each of which is of type UDFValue. The UDFValue class can hold values of different types (string, decimal, integer, date, time) and ensures proper serialization/deserialization to XML.

NOTE: In scenarios where only a portion of available UDFs are available to send in a request or receive in a response, those classes inherit either UserDefinedFields_Top10 or UserDefinedFields_Top5 classes.

using Midnight.SOAP.SDK.CommonObjects;

var customerInsertUDFs = new UserDefinedFields
{
    UDF7 = new UDFValue { Value = (decimal)0.999 }, // decimal type in Midnight UDF setup
    UDF11 = new UDFValue { Value = 12345 }, // csharp auto-recognizes this as an integer
    UDF1 = new UDFValue { Value = "testStringUDFInput" }, // csharp auto-recognizes this as a string 
    UDF5 = new UDFValue { Value = (decimal)999.00 } // currency-type field within Midnight UDF setup
};

var customerInsertResult = await customerService.CustomerInsertAsync(auth, new CustomerInsertRequestBody
{
    InputParameter = new CustomerInsertInputParameter
    {
        CustomerCode = "TESTCUSTOMER1234",
        CustomerName = "TEST CUSTOMER 123",
        UDF7 = customerInsertUDFs.UDF7,
        UDF11 = customerInsertUDFs.UDF11,
        UDF1 = customerInsertUDFs.UDF1,
        UDF5 = customerInsertUDFs.UDF5
    }
});

4. Retrieve Order Version List by Customer

A common thing that you might need to do is retrieve a list of customers, then for each customer retrieve a list of orders, and for each order retrieve a list of order versions to then update version details/drops/postage etc. Below is an example of how to accomplish this using the SDK.

using Midnight.SOAP.SDK;
using Midnight.SOAP.SDK.Utilities;
using Midnight.SOAP.SDK.CommonObjects;
using Midnight.SOAP.SDK.RequestObjects.CustomerInputs;
using Midnight.SOAP.SDK.RequestObjects.OrderInputs;
using Midnight.SOAP.SDK.RequestObjects.VersionInputs;


var soapClient = SoapClient.Configure();
var authService = new AuthenticationService(soapClient);
var customerService = new CustomerService(soapClient);
var orderService = new OrderService(soapClient);
var orderVersionService = new OrderVersionService(soapClient);
var validationHeader = await authService.AuthenticateAsync("your-dev-token");


var customerListInput = new CustomerListRequestBody { /* set properties */ };
var customerListResult = await customerService.CustomerListAsync(validationHeader, customerListInput);

foreach (var customer in customerListResult.Customers)
{
    var orderListInput = new OrderListRequestBody { /* set properties from customer */ };
    var orderListResult = await orderService.OrderListAsync(validationHeader, orderListInput); 

    // Error check result
    
    // filter orders as needed based on Result object
    var filteredOrders = orderListResult.Orders.Where(
        o => o.ProjectName.Contains("SomeFilter")).ToList();
    
    foreach (var order in filteredOrders.Orders)
    {
        var versionListInput = new OrderVersionListRequestBody { /* set properties from order */ };
        var versionListResult = await orderVersionService.OrderVersionListAsync(validationHeader, versionListInput);

        // Error check result

        foreach (var version in versionListResult.OrderVersions)
        {
            // Process each order version as needed
            // List/Update/Insert things like OrderVersionDetails, Drops, Inventory, Postage, etc.
        }
    }
}

5. Retrieve Entire Order and it's Versions, optionally also retrieve VersionDetails, VersionDrops, VersionInventory and VersionPostage

using Midnight.SOAP.SDK;
using Midnight.SOAP.SDK.Utilities;
using Midnight.SOAP.SDK.CommonObjects;
using Midnight.SOAP.SDK.RequestObjects.OrderInputs;

var soapClient = SoapClient.Configure();
var authService = new AuthenticationService(soapClient);
var orderService = new OrderService(soapClient);
var validationHeader = await authService.AuthenticateAsync("your-dev-token");

var entireOrder = await orderService.GetEntireOrderAsync(validationHeader, new EntireOrderRequestBody{
    OpenOrdersOnly = true, //optionally retrieve a closed order by setting this to false
    OrderNumber = "123456",
    IncludeServices = true, // order version details
    IncludeDrops = true,
    IncludeInventory = true,
    IncludePostage = true // order version postage
});

This is a new method that combines several other calls into a single method, as such there might well be issues we have not accounted for when using it. If you encounter a problem using it, please file an issue via GitHub.


Errors and Exceptions

The SDK uses a combination of exceptions and error messages within the result objects to indicate errors. The inheritance of CommonResult for all output objects ensures the ReturnCode and ReturnErrors object are consistently available across all service responses.

Error Example

...
    ReturnCode = -1, // Non-zero indicates an error
    ReturnErrors = 
    {
        Error = "Invalid authentication token." ,
        Error = "CustomerCode is required." 
    }
...

Exceptions

The SDK will throw exceptions immediately after a non-zero ReturnCode is detected in the response. The ReturnCode and ReturnErrors properties are logged when this occurs.

Exceptions Possible
  • ArgumentNullException: Thrown when a required parameter is null.
  • InvalidOperationException: Thrown when an operation is attempted that is not valid for the current state of the object.
  • AuthenticationException: Thrown when authentication fails.
  • Exception: Thrown for general errors that do not fit other categories.

Midnight API Rate Limiting Implemented

Overview

To maintain platform stability and ensure consistent performance for all Midnight customers, API rate limiting has been implemented for the Midnight API.

Why This Change Was Made

We identified API integrations generating significantly higher-than-expected request volumes. In some cases, this activity created enough load on backend database resources to impact overall system performance.

Because multiple customers may share the same infrastructure, excessive API traffic from a single integration can affect response times and performance for other customers. Rate limiting helps prevent these situations and protects the reliability of the platform.

Current Rate Limit

Midnight currently limits API traffic from a single IP address to approximately:

5,000 requests per 5-minute period

Requests exceeding this threshold will receive: HTTP 429 - Too Many Requests

Rate limit thresholds may be adjusted in the future as we continue to evaluate usage patterns and platform requirements.

What Happens When a Limit Is Reached?

If an application exceeds the allowed request rate, the API will temporarily reject additional requests and return an HTTP 429 response.

Applications should be designed to recognize and handle this response appropriately.

Customers integrating with the Midnight API should:

  • Handle HTTP 429 responses gracefully.
  • Implement retry logic when requests are temporarily rejected.
  • Use exponential backoff techniques when retrying requests.
  • Avoid repeatedly submitting the same request in rapid succession.
  • Filter data whenever possible to reduce the number of records being returned.
  • Synchronize incremental changes rather than repeatedly retrieving all available data.

Optimization Opportunities

Customers experiencing rate limiting may be able to significantly reduce API traffic by:

  • Filtering orders by date ranges.
  • Using modified-date fields to retrieve only changed records.
  • Limiting result sets to the data actually required.
  • Reviewing integration workflows that repeatedly request the same information.

Commit Message and Branch Naming Conventions

Conventional Commit Messages

All commit messages must follow the Conventional Commits specification, which is compatible with automated versioning tools like Versionize and GitVersion. Example formats:

  • feat!: add support for NuGet deploy and release
  • fix: correct null reference in authentication service
  • docs: update API usage section in README
  • refactor(service): simplify request logic
  • chore: update dependencies
  • test: add unit tests for AuthenticationService

Branch Naming Conventions

Branches must follow the enforced naming contract:

  • feature-new-api-integration
  • bugfix-fix-authentication-error
  • hotfix-critical-production-issue
  • docs-update-readme
  • refactor-service-layer
  • chore-update-dependencies
  • test-add-auth-tests
  • build-update-ci-workflow
  • release-v1.2.3
  • merge-main-into-feature

Branch names must match the pattern: ^(feature|bugfix|hotfix|docs|refactor|chore|test|experimental|build|release|merge)-[a-z0-9._-]+$

These conventions are enforced by git hooks and the CI/CD workflow to ensure consistency and compatibility with automated versioning and changelog generation.


Contributing

Contributions are welcome! Please fork the repository and submit a pull request.


License

This project is licensed under the MIT License.


Support

For questions or support, please open an issue on the repository.


Roadmap

The roadmap for Midnight.SOAP.SDK includes:

  • Remove Serilog dependency and replace with Microsoft.Extensions.Logging for better compatibility with ASP.NET Core applications.
  • Implement additional features as requested by the community.
  • Enhance documentation with more examples and use cases.

Midnight.SOAP.SDK makes integrating with the Midnight SOAP API fast, reliable, and developer-friendly.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.7 89 9/20/2026
2.2.6 102 8/27/2026
2.2.5 111 8/13/2026
2.2.4 92 8/13/2026
2.2.3 103 8/13/2026
2.2.2 104 8/10/2026
2.2.1 114 8/10/2026
2.2.0 110 8/10/2026
2.1.14 130 7/9/2026
2.1.13 127 6/17/2026
2.1.12 123 6/17/2026
2.1.11 125 6/4/2026
2.1.10 137 4/14/2026
2.1.9 125 4/14/2026
2.1.8 117 4/14/2026
2.1.7 111 4/14/2026
2.1.6 120 4/14/2026
2.1.5 125 2/10/2026
2.1.4 118 2/10/2026
2.1.3 232 11/4/2025
Loading failed