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

# signToken

> Sign a short-lived HMAC token on your backend to authenticate users against the Gatelit gateway.

`signToken` creates a compact, short-lived token that your frontend can use with the `"GatelitSigned"` auth scheme. Call it from your backend — never from client-side code.

```typescript theme={null}
import { signToken } from "@gatelit/sdk/sign"

const token = await signToken(options: SignedTokenOptions, secret: string): Promise<string>
```

The function uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API), available natively in Node.js 18+ and all edge runtimes (Cloudflare Workers, Vercel Edge, Deno).

The returned string is a compact dot-separated value: `base64url(header).base64url(payload).base64url(signature)` — structurally identical to a standard HS256 JWT.

<Warning>
  Never call `signToken` or expose `GATELIT_SIGNING_SECRET` in frontend code. Import `@gatelit/sdk/sign` only from server-side files (API routes, server functions, edge middleware).
</Warning>

***

## Parameters

### `options`

<ParamField body="sub" type="string" required>
  User identifier embedded in the token. Used for request attribution in dashboard logs.
</ParamField>

<ParamField body="orgId" type="string">
  Organisation ID to embed in the token. The gateway uses this to resolve org-scoped provider keys when BYOK is configured.
</ParamField>

<ParamField body="model" type="string">
  Restrict this token to a single model in `"provider/model-name"` format (for example `"openai/gpt-4o"`). Requests using a different model are rejected by the gateway. Omit to allow any model permitted by your policy.
</ParamField>

<ParamField body="maxTokens" type="number">
  Cap the maximum output tokens for requests made with this token.
</ParamField>

<ParamField body="ttl" type="number" default="60">
  Token lifetime in seconds. Defaults to `60`. Tokens expire at `iat + ttl`.
</ParamField>

### `secret`

<ParamField body="secret" type="string" required>
  Your `GATELIT_SIGNING_SECRET`. Store this in an environment variable and never expose it outside your server.
</ParamField>

***

## Examples

### Nuxt server route

```typescript theme={null}
// server/api/ai-token.get.ts
import { signToken } from "@gatelit/sdk/sign"

export default defineEventHandler(async (event) => {
  const user = await requireUser(event) // your auth middleware
  const token = await signToken({
    sub: user.id,
    model: "openai/gpt-4o",
    maxTokens: 500,
    ttl: 60,
  }, process.env.GATELIT_SIGNING_SECRET!)
  return { token }
})
```

### Next.js API route

<CodeGroup>
  ```typescript app/api/ai-token/route.ts theme={null}
  import { signToken } from "@gatelit/sdk/sign"

  export async function GET(req: Request) {
    // authenticate your user first — e.g. verify a session cookie
    const userId = await getUserIdFromRequest(req)
    if (!userId) {
      return Response.json({ error: "Unauthorized" }, { status: 401 })
    }

    const token = await signToken(
      {
        sub: userId,
        model: "openai/gpt-4o",
        maxTokens: 500,
        ttl: 60,
      },
      process.env.GATELIT_SIGNING_SECRET!,
    )

    return Response.json({ token })
  }
  ```

  ```typescript pages/api/ai-token.ts theme={null}
  import type { NextApiRequest, NextApiResponse } from "next"
  import { signToken } from "@gatelit/sdk/sign"

  export default async function handler(req: NextApiRequest, res: NextApiResponse) {
    // authenticate your user first
    const userId = await getUserIdFromRequest(req)
    if (!userId) {
      return res.status(401).json({ error: "Unauthorized" })
    }

    const token = await signToken(
      {
        sub: userId,
        model: "openai/gpt-4o",
        maxTokens: 500,
        ttl: 60,
      },
      process.env.GATELIT_SIGNING_SECRET!,
    )

    res.json({ token })
  }
  ```
</CodeGroup>

### Using the token on the frontend

Once your backend endpoint issues a token, pass it to `GatelitClient` via `getToken`:

```typescript theme={null}
import { GatelitClient } from "@gatelit/sdk"

const client = new GatelitClient({
  gatewayUrl: "https://gateway.yourapp.com",
  getToken: async () => {
    const { token } = await fetch("/api/ai-token").then(r => r.json())
    return { token, scheme: "GatelitSigned" }
  },
})
```

<Tip>
  `getToken` is called before every request. If your users make several requests in quick succession, consider caching the token in a variable and only re-fetching a new one when the current token is within a few seconds of expiry.
</Tip>

***

## Security notes

* **Never import `@gatelit/sdk/sign` in browser code.** The separate import path exists specifically to prevent the signing code from being bundled into client builds.
* **Store the secret in an environment variable.** Use `process.env.GATELIT_SIGNING_SECRET` (or your runtime's equivalent) and ensure it is excluded from version control.
* **Authenticate the user before issuing a token.** `signToken` does not perform any authentication — you must verify the caller's identity in your own middleware before calling it.
* **Keep TTLs short.** The default of 60 seconds is appropriate for most use cases. A shorter TTL limits the window of exposure if a token is intercepted.
