Modern parcel tracking API built with ASP.NET Core, Entity Framework Core, and a layered architecture across API, application, domain, and infrastructure projects.
ParcelTracking is a backend service for registering shipments, tracking parcel progress, estimating deliveries, recording delivery confirmations, and exposing operational analytics.
- Versioned REST API via
Asp.Versioning - API key authentication using the
X-Api-Keyheader configured inApiKeyAuthenticationHandler - OpenAPI support plus Scalar API reference in development from
Program.cs - PostgreSQL persistence through
UseNpgsql() - FluentValidation integration from
Program.cs - Health checks, HTTP logging, response caching, and rate limiting from
Program.cs - Seed mode for local demo data through
DataSeeder.SeedAsync() - Unit and integration tests with
xUnitandTestcontainers
The solution is organized as a clean layered application in ParcelTracking.slnx.
ParcelTracking.API # HTTP endpoints, middleware, auth, OpenAPI
ParcelTracking.Application # business logic, DTOs, validators, services
ParcelTracking.Domain # entities and enums
ParcelTracking.Infrastructure # EF Core, PostgreSQL, migrations, seeding
tests/ # unit and integration tests
- Register parcels via
ParcelsController.Register() - Retrieve parcel details via
ParcelsController.GetById() - Search parcels with filtering and pagination via
ParcelsController.SearchParcels() - Update parcel status with JSON Patch via
ParcelsController.Patch()
- CRUD endpoints for shipper and recipient addresses in
AddressesController
- Add parcel events with
TrackingEventsController.Create() - Retrieve timeline history with
TrackingEventsController.GetEventHistory()
- Create delivery confirmations with
ParcelsController.CreateDeliveryConfirmation() - Calculate and recalculate delivery estimates with
DeliveryEstimateController.GetEstimate()andDeliveryEstimateController.Recalculate() - Delivery confirmation logic updates parcel state in
DeliveryConfirmationService.CreateAsync()
- Parcel counts by status via
AnalyticsController.GetParcelCountByStatus() - Delivery performance reporting via
AnalyticsController.GetDeliveryPerformance() - Liveness and readiness probes exposed in
Program.cs
.NET 10fromParcelTracking.API.csprojASP.NET Core Web APIEntity Framework CorePostgreSQLviaNpgsqlFluentValidationOpenAPI+ScalarxUnit,FluentAssertions,MoqDotNet.Testcontainersfor integration testing
- .NET 10 SDK
- PostgreSQL 15+ running locally or remotely
- Optional: Docker for test and local database workflows
Development settings are defined in appsettings.Development.json.
Example development values:
- Connection string:
Host=localhost;Port=5432;Database=parceltracking;Username=parcel;Password=parcel123 - API key:
dev-test-key-12345
dotnet restore
dotnet run --project ParcelTracking.APIIn development, the API enables OpenAPI and Scalar through app.MapOpenApi() and app.MapScalarApiReference().
Use the built-in seed mode implemented in Program.cs:
dotnet run --project ParcelTracking.API -- --seedThis populates the database with sample addresses, parcels, tracking events, content items, delivery confirmations, and parcel watchers using DataSeeder.
Most endpoints require authorization through the X-Api-Key header as configured in Program.cs.
Example request header:
X-Api-Key: dev-test-key-12345API controllers use versioned routes such as [Route("api/v{version:apiVersion}/[controller]")].
Typical base URL:
https://localhost:{port}/api/v1
| Area | Endpoint | Description |
|---|---|---|
| Parcels | POST /api/v1/Parcels |
Register a parcel |
| Parcels | GET /api/v1/Parcels/{id} |
Get parcel details |
| Parcels | GET /api/v1/Parcels |
Search parcels |
| Parcels | PATCH /api/v1/Parcels/{id} |
Update status with JSON Patch |
| Parcels | POST /api/v1/Parcels/{trackingNumber}/delivery-confirmation |
Record delivery confirmation |
| Addresses | GET /api/v1/Addresses |
List addresses |
| Addresses | POST /api/v1/Addresses |
Create address |
| Tracking | GET /api/v1/parcels/{parcelId}/events |
Parcel event history |
| Tracking | POST /api/v1/parcels/{parcelId}/events |
Add tracking event |
| Estimates | GET /api/v1/DeliveryEstimate?id={parcelId} |
Get delivery estimate |
| Estimates | PUT /api/v1/DeliveryEstimate/recalculate?id={parcelId} |
Recalculate estimate |
| Analytics | GET /api/v1/Analytics/parcel-count-by-status |
Status breakdown |
| Analytics | GET /api/v1/Analytics/delivery-performance |
Delivery performance metrics |
| Health | GET /health |
Aggregated health report |
| Health | GET /health/live |
Liveness probe |
| Health | GET /health/ready |
Readiness probe |
The API includes several production-oriented capabilities configured in Program.cs:
- Problem details responses for errors
- Custom exception handlers
- HTTP request/response logging
- CORS policy split by environment
- Response caching for analytics and real-time endpoints
- Fixed-window rate limiting with
429 Too Many Requests
The repository contains both unit and integration tests, with additional notes in tests/README.md.
dotnet test ParcelTracking.slnxdotnet test tests/ParcelTracking.Application.Testsdotnet test tests/ParcelTracking.API.IntegrationTestsIntegration tests use PostgreSQL and DotNet.Testcontainers, while unit tests use the EF Core in-memory provider in ParcelTracking.Application.Tests.csproj.
- Development secrets should not be committed; sensitive config files are ignored in
.gitignore. - Current configuration is optimized for development visibility, including SQL logging and sensitive data logging in
Program.cs. - The project already generates XML API documentation from
ParcelTracking.API.csproj, which helps keep OpenAPI output descriptive.