Skip to main content
Struct authenticates every REST, websocket, and webhook management request with an API key. Two key types are supported:
PrefixUse fromDescription
sk_live_Server-side code onlySecret key. Full access to your organisation. Inherits the org’s plan, rate limit, and credit cap.
pk_jwt_Browsers, mobile apps, any untrusted clientPublic key. Useless without a valid JWT from your configured auth provider. Safe to ship in frontend bundles.
Generate keys from the Dashboard. Secret keys are shown only once at creation.

REST

Send the key in the X-API-Key header on every request:
curl https://api.struct.to/v1/markets \
  -H "X-API-Key: sk_live_YOUR_KEY"
For JWT public-key auth, send both credentials:
curl https://api.struct.to/v1/markets \
  -H "X-API-Key: pk_jwt_YOUR_KEY" \
  -H "Authorization: Bearer USER_JWT"

WebSocket

Browsers can’t send custom headers on WebSocket connections, so credentials are passed as query parameters:
wss://api.struct.to/ws?api-key=sk_live_YOUR_KEY
wss://api.struct.to/ws/alerts?api-key=sk_live_YOUR_KEY
JWT public-key auth adds a token parameter:
wss://api.struct.to/ws?api-key=pk_jwt_YOUR_KEY&token=USER_JWT

SDK

The TypeScript SDK accepts the same credentials. The same apiKey field accepts secret and public keys; pass jwt (or a rotating getJwt) alongside pk_jwt_*.
import { StructClient } from "@structbuild/sdk";

const client = new StructClient({
  apiKey: "sk_live_YOUR_KEY",
});

const userClient = new StructClient({
  apiKey: "pk_jwt_YOUR_KEY",
  jwt: session.accessToken,
});
See SDK Authentication for the JWT rotation pattern.

Rotating keys

To rotate a secret key:
  1. Generate a new sk_live_* key in the dashboard.
  2. Roll the new key out to your servers.
  3. Disable the old key in the dashboard.
Disabled keys reject new requests immediately. Open websocket connections stay live until they disconnect normally; reconnect attempts will fail authentication. JWT public keys rotate transparently when you point them at a new JWKS URL. Cached JWKS entries are refreshed every 5 minutes, or immediately when a JWT presents an unknown kid.

JWT public keys

pk_jwt_* keys let your end users authenticate directly from a browser or mobile app using a JWT from your auth provider (Privy, Auth0, Clerk, Turnkey, Google, custom). The Struct API verifies the JWT signature against your configured public key and applies per-user rate limits keyed on the JWT sub claim. See Frontend Auth (JWT) for the full flow, supported algorithms, and JWKS configuration. Manage keys at Dashboard › JWT Keys.
Symmetric algorithms (HS256, HS384, HS512) are not supported. Only asymmetric families (RS*, ES*, EdDSA) are accepted, because your public key needs to be safe to publish.

Error responses

StatusMeaningAction
401 UnauthorizedMissing or malformed credentials.Check the X-API-Key header is present and not empty.
401 UnauthorizedInvalid key, expired JWT, or signature mismatch.Verify the key value and JWT signing algorithm.
403 ForbiddenKey disabled or org over its credit cap.Re-enable the key or top up credits in the dashboard.
429 Too Many RequestsRate limit exceeded.Back off and retry. See Rate Limits.
On WebSocket, auth failures arrive as the auth_failed event (SDK) or a close frame with code 1008. Reconnect attempts are not retried automatically on auth failures, since the credentials need to be fixed first.

Security checklist

  • Use sk_live_* only from servers you control. Never embed in frontend bundles, mobile apps, or public repos.
  • Use pk_jwt_* for every browser-side or mobile call. Pair with a short-lived JWT (15 minutes or less) signed by your auth provider.
  • Scope work to multiple keys when you have distinct environments or services so you can rotate without coordinated downtime.
  • Monitor key usage in the dashboard. A key that suddenly spikes is the first sign it’s been leaked.
Last modified on May 31, 2026