SauceCode.MyData 1.0.0

dotnet add package SauceCode.MyData --version 1.0.0
                    
NuGet\Install-Package SauceCode.MyData -Version 1.0.0
                    
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="SauceCode.MyData" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SauceCode.MyData" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="SauceCode.MyData" />
                    
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 SauceCode.MyData --version 1.0.0
                    
#r "nuget: SauceCode.MyData, 1.0.0"
                    
#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 SauceCode.MyData@1.0.0
                    
#: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=SauceCode.MyData&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=SauceCode.MyData&version=1.0.0
                    
Install as a Cake Tool

SauceCode.MyData

NuGet NuGet Downloads Run Tests GitHub

SauceCode.MyData is a .NET library that provides a robust client for integrating with the AADE MyData (Independent Authority for Public Revenue) invoicing platform in Greece. It is designed to be simple, resilient, and easy to integrate into modern .NET applications.


Features

  • Two access modes - MyDataErpClient for an entity transmitting its own documents, and MyDataProviderClient for a provider acting on behalf of its client entities.
  • Runtime environment selection - Target Sandbox or Production per call via a client factory, so one process can serve both without re-registering.
  • Per-call credentials - Credentials are passed on each call rather than bound at registration, so a single registered client can serve many tenants.
  • Built-in HTTP resilience - Per-attempt timeout, retry with exponential backoff, and a circuit breaker, each client isolated so one environment's outage can't trip another's breaker. Fully configurable.
  • Errors as exceptions, business outcomes as data - Transport/protocol failures throw MyDataException; AADE's per-item results (including partial rejections) come back to you as data.

Installation

Install via NuGet:

dotnet add package SauceCode.MyData

Or search for SauceCode.MyData on NuGet.org.


Quickstart

1. Register services

In Program.cs (or your startup), register the mode you need. Each call registers a client factory plus a named HttpClient per environment, each with its own resilience pipeline:

using SauceCode.MyData;

var builder = WebApplication.CreateBuilder(args);

// ERP mode (entity transmits its own documents):
builder.Services.AddMyDataErp();

// Provider mode (provider acts for client entities) — register either or both:
builder.Services.AddMyDataProvider();

var app = builder.Build();

Optionally tune the resilience behaviour (timeout, retry, circuit breaker) with a callback — see Resilience:

builder.Services.AddMyDataErp(options =>
{
    options.Timeout = TimeSpan.FromSeconds(5);
    options.MaxRetryAttempts = 3;
});

2. Create a client for an environment

Inject the factory and call Create with the target MyDataEnvironment. The returned client is bound to that environment; call Create again for the other environment — no second registration needed.

using SauceCode.MyData;
using SauceCode.MyData.Clients;

public class InvoiceService(IMyDataErpClientFactory factory)
{
    private readonly MyDataErpClient _client = factory.Create(MyDataEnvironment.Production);
    // ...
}

3. Submit invoices

Pass the caller's credentials on each call. SendInvoicesAsync returns AADE's per-item outcomes as a List<ResponseType>:

using SauceCode.MyData.Clients;
using SauceCode.MyData.Exceptions;
using SauceCode.MyData.Models;
using SauceCode.MyData.MyDataContracts;

public class InvoiceService(IMyDataErpClientFactory factory)
{
    private readonly MyDataErpClient _client = factory.Create(MyDataEnvironment.Production);

    public async Task SubmitAsync(InvoicesDoc invoices, CancellationToken ct)
    {
        var credentials = new MyDataErpCredential(
            username: "your-aade-user-id",         // sent as the aade-user-id header
            password: "your-subscription-key");    // sent as the ocp-apim-subscription-key header

        try
        {
            List<ResponseType> outcomes = await _client.SendInvoicesAsync(invoices, credentials, ct);

            foreach (var outcome in outcomes)
            {
                if (outcome.StatusCode == "Success")
                {
                    // Accepted — outcome.InvoiceMark is AADE's unique registration number (MARK).
                    Console.WriteLine($"Invoice {outcome.Index} registered as MARK {outcome.InvoiceMark}.");
                }
                else
                {
                    // Rejected — inspect the per-item errors (this is not an exception).
                    foreach (var error in outcome.Errors)
                        Console.WriteLine($"Invoice {outcome.Index} rejected: [{error.Code}] {error.Message}");
                }
            }
        }
        catch (MyDataException ex)
        {
            // Transport/protocol failure (non-success HTTP status, unreadable payload, transport error).
            Console.WriteLine($"MyData call failed ({(int)ex.StatusCode}): {ex.Message}");
            Console.WriteLine(ex.ErrorDetail is null ? ex.RawResponse : "See ex.ErrorDetail for parsed AADE detail.");
        }
    }
}

The same shape applies to the other ERP calls — SendIncomeClassificationAsync, SendExpensesClassificationAsync, and CancelInvoiceAsync(long mark, ...) — and to the Provider client's SendInvoicesAsync. Document retrieval (RequestTransmittedDocsAsync / RequestDocsAsync) takes a DocumentRetrievalQuery and returns the requested documents.

Error handling at a glance

Situation How it surfaces
Non-success HTTP status, empty/undeserializable body, or transport error throws MyDataException (StatusCode, RawResponse, best-effort parsed ErrorDetail)
Batch accepted, or partially rejected returns List<ResponseType> — check each item's StatusCode, Errors, and InvoiceMark

Per-item business outcomes are never signalled through an exception; a partially-rejected batch is a normal, successful call.


Resilience

Every HTTP call is wrapped in a per-client resilience pipeline. Each (mode, environment) pair gets its own pipeline instance, so a Sandbox outage can never trip the Production circuit breaker. Defaults reproduce the library's historical behaviour and can be overridden via the callback on AddMyDataErp / AddMyDataProvider (MyDataResilienceOptions):

Option Default Behaviour
Timeout 2 s Per-attempt timeout; a slower attempt is abandoned and counts as a transient failure.
MaxRetryAttempts 2 Retries after the initial attempt (3 attempts total), with exponential backoff and jitter.
RetryBaseDelay 200 ms Base delay for the backoff.
CircuitBreakerFailureThreshold 3 Failures within the sampling window that open the circuit.
CircuitBreakerBreakDuration 30 s How long the circuit stays open before a trial call.
CircuitBreakerSamplingDuration 30 s Rolling window over which failures are counted.

Transient failures (5xx, 408, timeouts, HttpRequestException) are retried and metered against the breaker. 429 Too Many Requests is deliberately not retried; other non-transient responses (400, 401, 404, …) pass through directly.


Versioning & AADE schema

The library follows Semantic Versioning. The generated XSD contracts are the public API, so an AADE schema change that alters a contract is a breaking (major) change — see the SemVer policy.

Each package records the AADE schema version its contracts target. Check it at runtime, or read the aade-schema-* tag on nuget.org:

Console.WriteLine(MyDataSchema.TargetedVersion); // e.g. "2.0.1"

The stable package tracks the production schema. Prerelease packages (e.g. 1.1.0-preview.1) are built from the ahead-of-production sandbox schema, so early adopters can test upcoming AADE changes before they go live.

Packages ship with SourceLink and a symbol package (snupkg on nuget.org), so you can step straight into the library's source while debugging.


License

This project is licensed under the PolyForm Noncommercial License 1.0.0.

Free usage

You may use this library for any personal, hobby, research, educational, or other non‑commercial purpose at no cost.

Examples of allowed free usage include:

  • Personal or hobby projects
  • Student or academic work
  • Non‑profit or research use
  • Internal evaluation or experimentation
  • Open‑source projects that are not used commercially

Commercial usage

A commercial license is required if you:

  • Use this library in a commercial product
  • Use it within a business or organization for revenue‑generating activities
  • Provide it as part of a paid service
  • Use it in production environments that support commercial operations

If your company earns revenue, sells software, or uses this library in production, you must obtain a commercial license.

Commercial License

For commercial usage, a paid license is required. See the full commercial license agreement here:

COMMERCIAL_LICENSE.md


Contributing

Please read our CONTRIBUTING.md before submitting pull requests. By contributing, you agree to the terms described there.


Support

For questions, issues, or feature requests, please open an issue in this repository.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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
1.0.0 113 7/27/2026
1.0.0-alpha.3 82 2/16/2026
1.0.0-alpha.2 74 2/9/2026
1.0.0-alpha.1 79 2/8/2026