.NET libraries for logistics carrier APIs. Currently supports DHL (Shipping, Tracking, Pickup, Returns, Internetmarke, Location Finder) and GO! Express (Shipping, Tracking) — all targeting .NET 8, 9, and 10.
Feature highlights:
- Carrier-agnostic abstractions (
IShipmentService,ITrackingService) for multi-carrier support - DHL Parcel DE Shipping API v2 — create, validate, cancel shipments, manifests
- DHL Parcel DE Tracking (XML v0) and Unified Tracking (JSON) with signature retrieval
- DHL Pickup API v3 — create, cancel, and query pickup orders
- DHL Returns API v1 — create return orders, list return locations
- DHL Internetmarke/Portokasse API v1 — stamps, catalog, wallet, cart checkout
- DHL Unified Location Finder v1 — search by address, geo-coordinates, or keyword
- GO! Express Shipping — create, cancel shipments, label generation
- GO! Express Tracking — track shipments
- Builder-pattern DI registration with typed
HttpClientpipeline - OAuth ROPC, API key, and Basic Auth — handled automatically per carrier
- Sandbox support for DHL and GO! Express
- .NET 8.0, 9.0, or 10.0
- A DHL developer account and/or GO! Express credentials
# Individual packages
dotnet add package Parcel.NET.Dhl.Shipping
dotnet add package Parcel.NET.Dhl.Tracking
dotnet add package Parcel.NET.GoExpress.Shipping
# Or install everything for a carrier
dotnet add package Parcel.NET.Dhl.All
dotnet add package Parcel.NET.GoExpress.All
# Or install all carriers at once
dotnet add package Parcel.NET.Allbuilder.Services.AddDhl(options =>
{
options.ApiKey = "your-api-key";
options.ApiSecret = "your-api-secret";
options.Username = "your-username";
options.Password = "your-password";
options.UseSandbox = true;
})
.AddDhlShipping()
.AddDhlTracking()
.AddDhlUnifiedTracking()
.AddDhlPickup()
.AddDhlReturns()
.AddDhlInternetmarke()
.AddDhlLocationFinder();builder.Services.AddGoExpress(options =>
{
options.Username = "your-username";
options.Password = "your-password";
options.CustomerId = "1234567";
options.ResponsibleStation = "FRA";
options.UseSandbox = true;
})
.AddGoExpressShipping()
.AddGoExpressTracking();Use the carrier-agnostic IShipmentService or the carrier-specific client:
var shippingService = serviceProvider.GetRequiredService<IShipmentService>();
var request = new DhlShipmentRequest
{
BillingNumber = "33333333330101",
Product = DhlProduct.V01PAK,
Shipper = new Address
{
Name = "Max Mustermann",
Street = "Musterstraße",
HouseNumber = "1",
PostalCode = "53113",
City = "Bonn",
CountryCode = "DEU"
},
Consignee = new Address
{
Name = "Erika Musterfrau",
Street = "Berliner Straße",
HouseNumber = "42",
PostalCode = "10117",
City = "Berlin",
CountryCode = "DEU"
},
Packages = [new Package { Weight = 2.5 }]
};
var response = await shippingService.CreateShipmentAsync(request);
Console.WriteLine($"Shipment: {response.ShipmentNumber}");var trackingService = serviceProvider.GetRequiredService<ITrackingService>();
var result = await trackingService.TrackAsync("00340434161094042557");
Console.WriteLine($"Status: {result.Status}");
foreach (var evt in result.Events)
{
Console.WriteLine($" {evt.Timestamp}: {evt.Description} ({evt.Location})");
}IDhlShippingClient extends the carrier-agnostic IShipmentService with DHL-specific operations:
var dhlClient = serviceProvider.GetRequiredService<IDhlShippingClient>();
// Validate before creating
var validation = await dhlClient.ValidateShipmentAsync(request);
if (validation.Valid)
{
var response = await dhlClient.CreateShipmentAsync(request);
}
// Create daily closing manifest
var manifest = await dhlClient.CreateManifestAsync();Two tracking clients are available:
| Client | API | Format | Sandbox |
|---|---|---|---|
IDhlTrackingClient |
Parcel DE Tracking v0 | XML | Yes |
IDhlUnifiedTrackingClient |
Unified Tracking | JSON | No |
// Parcel DE Tracking with signature retrieval
var trackingClient = serviceProvider.GetRequiredService<IDhlTrackingClient>();
var result = await trackingClient.TrackAsync("00340434161094042557");
var signature = await trackingClient.GetSignatureAsync("00340434161094042557");
// Unified Tracking (JSON)
var unifiedClient = serviceProvider.GetRequiredService<IDhlUnifiedTrackingClient>();
var result = await unifiedClient.TrackAsync("00340434161094042557");var pickupClient = serviceProvider.GetRequiredService<IDhlPickupClient>();
var order = await pickupClient.CreatePickupOrderAsync(new PickupOrderRequest { /* ... */ });
var details = await pickupClient.GetPickupOrderAsync(order.OrderNumber);
await pickupClient.CancelPickupOrderAsync(order.OrderNumber);var returnsClient = serviceProvider.GetRequiredService<IDhlReturnsClient>();
var returnOrder = await returnsClient.CreateReturnOrderAsync(new ReturnOrderRequest { /* ... */ });
var locations = await returnsClient.GetReturnLocationsAsync("DEU");var internetmarkeClient = serviceProvider.GetRequiredService<IDhlInternetmarkeClient>();
var userInfo = await internetmarkeClient.GetUserInfoAsync();
var catalog = await internetmarkeClient.GetCatalogAsync();
var balance = await internetmarkeClient.GetWalletBalanceAsync();
var cart = await internetmarkeClient.InitializeCartAsync(new CartRequest { /* ... */ });
var checkout = await internetmarkeClient.CheckoutCartAsync(cart.CartId);var locationFinder = serviceProvider.GetRequiredService<IDhlLocationFinderClient>();
var byAddress = await locationFinder.FindByAddressAsync("DEU", "Bonn", "53113");
var byGeo = await locationFinder.FindByGeoAsync(50.7374, 7.0982, 5000);
var location = await locationFinder.GetLocationByIdAsync("8003-4012221");var goClient = serviceProvider.GetRequiredService<IGoExpressShippingClient>();
var response = await goClient.CreateShipmentAsync(request);
var label = await goClient.GenerateLabelAsync(response.ShipmentNumber, GoExpressLabelFormat.Pdf);
await goClient.CancelShipmentAsync(response.ShipmentNumber);var trackingService = serviceProvider.GetRequiredService<ITrackingService>();
var result = await trackingService.TrackAsync("GO123456789");| Property | Description | Required |
|---|---|---|
ApiKey |
DHL API key (OAuth client_id) | Yes |
ApiSecret |
DHL API secret (OAuth client_secret) | For Shipping |
Username |
DHL ROPC username | For Shipping |
Password |
DHL ROPC password | For Shipping |
TrackingUsername |
Parcel DE Tracking credential | For Tracking (XML) |
TrackingPassword |
Parcel DE Tracking credential | For Tracking (XML) |
InternetmarkeUsername |
Internetmarke credential | For Internetmarke |
InternetmarkePassword |
Internetmarke credential | For Internetmarke |
UseSandbox |
Use sandbox environment | No |
| Property | Description | Required |
|---|---|---|
Username |
Basic Auth username | Yes |
Password |
Basic Auth password | Yes |
CustomerId |
Customer ID (max 7 chars) | Yes |
ResponsibleStation |
Station code (3 chars) | For Shipping |
UseSandbox |
Use sandbox environment | No |
Parcel.NET.Abstractions (IShipmentService, ITrackingService, models)
|
+-- Parcel.NET.Dhl (DhlOptions, DhlTokenService, auth handlers)
| +-- Dhl.Shipping (IDhlShippingClient)
| +-- Dhl.Tracking (IDhlTrackingClient)
| +-- Dhl.UnifiedTracking(IDhlUnifiedTrackingClient)
| +-- Dhl.Pickup (IDhlPickupClient)
| +-- Dhl.Returns (IDhlReturnsClient)
| +-- Dhl.Internetmarke (IDhlInternetmarkeClient)
| +-- Dhl.LocationFinder (IDhlLocationFinderClient)
|
+-- Parcel.NET.GoExpress (GoExpressOptions, auth handler)
+-- GoExpress.Shipping (IGoExpressShippingClient)
+-- GoExpress.Tracking (GoExpressTrackingClient)
All API errors throw typed exceptions:
try
{
var response = await shippingService.CreateShipmentAsync(request);
}
catch (ShippingException ex)
{
Console.WriteLine($"Status: {ex.StatusCode}, Error: {ex.ErrorCode}");
Console.WriteLine($"Raw response: {ex.RawResponse}");
}See CONTRIBUTING.md for build instructions, guidelines, and how to add new carriers.
MIT — see LICENSE for details.
