The SDK supports both key types you can generate in the 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.
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" });
Never embed sk_* keys in frontend bundles, mobile apps, or public repositories. Use JWT public keys for any environment you do not fully control.
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 JWT Public Key Auth for the full auth flow.
REST
import { StructClient } from "@structbuild/sdk";
const client = new StructClient({
apiKey: "pk_jwt_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
jwt: userAccessToken,
});
The SDK sends both credentials on every request:
X-API-Key: pk_jwt_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
Authorization: Bearer <user_jwt>
WebSocket
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.
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.
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 for the full error hierarchy.