# Evaluate in browsers

Use the hosted evaluation endpoint with publishable keys and exposed flags.

Browser evaluation calls `POST /v1/evaluate` with a publishable client key. Browser and React packages
are not publicly released, so use the HTTP path documented here.

Use browser evaluation only for values safe for users to inspect. A browser result can shape
presentation but cannot authorize a sensitive operation.

## Prepare the environment

1. Open the project **Environments** page.
2. Select the intended environment.
3. Create a **Browser client key**.
4. Add every exact web origin that may call the API.
5. Enable **Client SDK access** on each required flag configuration.
6. Choose a safe typed default for every request.

The API rejects a client key used without `Origin` or from outside its allowlist. An unexposed flag
behaves as missing even when server evaluation can resolve it.

## Make a request

```ts
const response = await fetch("https://api.featuregate.dev/v1/evaluate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${featureGateClientKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    evaluations: [{ key: "new-checkout", defaultValue: false }],
    context: { account: { plan: "pro" } },
  }),
});

if (!response.ok) {
  return false;
}

const body = await response.json();
const result = body.evaluation.results.find(
  (candidate: { key: string }) => candidate.key === "new-checkout",
);

return typeof result?.value === "boolean" ? result.value : false;
```

Keep the fallback in application code. A network failure, rejected origin, revoked key, hidden flag,
or type mismatch must still produce deliberate UI behaviour.

## Configure allowed origins

Origins include scheme, hostname, and port. Configure each required origin exactly:

- `https://app.example.com`
- `https://admin.example.com`
- `http://localhost:5173`

Do not add broad origins for convenience. Remove local and retired origins when they are no longer
needed. Requests from non-browser tools without `Origin` are rejected for client keys.

## Expose flags deliberately

Client exposure is set per flag and environment. Exposing a flag in staging does not expose it in
production. Creating a client key does not expose all flags.

Before exposure, review every possible fallback and rule outcome. Do not expose secrets, internal
endpoints, private configuration, or data whose visibility would reveal a security control.

Browser tools can inspect the key, request, context, and response. Treat every exposed value as public
to users who can run the application.

## Security boundary

A publishable key is not a secret, but it remains restricted by environment binding, origin, scope,
and flag exposure. Those controls reduce accidental access; they do not make browser context trusted.

A user can modify `account.plan`, `user.role`, and any other browser-supplied attribute. Enforce plan
entitlements and authorization on the server before performing protected work.

Never ship a server runtime or management key to a client. If one is exposed, revoke it and rotate the
affected integration immediately.

## Troubleshooting

- **CORS or `403`:** verify the exact origin, including scheme and port.
- **Caller default:** confirm client exposure in the key-bound environment and check the value type.
- **A rule is bypassed:** confirm the browser sends every required context path.
- **A protected action succeeds incorrectly:** move enforcement to trusted server code.
- **A lost client key:** create and deploy a replacement, then revoke the old key.

Related pages: [Evaluation credentials](/docs/evaluate/credentials),
[Evaluate over HTTP](/docs/evaluate/http-evaluation), and
[Errors and fallbacks](/docs/evaluate/errors-and-fallbacks).
