# Call an AI model from a browser app without exposing an API key

A model API key in browser JavaScript can be read by anyone who opens the
page, so frontend-only apps usually need a proxy server to hold the key. With
Seige, the app calls `seige.ai.generate()` from the browser. Seige holds the
model credential, the user approves AI access for the app, and each request is
charged to the user's Seige AI allowance. There is no key in your code and no
server to run.

```js
import { createSeige } from "@seige_sdk/sdk";

const seige = createSeige({ appName: "Trip planner" });

const { data, error } = await seige.ai.generate({
  prompt: "Suggest a packing list for this trip.",
  input: { city: "Lisbon", nights: 3, month: "October" },
});
if (error) console.warn(error.code, error.hint);
else console.log(data.text, data.usage);
```

## What happens on the first call

The first `seige.ai.generate()` call opens a Seige window that asks the user to
allow the app to generate AI answers. After they approve, the call continues
and returns the answer. Later calls do not ask again in that browser. To ask
before the feature is used, call `seige.request({ access: "ai" })`.

## Structured answers

Pass a `schema` with a `parse` method, or a compatible schema library object.
The SDK asks the model for JSON, parses the answer and validates it. The
validated value is returned as `data.value`. Invalid JSON or a rejected value
is returned as an error. Describe the expected fields in the prompt.

```js
const { data } = await seige.ai.generate({
  prompt: "Return {\"items\": string[]} with up to eight items to pack.",
  input: trip,
  schema: { parse: (value) => ({ items: value.items.map(String) }) },
});
```

## Cancelling and limits

- Pass an `AbortSignal` as `signal` to cancel a request.
- The prompt is limited to 16,000 bytes and the input to 100,000 bytes. Output
  defaults to 2,048 tokens, with a maximum of 4,096.
- An app can make 20 requests per hour, within 100 requests per hour for all
  apps on the account, and one request per account runs at a time.
  `seige.ai.usage()` reports the current window.
- When a request's estimated cost exceeds available AI credit, calls return
  `ALLOWANCE_EXCEEDED`. Pending requests reserve credit until settlement.
  AI credit has no automatic hourly reset. Do not retry automatically.

## What the model receives

`seige.ai.generate()` is a standard model endpoint, not an agent. It has no
tools and no access to the user's account. It receives only the prompt and
input that your app sends, and your app can only send data the user gave it.
AI inputs are not end-to-end encrypted: Seige and the model host process them
in readable form. The approval window tells the user this before they allow
access.

## When this fits

This approach suits apps where each signed-in user asks for AI help with their
own data. It does not suit anonymous visitors, because every request needs a
signed-in Seige user who approved AI access, or apps that need tools, long
agent loops or a specific model provider.

## Related guides

- [Add sign-in to a browser app without a backend](/guides/sign-in-without-a-backend/)
- [Instructions for coding agents](/guides/backend-for-coding-agents/)
- [Complete SDK reference](/developers/sdk-reference.md)
