Zatca.Net 1.0.2

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

Zatca.Net

License: MIT .NET CI GitHub stars

Zatca.Net

A clean, modern .NET SDK for Saudi Arabia's ZATCA e-invoicing (Fatoora) Phase 2: TLV QR code generation, SHA-256 invoice hashing, ECDSA (secp256k1) signing primitives, EGS onboarding (compliance → production CSIDs), and the clearance / reporting APIs.

Targets netstandard2.0 and net8.0. Only dependencies: System.Text.Json (+ DI abstractions). Bring your own HttpClient.

Disclaimer: community SDK, not affiliated with or endorsed by ZATCA (Zakat, Tax and Customs Authority). Always verify behavior against ZATCA's official documentation before going live — tax compliance is your responsibility.

Install

dotnet add package Zatca.Net

Or reference the project directly until the NuGet package is published.

Quickstart — QR code

using Zatca.Qr;

// Phase 1 style: tags 1-5
string qrPayload = QrCodeGenerator.GeneratePhase1(
    sellerName: "شركة الاختبار",
    vatNumber: "399999999900003",
    timestamp: "2026-10-08T12:00:00Z",   // ISO-8601
    invoiceTotalWithVat: "115.00",
    vatTotal: "15.00");

// Render qrPayload as a QR image with your favorite QR library.

Phase 2 adds the cryptographic tags (6–9):

using Zatca.Crypto;
using Zatca.Qr;

byte[] xmlBytes = GetSignedInvoiceXml();          // your signed UBL 2.1 XML
byte[] hash = InvoiceHasher.ComputeHash(xmlBytes);

using (var signer = EcdsaInvoiceSigner.CreateSecp256k1())
{
    string qr = QrCodeGenerator.Generate(new QrData
    {
        SellerName = "شركة الاختبار",
        VatNumber = "399999999900003",
        Timestamp = "2026-10-08T12:00:00Z",
        InvoiceTotalWithVat = "115.00",
        VatTotal = "15.00",
        InvoiceHash = hash,                       // tag 6
        EcdsaSignature = signer.SignHash(hash),   // tag 7 (raw 64-byte r‖s)
        PublicKey = signer.ExportPublicKeyUncompressed(), // tag 8
        StampSignature = stampSignatureBytes     // tag 9 (simplified invoices)
    });
}

Quickstart — onboarding & submission

using Zatca;
using Zatca.Models;

var client = new ZatcaClient(new ZatcaClientOptions
{
    // defaults to the sandbox; switch BaseUrl for simulation/production
});

// 1. Compliance CSID (OTP from the Fatoora portal; "123345" on sandbox)
CsIdResponse compliance = await client.RequestComplianceCsIdAsync(csrBase64, otp);

// 2. Compliance checks with the compliance credentials
var complianceClient = client.WithCredentials(compliance.BinarySecurityToken, compliance.Secret);
await complianceClient.SubmitComplianceInvoiceAsync(new InvoiceSubmission
{
    InvoiceHash = InvoiceHasher.ComputeHashHex(signedXmlBytes),
    Uuid = invoiceUuid,
    InvoiceBase64 = Convert.ToBase64String(signedXmlBytes)
});
// ... repeat for each invoice type declared in your CSR ...

// 3. Production CSID
CsIdResponse production = await complianceClient.RequestProductionCsIdAsync(compliance.RequestId);

// 4. Report (simplified/B2C) or clear (standard/B2B) with production credentials
var prod = client.WithCredentials(production.BinarySecurityToken, production.Secret);

ZatcaSubmissionResult reported = await prod.ReportInvoiceAsync(submission); // simplified
ZatcaSubmissionResult cleared  = await prod.ClearInvoiceAsync(submission);  // standard

if (cleared.IsAccepted) { /* persist, then share with buyer */ }

ASP.NET Core DI

services.AddZatca(options =>
{
    options.BaseUrl = ZatcaClientOptions.SimulationBaseUrl;
    options.BinarySecurityToken = config["Zatca:Token"];
    options.Secret = config["Zatca:Secret"];
});

API reference

ZatcaClient

Method Endpoint Notes
RequestComplianceCsIdAsync(csrBase64, otp) POST /compliance Headers OTP, Accept-Version: V2. No auth.
SubmitComplianceInvoiceAsync(submission) POST /compliance/invoices Basic auth with compliance CSID.
RequestProductionCsIdAsync(complianceRequestId) POST /production/csids Basic auth with compliance CSID.
RenewProductionCsIdAsync(csrBase64, otp) PATCH /production/csids Basic auth with production CSID + OTP header.
ReportInvoiceAsync(submission) POST /invoices/reporting/single Clearance-Status: 0. Simplified invoices, report within 24h.
ClearInvoiceAsync(submission) POST /invoices/clearance/single Clearance-Status: 1. Standard invoices, clear before sharing with buyer.
WithCredentials(token, secret) — New client sharing the HttpClient, different CSID set.

Errors surface as ZatcaApiException (HTTP status + raw body).

Crypto & QR

  • QrCodeGenerator.Generate(QrData) / GeneratePhase1(...) → base64 TLV payload; Decode(base64) → fields (for verification).
  • InvoiceHasher.ComputeHash / ComputeHashHex / ComputeHashBase64 — SHA-256.
  • IInvoiceSigner + EcdsaInvoiceSigner(ECDsa) — bring your own key; SignHash returns raw 64-byte r‖s; CreateSecp256k1() factory for supported platforms.
  • TaxInvoice (+ Party, InvoiceLine) — domain model with Validate() (totals consistency, buyer required for standard, Saudi VAT format).
  • SaudiVatValidator.IsValid — 15 digits, starts and ends with 3.

Environments

Environment Base URL OTP CSR certificate template
Sandbox (developer portal) https://gw-fatoora.zatca.gov.sa/e-invoicing/developer-portal fixed 123345 TSTZATCA-Code-Signing
Simulation https://gw-fatoora.zatca.gov.sa/e-invoicing/simulation from Fatoora portal PREZATCA-Code-Signing
Production https://gw-fatoora.zatca.gov.sa/e-invoicing/core from Fatoora portal (single-use, 1h) ZATCA-Code-Signing

Notes from the official flow:

  • The sandbox only validates invoices for the test VAT 399999999900003.
  • Simulation enforces the compliance gate (up to 6 sample documents: standard/simplified × invoice/credit/debit) before issuing a production CSID.
  • Always branch on ZATCA's response body (reportingStatus/clearanceStatus, validationResults.status), not just the HTTP status.

Honest scope

What this SDK does:

  • TLV QR payloads (tags 1–9) per ZATCA's Security Features Implementation Standards, with decode support.
  • SHA-256 hashing and ECDSA/secp256k1 signing primitives with raw r‖s output for QR tag 7.
  • Typed clients for onboarding (compliance/production CSIDs, renewal) and clearance/reporting, with correct endpoints, headers and Basic auth.
  • Invoice domain models with consistency validation, Saudi VAT validation.

What it does not do (by design):

  • UBL 2.1 XML generation — you build the invoice XML (fields, UBLExtensions, cac:Signature skeleton) in your ERP; the SDK hashes, signs and submits it.
  • XAdES-BES enveloped signing inside the XML — the IInvoiceSigner signs hash bytes; embedding the <ds:Signature> block is integrator work.
  • CSR generation — generate the secp256k1 key and CSR (with ZATCA's required subject/extension fields) via OpenSSL or your CA tooling, then pass the base64 CSR in.
  • Private-key storage — keys never enter this SDK except as the ECDsa instance you hand it; encrypt CSIDs and keys at rest.

Development

dotnet build Zatca.sln
dotnet test Zatca.sln

Tests are fully offline (mocked HTTP, fixed vectors, independent golden QR bytes).

License

MIT — see LICENSE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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.2 47 10/8/2026
1.0.1 43 10/8/2026
1.0.0 44 10/8/2026

NuGet polish release: branded package icon, embedded README, and full repository metadata.