---
title: Authentication
description: Authenticate your product's requests to Beeuni.
---

## Create a client

The SDK reads `getToken` on each request. Your application owns token storage and refresh.

```ts
import { createBeeuni } from '@beeuni/sdk';

const beeuni = createBeeuni({
  backendUrl: 'https://api.beeuni.ai/v1',
  getToken: async () => process.env.BEEUNI_API_KEY ?? null,
});

const projects = await beeuni.projects.list();
```

## Choose a credential

- Use a personal API key for server scripts or CI. Keep it on your server and choose the narrowest scope available.
- Use a service account for an agent or another non-human caller. Assign it the project roles it needs; a new service account has no project access.
- For an application acting on behalf of its users, use [Sign in with Beeuni](/docs/sdk/sign-in). Its server handler manages OAuth tokens and refresh.

## Handle rejected requests

`401` means the credential is missing, expired, or invalid. `403` can indicate insufficient permissions or a disabled feature; read the response's error code before retrying.

If your token getter caches a rotating token, attach `invalidate(rejectedToken)` to it. The SDK uses that callback before retrying a rejected token once.

## Keep credentials private

Do not embed server API keys in browser code, URLs, or logs. Use your server or the OAuth proxy for browser requests. Revoke a compromised credential in **Settings → API keys**.

For a Node or Bun server handling requests for different people, use `createScopedBeeuni` per request. Do not repeatedly configure a shared client with different credentials. See [Server-side isolation](/docs/sdk/reference#server-side-isolation).

## Proxy credentials and access requirements

Set `credentialHeader` only when your own backend proxy expects a custom header. The SDK sends the token there without a `Bearer` prefix, instead of setting `Authorization`. This does not bypass Beeuni authentication.

Use `onAccessRemedy(code)` to direct a person through sign-in when REST requests return `403 sso_required` or `403 account_mfa_required`. Runtime proxy requests and event streams do not call this callback. It does not grant permissions or retry the request after sign-in.

[Full example](/docs/sdk/example)
