> ## 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.

# JWT Public Keys

> Let your end users authenticate directly to the Struct API using JWTs from their own auth provider.

JWT public keys let builders expose Struct API access to their end users **without sharing their real `sk_*` API key**. End users authenticate with JWTs from the builder's own auth provider (Privy, Turnkey, Google, Auth0, etc.). Struct only verifies the JWT, never creates or manages it.

Each JWT public key (`pk_jwt_*`) is safe to hardcode in frontend bundles. It tells Struct:

* Which JWKS URL or inline public key to use to verify the end user's JWT
* Which builder organisation to bill the request to
* What per-session rate limit to enforce

<Note>End users never see or interact with the `pk_jwt_*` key. Their only credential is the JWT issued by their own auth provider.</Note>

## How It Works

```
Builder dashboard          Builder's frontend app          Struct API
─────────────────────────────────────────────────────────────────────
Create pk_jwt_xxx  ──►  Hardcode pk_jwt_xxx
Configure JWKS URL
                           User logs in via Privy ──►
                           Privy issues JWT        ◄──

                           API request with:       ──►  Verify JWT against JWKS
                           X-Api-Key: pk_jwt_xxx        Bill credits to builder's org
                           Authorization: Bearer JWT     Apply per-session rate limit
```

## Setting Up a JWT Public Key

JWT public keys are configured from within an API key's settings page.

<Steps>
  <Step title="Navigate to your API key">
    Go to **API Keys** in your organisation's dashboard and select the API key you want to associate with JWT auth.
  </Step>

  <Step title="Open the Settings tab">
    On the API key detail page, click the **Settings** tab.
  </Step>

  <Step title="Configure JWT public key">
    Fill in the JWT public key configuration:

    * A **name** for the key (e.g. `My App (Privy)`)
    * A **JWKS URL** *or* an **inline public key** for JWT verification
    * Optionally, expected **audience** and **issuer** claims
    * Optionally, a **per-session rate limit** (requests per minute per end user)
  </Step>

  <Step title="Copy your key">
    Your `pk_jwt_*` key is shown once at creation. Embed it in your frontend application.
  </Step>
</Steps>

## Managing Keys

From the API key's **Settings** tab you can:

* **Update** a key's name, JWKS URL, public key, audience, issuer, rate limit, or enabled status
* **Disable** a key to temporarily block all requests using it (takes effect within 60 seconds)
* **Delete** a key to permanently invalidate it (takes effect immediately)

<Note>Updates take effect within 60 seconds as the cached record expires.</Note>

## Configuration Fields

| Field             | Type    | Required  | Description                                                                                                                   |
| ----------------- | ------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `name`            | string  | Yes       | Human-readable label                                                                                                          |
| `jwks_url`        | string  | Either/or | JWKS endpoint URL. Used for RS256, RS384, RS512, ES256, ES384 (Privy, Google, Turnkey, Auth0, etc.)                           |
| `public_key`      | string  | Either/or | Inline public key (PEM or JWK JSON). Supports RSA, EC, and EdDSA algorithms. Alternative to `jwks_url`; provide one, not both |
| `audience`        | string  | No        | If set, the `aud` claim in the user JWT must match this value                                                                 |
| `issuer`          | string  | No        | If set, the `iss` claim in the user JWT must match this value                                                                 |
| `per_session_rpm` | integer | No        | Rate limit per end user session (per `sub` claim), in requests per minute. `null` = no per-session limit                      |

Exactly one of `jwks_url` or `public_key` must be provided: not both, not neither.

## Billing

Each `pk_jwt_*` key is associated with a standard API key at creation time. All credits and rate limits are billed through that parent API key, so the parent key's rate limit and credit cap apply. End users do not need a Struct account or credits.

The `per_session_rpm` is an additional per-user cap applied on top of the parent key's limits, keyed on the `sub` claim from the user JWT.

## Security

* A leaked `pk_jwt_*` key cannot be exploited alone; it is useless without a valid user JWT from the configured provider
* Struct only stores public verification material (JWKS URLs or public keys), never private keys or signing secrets
* Only asymmetric JWT algorithms are supported (RS256, RS384, RS512, ES256, ES384, EdDSA); symmetric secrets (HS256) are not accepted
* Disabling or deleting a key takes effect within 60 seconds (cache TTL)
* JWKS keys are cached for 5 minutes. If a provider rotates signing keys, the first request with a new `kid` will trigger an immediate re-fetch
