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

# Client credentials flow

> A server to server flow for your own backend, with no user prompt

Use this flow when your own backend calls the API using your own account. There is no user
to prompt, so there is no consent screen and no redirect. It requires a **Service**
application.

## How it works

Your server sends its `client_id` and `client_secret` to the token endpoint and receives an
access token. The token acts as the account that owns the application.

<Info>
  With this flow, `GET /api/v1/user` returns the profile of the account that owns the
  application. Grant the `profile:read` scope to the application to use it.
</Info>

## Request a token

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://platform.nemu.cc/api/oauth/token' \
    -H 'Content-Type: application/x-www-form-urlencoded' \
    -d 'grant_type=client_credentials' \
    -d 'client_id=cl_123' \
    -d 'client_secret=cls_456'
  ```

  ```ts Node theme={null}
  const body = new URLSearchParams({
    grant_type: "client_credentials",
    client_id: "cl_123",
    client_secret: "cls_456",
  });

  const res = await fetch("https://platform.nemu.cc/api/oauth/token", {
    method: "POST",
    headers: { "content-type": "application/x-www-form-urlencoded" },
    body,
  });

  const { access_token } = await res.json();
  ```
</CodeGroup>

You can also send the credentials with HTTP Basic auth instead of the body.

```bash theme={null}
curl -X POST 'https://platform.nemu.cc/api/oauth/token' \
  -u 'cl_123:cls_456' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials'
```

A successful response returns an access token that lasts one hour. There is no refresh
token. Request a new token when the current one is close to expiry.

```json theme={null}
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "workspaces:read models:read"
}
```

## Call the API

Send the token as a bearer token against the versioned REST API.

```bash theme={null}
curl 'https://platform.nemu.cc/api/v1/workspaces' \
  -H 'Authorization: Bearer eyJhbGciOi...'
```

## Use the SDK

The `Nemu` client handles the token for you. It fetches a token on the first call and caches
it until it is close to expiry.

```ts theme={null}
import { Nemu } from "@nemu-ai/sdk";

const nemu = new Nemu({
  client_id: process.env.nemu_client_id!,
  client_secret: process.env.nemu_client_secret!,
});

const account = await nemu.user.get();
const workspaces = await nemu.workspaces.list();
```

See the [SDK guide](/oauth/sdk) for the full surface.

<Warning>
  The `client_secret` grants full access to everything the application can do. Keep it on your
  server and rotate it from the console if it leaks.
</Warning>
