***

title: Shared SDK Client
subtitle: Bootstrap one Gwop client and keep identity request options separate
slug: integration-patterns/shared-client
----------------------------------------

Start with one shared `Gwop` client for your backend. Do not create ad hoc SDK instances inside routes or services.

## Why this pattern

* merchant API key, webhook secret, and timeout are app-level configuration
* invoices and webhook verification use the same client instance
* auth intents, sessions, and JWKS still need identity-specific request options

That split is the important nuance: one SDK client, plus explicit request options for the identity surface.

## Recommended shape

```typescript
import { Gwop } from "@gwop/sdk";

export function createGwopClient(config: AppConfig): Gwop {
  return new Gwop({
    merchantApiKey: config.gwop.merchantApiKey,
    webhookSecret: config.gwop.webhookSecret,
    timeoutMs: config.gwop.timeoutMs,
  });
}

export function createGwopIdentityRequestOptions(config: AppConfig) {
  return {
    serverURL: config.gwop.identity.baseUrl,
    timeoutMs: config.gwop.timeoutMs,
  } as const;
}
```

## What to carry into your own app

* create the SDK once at startup
* inject it into your adapters or services
* keep identity request options as a small explicit helper
* avoid hardcoding the identity hostname deep inside auth code

## Related pages

<CardGroup cols={2}>
  <Card title="Quickstart" icon="duotone bolt" href="/sdk-quickstart">
    Start from the end-to-end flow before splitting the code into adapters
  </Card>

  <Card title="Wallet Auth" icon="duotone wallet" href="/integration-patterns/wallet-auth">
    See how auth calls use the shared client plus identity request options
  </Card>
</CardGroup>
