> This page is for version 2024-10-01 (default).
> For other versions, use one of these documentation indexes:
> - 2024-10-01 (default): https://docs.getkard.com/2024-10-01/llms.txt
> - Legacy: https://docs.getkard.com/legacy/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getkard.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getkard.com/_mcp/server.

C# Getting Started

This guide walks you through installing the [**Kard .NET SDK**](https://github.com/KardFinancial/kard-csharp-sdk/), authenticating with the Kard API, and making your first request.

## Prerequisites

- **.NET Framework 4.6.2+** or **.NET Standard 2.0+**
- **`KARD_CLIENT_ID` and `KARD_CLIENT_SECRET`**

## Install the SDK

```bash
dotnet add package KardFinancial
```

## Create a Client

Import and instantiate the `KardClient` using your credentials.

```csharp
using KardFinancial;

var client = new KardClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");
```

If `KARD_CLIENT_ID` and `KARD_CLIENT_SECRET` are set in your runtime environment, the SDK will automatically use them, so you can initialize the client without passing credentials explicitly.

```csharp
using KardFinancial;

var client = new KardClient();
```

The client automatically handles **authentication, retries, and timeouts.**

## Environments

You can configure a custom base URL by setting `BaseUrl` on `ClientOptions`.

```csharp
using KardFinancial;

var client = new KardClient(new ClientOptions
{
    BaseUrl = KardEnvironment.Production
});
```

## Make Your First API Calls

**1.** [Creating a User](https://docs.getkard.com/api/users/create):

```csharp
using KardFinancial;

var client = new KardClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

await client.Users.CreateAsync(
    "organization-123",
    new CreateUsersObject
    {
        Data = new List<UserRequestDataUnion>()
        {
            new UserRequestDataUnion(
                new UserRequestDataUnion.User(
                    new UserRequestData
                    {
                        Id = "1234567890",
                        Attributes = new UserRequestAttributes
                        {
                            ZipCode = "11238",
                            EnrolledRewards = new List<EnrolledRewardsType>()
                            {
                                EnrolledRewardsType.Cardlinked,
                            },
                            Email = "user@example.com",
                            HashedEmail =
                                "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3e2d8a5b76e45a1d4c4e2e3a1",
                            PhoneNumber = "+14155552671",
                            BirthYear = "1990",
                            HistoricalTransactionsSent = true,
                        },
                    }
                )
            ),
        },
    }
);
```

To enhance offer targeting and attribution, you can include a **hashed email (HEM)** when creating users. The SDK includes a built-in `Hem.GenerateHEM` utility that normalizes and hashes email addresses:

```csharp
using KardFinancial;
using KardFinancial.Hem;

var client = new KardClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

var hashedEmail = Hem.GenerateHEM("Jane.Doe+work@gmail.com");

await client.Users.CreateAsync(
    "organization-123",
    new CreateUsersObject
    {
        Data = new List<UserRequestDataUnion>()
        {
            new UserRequestDataUnion(
                new UserRequestDataUnion.User(
                    new UserRequestData
                    {
                        Id = "1234567890",
                        Attributes = new UserRequestAttributes
                        {
                            EnrolledRewards = new List<EnrolledRewardsType>()
                            {
                                EnrolledRewardsType.Cardlinked,
                            },
                            HashedEmail = hashedEmail,
                        },
                    }
                )
            ),
        },
    }
);
```

The function normalizes the email before hashing (removes whitespace, lowercases, and handles Gmail-specific rules like dot and `+` suffix removal). It throws an `ArgumentException` for invalid inputs.

**2.** [Fetching Offers for User with Extended API](https://docs.getkard.com/api/rewards/offers):

```csharp
using KardFinancial;
using KardFinancial.Users;

var client = new KardClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

await client.Users.Rewards.OffersAsync(
    "organization-123",
    "1234567890",
    new GetOffersByUserRequest
    {
        PageSize = 1,
        FilterIsTargeted = true,
        Sort = new List<OfferSortOptions> { OfferSortOptions.StartDateDesc },
        SupportedComponents = new List<ComponentType>
        {
            ComponentType.ShortDescription,
            ComponentType.LongDescription,
            ComponentType.Cta,
            ComponentType.Tags,
            ComponentType.DetailTags,
            ComponentType.BaseReward,
        },
    }
);
```

**3.** [Submitting Transaction for User](https://docs.getkard.com/api/transactions/create):

```csharp
using KardFinancial;

var client = new KardClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

await client.Transactions.CreateAsync(
    "organization-123",
    new TransactionsRequestBody
    {
        Data = new List<Transactions>
        {
            new Transactions(
                new Transactions.Transaction(
                    new TransactionsRequest
                    {
                        Id = "12345610",
                        Attributes = new TransactionsAttributes
                        {
                            UserId = "1234567890",
                            Amount = 1000,
                            Subtotal = 800,
                            Status = TransactionStatus.Approved,
                            Currency = "USD",
                            Description = "ADVANCEAUTO",
                            AuthorizationDate = DateTime.Parse("2021-07-02T17:47:06Z"),
                            PaymentType = TransactionPaymentType.Card,
                            Direction = DirectionType.Debit,
                            Merchant = new Merchant
                            {
                                Id = "12345678901234567",
                                Name = "ADVANCEAUTO",
                                AddrStreet = "125 Main St",
                                AddrCity = "Philadelphia",
                                AddrState = States.Pa,
                                AddrZipcode = "19147",
                                AddrCountry = "United States",
                                Latitude = "37.9419429",
                                Longitude = "-73.1446869",
                                StoreId = "12345",
                            },
                            CardBin = "123456",
                            CardLastFour = "4321",
                            AuthorizationCode = "123456",
                            RetrievalReferenceNumber = "100804333919",
                            SystemTraceAuditNumber = "333828",
                            AcquirerReferenceNumber = "1234567890123456789012345678",
                            TransactionId = "12345611",
                        },
                    }
                )
            ),
        },
    }
);
```

All SDK methods return **typed responses and throw typed errors.**

## Handling Errors

If an API request fails (4xx or 5xx), the SDK throws a `KardApiException`.

```csharp
using KardFinancial;

try
{
    var response = await client.Users.CreateAsync(...);
}
catch (KardApiException e)
{
    System.Console.WriteLine(e.Body);
    System.Console.WriteLine(e.StatusCode);
}
```

## Common Configuration Options

### Configure Retries

Retries are enabled by default (max 2 attempts) with exponential backoff. The SDK retries on status codes 408, 429, and 5xx. Configure with the `MaxRetries` request option:

```csharp
var response = await client.Users.CreateAsync(
    ...,
    new RequestOptions {
        MaxRetries = 0
    }
);
```

### Set a Timeout

The SDK defaults to a 30 second timeout. Override it with the `Timeout` request option.

```csharp
var response = await client.Users.CreateAsync(
    ...,
    new RequestOptions {
        Timeout = TimeSpan.FromSeconds(3)
    }
);
```

### Add Custom Headers

Use the `AdditionalHeaders` request option to send extra headers.

```csharp
var response = await client.Users.CreateAsync(
    ...,
    new RequestOptions {
        AdditionalHeaders = new Dictionary<string, string?>
        {
            { "X-Custom-Header", "custom-value" }
        }
    }
);
```

### Add Query Parameters

Use the `AdditionalQueryParameters` request option to send extra query params.

```csharp
var response = await client.Users.CreateAsync(
    ...,
    new RequestOptions {
        AdditionalQueryParameters = new Dictionary<string, string>
        {
            { "custom_param", "custom-value" }
        }
    }
);
```

## Access Raw HTTP Responses

To inspect status codes, headers, or the URL, use `.WithRawResponse()`.

```csharp
using KardFinancial;

var result = await client.Users.CreateAsync(...).WithRawResponse();

var data = result.Data;
var statusCode = result.RawResponse.StatusCode;
var headers = result.RawResponse.Headers;
var url = result.RawResponse.Url;

if (headers.TryGetValue("X-Request-Id", out var requestId))
{
    System.Console.WriteLine($"Request ID: {requestId}");
}
```

## Forward Compatible Enums

This SDK uses forward-compatible enums that handle unknown values gracefully.

```csharp
using KardFinancial;

// Using a built-in value
var cardNetwork = CardNetwork.Visa;

// Using a custom value
var customCardNetwork = CardNetwork.FromCustom("custom-value");

// Using in a switch statement
switch (cardNetwork.Value)
{
    case CardNetwork.Values.Visa:
        Console.WriteLine("Visa");
        break;
    default:
        Console.WriteLine($"Unknown value: {cardNetwork.Value}");
        break;
}

// Explicit casting
string cardNetworkString = (string)CardNetwork.Visa;
CardNetwork cardNetworkFromString = (CardNetwork)"VISA";
```