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

# Authentication

> API key and JWT public key auth with the SDK.

The SDK supports both key types you can generate in the [dashboard](https://struct.to/dashboard):

* **Secret keys** (`sk_*`) for server-side code, giving full access to your organisation.
* **JWT public keys** (`pk_jwt_*`) for client-side code, where each end user supplies their own JWT.

Both are configured through the `apiKey` field on every client.

## Secret API key

Use secret keys from trusted server environments only. They authenticate as your organisation and inherit its rate limits and credit cap.

```typescript theme={null}
import { StructClient, StructWebSocket, StructAlertsWebSocket } from "@structbuild/sdk";

const client = new StructClient({ apiKey: "sk_live_xxx" });
const ws = new StructWebSocket({ apiKey: "sk_live_xxx" });
const alerts = new StructAlertsWebSocket({ apiKey: "sk_live_xxx" });
```

<Warning>Never embed `sk_*` keys in frontend bundles, mobile apps, or public repositories. Use JWT public keys for any environment you do not fully control.</Warning>

## JWT public key auth

JWT public key auth lets end users call the API with a JWT from your auth provider (Privy, Auth0, Clerk, Google, Turnkey, and so on) without exposing a secret key. You create a `pk_jwt_*` key in the dashboard, configure it with your JWKS URL or inline public key, then pass it alongside the user's JWT.

See [Frontend Auth (JWT)](/api-reference/jwt-auth) for the full auth flow.

### REST

```typescript theme={null}
import { StructClient } from "@structbuild/sdk";

const client = new StructClient({
  apiKey: "pk_jwt_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  jwt: userAccessToken,
});
```

The SDK sends both credentials on every request:

```http theme={null}
X-API-Key: pk_jwt_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
Authorization: Bearer <user_jwt>
```

### WebSocket

```typescript theme={null}
import { StructWebSocket } from "@structbuild/sdk";

const ws = new StructWebSocket({
  apiKey: "pk_jwt_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  jwt: userAccessToken,
});
```

Both credentials are appended as query params:

```
wss://api.struct.to/ws?api-key=pk_jwt_xxx&token=<user_jwt>
```

### Rotating JWTs

A `jwt` value is captured when the socket is constructed. If your JWT can rotate while the socket stays alive (for example, refreshed by your auth SDK), pass `getJwt` instead. It is invoked on every reconnect so the new URL always carries a fresh token.

```typescript theme={null}
const ws = new StructWebSocket({
  apiKey: "pk_jwt_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  getJwt: () => auth.getAccessToken(),
});
```

`getJwt` takes precedence over `jwt` when both are provided.

## Shipping the key to the browser

`pk_jwt_*` keys are safe to hardcode in frontend bundles. They are useless without a valid JWT signed by your configured auth provider.

```typescript theme={null}
const client = new StructClient({
  apiKey: process.env.NEXT_PUBLIC_STRUCT_JWT_KEY!,
  jwt: session.accessToken,
});
```

## Errors

Auth failures surface as:

* **REST**: `HttpError` with status `401`.
* **WebSocket**: the `auth_failed` event, followed by `disconnected`. The socket will not attempt to reconnect on auth failures.

See [Errors](/sdk/errors) for the full error hierarchy.
