# Security

> API keys, public IDs, allowed origins, and how to limit what browser search can read.

## API keys

API keys are secrets for your servers. Create them on the **API keys** page, which only workspace owners can see:

- The `write` scope changes records, settings, and browser search restrictions.
- The `search` scope searches, for server-rendered pages and backends.
- A key can be limited to one index.

Give each service a key with only the scopes and index it needs, and keep keys in your server's environment, never in browser code or a repository. If a key leaks, delete it on the **API keys** page and create another.

> **Note:** The API refuses API-key requests sent from web pages, so a key put in browser code by mistake
> fails instead of quietly working.

## Public IDs and allowed origins

Browser search uses an index's public ID instead of a key. It is visible in your page's source, so it can only search, only its own index, and only from the origins on the index's **Public access** page.

- Add each origin exactly, with its scheme and any port: `https://shop.example.com`, `https://www.example.com`, `http://localhost:5173`. An index has up to 20.
- Browser search is off until an owner saves at least one origin.
- Each visitor (IP address) can make 240 searches a minute on an index, and an index takes up to 6,000 a minute in all. Over either limit, public search answers `429` with a `Retry-After` header.
- If a public ID is misused, rotate it on the **Public access** page. Searches with the old ID stop within a minute, so put the new one in your storefront right away.

> **Warning:** Origin checks stop other websites from using your index from their visitors' browsers. They don't
> authenticate other callers: a script can send any `Origin` header. Treat everything browser search
> can read as public.

## What browser search can read

By default, browser search returns every field of the records you upload, and can search, filter, facet, and sort by everything the index's settings allow. Only upload fields you're happy to publish, and leave out things like cost prices, supplier details, and internal notes.

To limit browser search further, set a public search policy under **What browsers can see**, or from your server:

```ts
await products.setPublicSearchPolicy({
  returnFields: ["objectID", "title", "brand.name", "price", "image", "url"],
  searchFields: ["title", "brand.name"],
  filterFields: ["brand.name", "price", "inStock"],
  facetFields: ["brand.name"],
  sortIds: ["relevance", "price-asc"],
  defaultSort: "relevance",
})
```

With a policy, browser searches can only return, search, filter, facet, and sort by the listed fields, and requests for others are rejected. `usePublicIndexDefaults()` removes the policy, and `getPublicSearchAccess()` shows the public ID, origins, and current policy.

`attributesToRetrieve` in a search request only asks for fewer fields; it doesn't keep the others private. Use a policy, or leave the fields out of your records.

## Workspace members

Owners manage members, API keys, and allowed origins, and change records and settings in the dashboard. Other members can see indexes and their settings, try searches, and read analytics. Owners invite members from **Settings**.
