> 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.

# Getting Started

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

## Prerequisites

- **Go 1.18+**
- **`KARD_CLIENT_ID` and `KARD_CLIENT_SECRET`**

## Create a Client

Import and instantiate the client using your credentials.

This SDK supports two authentication methods:

**OAuauth Client Credentials**

```go
client := client.NewClient(
    option.WithToken("<YOUR_ACCESS_TOKEN>"),
)
```

**Bearer Token Authentication**

```go
client := client.NewClient(
    option.WithClientCredentials(
        "<YOUR_CLIENT_ID>",
        "<YOUR_CLIENT_SECRET>",
    ),
)
```

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

## Environments

This SDK allows you to configure different environments for API requests with the `option.WithBaseURL` option.

```go
client := client.NewClient(
    option.WithBaseURL(kard.Environments.Production),
)
```

## Make Your First API Calls

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

```go
package example

import (
    context "context"

    kard "github.com/KardFinancial/kard-go-sdk"
    client "github.com/KardFinancial/kard-go-sdk/client"
    option "github.com/KardFinancial/kard-go-sdk/option"
)

func do() {
    client := client.NewClient(
        option.WithClientCredentials(
            "<clientId>",
            "<clientSecret>",
        ),
    )
    request := &kard.CreateUsersObject{
        Data: []*kard.UserRequestDataUnion{
            &kard.UserRequestDataUnion{
                User: &kard.UserRequestData{
                    Id: "1234567890",
                    Attributes: &kard.UserRequestAttributes{
                        ZipCode: kard.String(
                            "11238",
                        ),
                        EnrolledRewards: []kard.EnrolledRewardsType{
                            kard.EnrolledRewardsTypeCardlinked,
                        },
                        Email: kard.String(
                            "user@example.com",
                        ),
                        HashedEmail: kard.String(
                            "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3e2d8a5b76e45a1d4c4e2e3a1",
                        ),
                        PhoneNumber: kard.String(
                            "+14155552671",
                        ),
                        BirthYear: kard.String(
                            "1990",
                        ),
                        HistoricalTransactionsSent: kard.Bool(
                            true,
                        ),
                    },
                },
            },
        },
    }
    client.Users.Create(
        context.TODO(),
        "organization-123",
        request,
    )
}
```

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:

```go
package example

import (
    context "context"

    kard "github.com/KardFinancial/kard-go-sdk"
    client "github.com/KardFinancial/kard-go-sdk/client"
    hem "github.com/KardFinancial/kard-go-sdk/hem"
    option "github.com/KardFinancial/kard-go-sdk/option"
)

func do() {
    client := client.NewClient(
        option.WithClientCredentials(
            "<clientId>",
            "<clientSecret>",
        ),
    )

    hashedEmail, err := hem.GenerateHEM("Jane.Doe+work@gmail.com")
    if err != nil {
        return
    }

    request := &kard.CreateUsersObject{
        Data: []*kard.UserRequestDataUnion{
            &kard.UserRequestDataUnion{
                User: &kard.UserRequestData{
                    Id: "1234567890",
                    Attributes: &kard.UserRequestAttributes{
                        EnrolledRewards: []kard.EnrolledRewardsType{
                            kard.EnrolledRewardsTypeCardlinked,
                        },
                        HashedEmail: kard.String(
                            hashedEmail,
                        ),
                    },
                },
            },
        },
    }
    client.Users.Create(
        context.TODO(),
        "organization-123",
        request,
    )
}
```

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

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

```go
package example

import (
    context "context"

    kard "github.com/KardFinancial/kard-go-sdk"
    client "github.com/KardFinancial/kard-go-sdk/client"
    option "github.com/KardFinancial/kard-go-sdk/option"
)

func do() {
    client := client.NewClient(
        option.WithClientCredentials(
            "<clientId>",
            "<clientSecret>",
        ),
    )
    request := &kard.GetOffersByUserRequest{
        PageSize: kard.Int(
            1,
        ),
        FilterIsTargeted: kard.Bool(
            true,
        ),
        Sort: kard.String(
            "-startDate",
        ),
        SupportedComponents: []*kard.ComponentType{
            kard.ComponentTypeShortDescription.Ptr(),
            kard.ComponentTypeLongDescription.Ptr(),
            kard.ComponentTypeCta.Ptr(),
            kard.ComponentTypeTags.Ptr(),
            kard.ComponentTypeDetailTags.Ptr(),
            kard.ComponentTypeBaseReward.Ptr(),
        },
    }
    client.Users.Rewards.Offers(
        context.TODO(),
        "organization-123",
        "1234567890",
        request,
    )
}
```

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

```go
package example

import (
    context "context"

    kard "github.com/KardFinancial/kard-go-sdk"
    client "github.com/KardFinancial/kard-go-sdk/client"
    option "github.com/KardFinancial/kard-go-sdk/option"
)

func do() {
    client := client.NewClient(
        option.WithClientCredentials(
            "<clientId>",
            "<clientSecret>",
        ),
    )
    request := &kard.CreateTransactionsObject{
        Data: []*kard.TransactionsDataUnion{
            &kard.TransactionsDataUnion{
                Transaction: &kard.TransactionsData{
                    Id: "12345610",
                    Attributes: &kard.TransactionsAttributes{
                        UserId: "1234567890",
                        Amount: 1000,
                        Subtotal: kard.Int(
                            800,
                        ),
                        Status:   "APPROVED",
                        Currency: "USD",
                        Description: "ADVANCEAUTO",
                        AuthorizationDate: "2021-07-02T17:47:06Z",
                        PaymentType: kard.String(
                            "CARD",
                        ),
                        Direction: "DEBIT",
                        Merchant: &kard.Merchant{
                            Id:   "12345678901234567",
                            Name: "ADVANCEAUTO",
                            AddrStreet: kard.String(
                                "125 Main St",
                            ),
                            AddrCity: kard.String(
                                "Philadelphia",
                            ),
                            AddrState: kard.String(
                                "PA",
                            ),
                            AddrZipcode: kard.String(
                                "19147",
                            ),
                            AddrCountry: kard.String(
                                "United States",
                            ),
                            Latitude: kard.String(
                                "37.9419429",
                            ),
                            Longitude: kard.String(
                                "-73.1446869",
                            ),
                            StoreId: kard.String(
                                "12345",
                            ),
                        },
                        CardBin:      "123456",
                        CardLastFour: "4321",
                        AuthorizationCode: kard.String(
                            "123456",
                        ),
                        RetrievalReferenceNumber: kard.String(
                            "100804333919",
                        ),
                        SystemTraceAuditNumber: kard.String(
                            "333828",
                        ),
                        AcquirerReferenceNumber: kard.String(
                            "1234567890123456789012345678",
                        ),
                        TransactionId: "12345611",
                    },
                },
            },
        },
    }
    client.Transactions.Create(
        context.TODO(),
        "organization-123",
        request,
    )
}
```

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

## Handling Errors

If an API request fails (4xx or 5xx), the SDK returns a structured error compatible with `errors.Is` and `errors.As`.

```go
response, err := client.Users.Create(...)
if err != nil {
    var apiError *core.APIError
    if errors.As(err, apiError) {
        // Do something with the API error ...
    }
    return err
}
```

## 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 `option.WithMaxAttempts`:

```go
client := client.NewClient(
    option.WithMaxAttempts(1),
)

response, err := client.Users.Create(
    ...,
    option.WithMaxAttempts(1),
)
```

### Set a Timeout

Use the standard `context` library to set a per-request timeout.

```go
ctx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()

response, err := client.Users.Create(ctx, ...)
```

## Access Raw HTTP Responses

To inspect headers or status codes, use `WithRawResponse`.

```go
response, err := client.Users.WithRawResponse.Create(...)
if err != nil {
    return err
}
fmt.Printf("Got response headers: %v", response.Header)
fmt.Printf("Got status code: %d", response.StatusCode)
```

## Explicit Null

To send an explicit `null` through an optional parameter, use the setter methods on the request object; they flip a bit in `explicitFields` so the property is serialized rather than omitted.

```go
type ExampleRequest struct {
    // An optional string parameter.
    Name *string `json:"name,omitempty" url:"-"`

    // Private bitmask of fields set to an explicit value and therefore not to be omitted
    explicitFields *big.Int `json:"-" url:"-"`
}

request := &ExampleRequest{}
request.SetName(nil)

response, err := client.Users.Create(ctx, request, ...)
```

## Custom HTTP Client

A variety of request options are included to adapt the behavior of the library, which includes configuring authorization tokens, or providing your own instrumented `*http.Client`.

Providing your own `*http.Client` is recommended. Otherwise, the `http.DefaultClient` will be used, and your client will wait indefinitely for a response (unless the per-request, context-based timeout is used).

```go
// Specify default options applied on every request.
client := client.NewClient(
    option.WithToken("<YOUR_API_KEY>"),
    option.WithHTTPClient(
        &http.Client{
            Timeout: 5 * time.Second,
        },
    ),
)

// Specify options for an individual request.
response, err := client.Users.Create(
    ...,
    option.WithToken("<YOUR_API_KEY>"),
)
```