> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zabcik.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Understand OAuth2 token management and caching behavior in the GoPay SDK.

# Authentication

The SDK authenticates against GoPay using OAuth2 `client_credentials`.

<Info>
  You **do not** call the token endpoint yourself for normal API usage — the SDK caches access tokens and refreshes them before expiry.
</Info>

## How it works

On first API call:

1. The SDK sends a request to `POST /oauth2/token`
2. It stores the token in cache with expiration timestamp
3. It reuses that token until it approaches expiration
4. It refreshes automatically before expiry (refresh margin)

## Token endpoint request

The SDK sends:

* `grant_type=client_credentials`
* configured `scope` (`payment-all` by default)
* `Authorization: Basic <base64(clientId:clientSecret)>`

## Token cache

By default, `InMemoryTokenCache` is used.

<Tip>
  A shared cache (Redis, memcached, etc.) is useful when you run **multiple server instances** so you don’t multiply OAuth token requests unnecessarily.
</Tip>

You can inject your own cache to share tokens across requests or processes:

```ts theme={null}
import { createGoPayClient, type TokenCache } from 'gopay-sdk';

class RedisLikeCache implements TokenCache {
  private readonly storage = new Map<string, any>();

  get(key: string) {
    return this.storage.get(key);
  }

  set(key: string, value: any) {
    this.storage.set(key, value);
  }

  delete(key: string) {
    this.storage.delete(key);
  }
}

const client = createGoPayClient(
  {
    goid: 8123456789,
    clientId: process.env.GOPAY_CLIENT_ID!,
    clientSecret: process.env.GOPAY_CLIENT_SECRET!,
    gatewayUrl: 'https://gw.sandbox.gopay.com/api',
  },
  {
    tokenCache: new RedisLikeCache(),
  },
);
```

## Concurrency behavior

The token manager deduplicates concurrent token requests:

* if multiple requests need a token at once, only one token HTTP call is executed
* all callers await the same in-flight promise

This avoids token endpoint burst traffic.

## Recommended settings

* keep `tokenRefreshMarginSeconds` default (`30`) unless your infra requires more buffer
* keep credentials in environment variables or secret manager
* avoid rotating credentials without coordinated deployment across all nodes
