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

# NextJS

> Learn more about using Oneloop NextJS SDK

<Note>
  This SDK is for adding authentication to your NextJS routes. If you would like
  to add our embeddable frontend UI to your NextJS app, please refer to the
  [Oneloop UI SDK](/sdk/starter-kits/nextjs).
</Note>

Our NextJS SDK is a simple way to add authentication to your NextJS routes. We have also written an in-depth blog on how to add API Keys to your NextJS routes using Oneloop. You can read it [here](https://www.oneloop.ai/blog/how-to-add-api-keys-to-nextjs-routes).

## Installation

```bash bash theme={null}
npm i @oneloop-hq/nextjs@latest
```

## Adding Authentication

Adding Oneloop auth to your NextJS routes is as simple as adding the `auth` higher order function to your route handler.
First you create a oneloop client using 'createOneloop' function and pass in your Oneloop SDK key to it.
Then you pass this client to the `auth` higher order function.

This function will automatically verify the user's API key and return a 401 if the key is invalid. To override this behavior, you can pass in a custom error handlers as the third argument as shown here

<Warning>
  Please make sure **not to expose your Oneloop SDK key** in your frontend code.
  Always add your SDK key to your server components or environment variables.
</Warning>

```typescript api/profile/route.ts theme={null}
"use server";
import { createOneloop } from "@oneloop-hq/nextjs";

const oneloop = createOneloop("<YOUR_ONELOOP_SDK_KEY>");

export const GET = oneloop.auth(async (request: Request) => {
  return new Response("Profile Endpoint Authenticated");
});
```

## Validating with scopes

At Oneloop, we call RBAC / Permissions as Scopes. You can easily add scopes to your route by passing in the `scopes` property to the `auth` function.

Scopes takes in an array of objects with the `representation` and optional `read`, `create`, `update`, and `del` properties.

So to check if the key has *read* and *create* access attached to *profile* scope, we can modify our code as below

```typescript api/profile/route.ts theme={null}
export const GET = oneloop.auth(
  async (request: Request) => {
    return new Response("Profile Endpoint Authenticated");
  },
  {
    scopes: [
      {
        representation: "profile",
        read: true,
        create: true,
      },
    ],
  }
);
```

## Handling Errors

You can also pass in a custom handlers in econd argument to the `auth` function for handling errors and invalid keys.
There are 2 types of handlers you can pass in: `onError` and `onInvalidKey`.

### `onInvalidKey()`

This function will be called if the user's API key is invalid, rate limited, reached usage limit, or does not have the required scopes

```typescript api/profile/route.ts theme={null}
export const GET = oneloop.auth(
  async (request: Request) => {
    return new Response("Profile Endpoint Authenticated");
  },
  {
    scopes: [
      {
        representation: "profile",
        read: true,
        create: true,
      },
    ],
    onInvalidKey: async (request, error) => {
      return new Response("Invalid Key: " + err.message, { status: err.code });
    },
  }
);
```

### `onError()`

This function will be called if there is an error while verifying the user's API key. Possible scenario can be if you passed in the wrong Oneloop SDK Key

```typescript api/profile/route.ts theme={null}
export const GET = oneloop.auth(
  async (request: Request) => {
    return new Response("Profile Endpoint Authenticated");
  },
  {
    scopes: [
      {
        representation: "profile",
        read: true,
        create: true,
      },
    ],
    onError: async (request, error) => {
      return new Response("Error while verifying API key", { status: 500 });
    },
  }
);
```
