Camt.Net 1.1.0

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

Camt.Net

Zero-dependency ISO 20022 bank statement parser for .NET. Turn camt.053, camt.052 and camt.054 XML into a typed, ergonomic object model, with decimal money and DateOnly dates, across schema versions.

NuGet   MIT   Zero dependencies   Native AOT clean

Why

ISO 20022 camt is the modern successor to the SWIFT MT940 statement (if you still consume those, see the sibling Mt940.Net). Banks increasingly hand you camt.053 end-of-day statements, camt.052 intraday reports and camt.054 debit/credit notifications, and the XML is verbose, deeply nested, and versioned by namespace.

The existing options are heavy. The generic Iso20022 code-generated packages ship thousands of DTO classes for the entire standard and pin you to one schema version, so a camt.053.001.02 file and a camt.053.001.08 file need different types. Camt.Net is the small, focused primitive instead: it reads exactly the statement, balance and entry data you actually use, and it does so namespace-agnostically so multiple schema versions parse through the same code path. In-box System.Xml.Linq only, no runtime dependencies.

Install

dotnet add package Camt.Net

Use

using Camt;

CamtDocument doc = CamtStatement.Parse(xml); // string or Stream

foreach (Statement statement in doc.Statements)
{
    Console.WriteLine($"{statement.AccountId} ({statement.Currency})");

    foreach (Balance balance in statement.Balances)
    {
        Console.WriteLine($"  {balance.Type}: {balance.SignedAmount} {balance.Currency}");
    }

    foreach (Entry entry in statement.Entries)
    {
        Console.WriteLine($"  {entry.BookingDate}: {entry.SignedAmount} {entry.Currency} {entry.Reference}");
    }
}

Non-throwing variant:

if (CamtStatement.TryParse(xml, out CamtDocument? doc))
{
    // use doc
}

The balance-conservation guarantee

Every entry and balance exposes a SignedAmount: positive for a credit, negative for a debit. That makes the fundamental statement invariant a one-liner you can assert against your own data:

Balance opening = statement.Balances.Single(b => b.Type == BalanceType.Opening);
Balance closing = statement.Balances.Single(b => b.Type == BalanceType.Closing);

decimal movement = statement.Entries.Sum(e => e.SignedAmount);

// opening + net movement == closing
Debug.Assert(opening.SignedAmount + movement == closing.SignedAmount);

Money is decimal throughout and parsed with InvariantCulture, so there is no binary floating-point drift and no locale surprise in your reconciliation.

Model

  • CamtDocument { CamtMessageType MessageType, IReadOnlyList<Statement> Statements }
  • Statement { string? Id, string? AccountId, string? Currency, IReadOnlyList<Balance> Balances, IReadOnlyList<Entry> Entries }
  • Balance { BalanceType Type, decimal Amount, string Currency, CreditDebit CreditDebit, DateOnly? Date, string? ProprietaryCode, decimal SignedAmount }
  • Entry { decimal Amount, string Currency, CreditDebit CreditDebit, DateOnly? BookingDate, DateOnly? ValueDate, string? Reference, string? AdditionalInfo, string? Status, string? ProprietaryCode, string? BankTransactionCode, decimal SignedAmount }

AccountId prefers the IBAN and falls back to the proprietary other identifier. BalanceType maps the ISO codes: OPBD/OPAV/PRCD to Opening, CLBD/CLAV to Closing, ITBD/ITAV to Interim, everything else to Other.

Proprietary codes and bank transaction codes

Banks often carry their own codes alongside (or instead of) the standard ISO ones. Camt.Net surfaces these raw values instead of discarding them:

  • Balance.ProprietaryCode holds the raw code from a <Prtry> balance type, for example LEDGER. When it is populated, Balance.Type is BalanceType.Other, so a consumer can still read the exact bank code.
  • Entry.ProprietaryCode holds the raw proprietary status code from the entry <Sts> when it is not a standard ISO status.
  • Entry.BankTransactionCode categorizes the entry: the ISO domain, family and sub-family joined by / (for example PMNT/RCDT/ESCT), or the proprietary <BkTxCd><Prtry><Cd> value (for example NTRF+00100) when no ISO structure is present.

All three are additive and default to null when the source XML does not carry them.

Namespace handling

camt messages carry a URN namespace that encodes the schema version, for example urn:iso:std:iso:20022:tech:xsd:camt.053.001.02 and ...camt.053.001.08. Camt.Net matches elements by local name and ignores the namespace, so files written against different schema versions parse through the same code with no configuration.

Notes and limitations

  • Parse-only. This library reads XML; it does not generate it.
  • camt.05x statement family only (camt.053, camt.052, camt.054). Other ISO 20022 message groups are out of scope.
  • The model surfaces the core statement, balance and entry fields, plus proprietary balance/status codes and the entry bank transaction code. Deeper sub-structures such as full structured remittance and related parties are not mapped.
  • decimal output and DateOnly input/output. Time-of-day on DtTm dates is intentionally dropped.

License

MIT. Copyright Israel Iyonsi.

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.
  • net8.0

    • No dependencies.

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.1.0 80 8/21/2026
1.0.1 82 8/21/2026
1.0.0 85 8/19/2026