---
sidebar_label: Personal access tokens
toc_max_heading_level: 3
doc_id: 7e5a1df2-bec4-4dad-b7f0-8e68dea2cb36
description: >-
  Create personal access tokens that act as you from the CLI, your own scripts,
  or an AI assistant. A token follows your access or a set of grants you choose,
  and it can never do more than you.
keywords:
  - personal access tokens
  - PAT
  - user settings
  - API keys
  - access tokens
  - MCP
  - authentication
title: Personal access tokens
canonical: 'https://docs.nullplatform.com/docs/authorization/personal-access-tokens'
---
# Personal access tokens

A personal access token acts as you from the CLI, your own scripts, or an AI assistant connected through the [MCP server](/docs/mcp-server). Whatever access you give it, it can never do more than you can.

## When to use one

Use a personal access token when a script or an agent should act **as you**: your own scripts, your local tools, or an AI assistant. What it does is traceable to you, and it stops working when you lose the access it relies on.

For automation that runs without you, or that shouldn't depend on one person, like a team's CI pipeline, use an [API key](/docs/authorization/api-keys) instead. It belongs to a machine user, so it keeps working when people join or leave the team.

> **Note:** The **Copy session token** option in your user menu is something else: it copies the short-lived token of your current login, for a quick API call.

## What a token can do

When you create a token, you choose its access:

- **Same access as me**: the token follows your access in the organization. Roles you get later are added, and roles you lose stop working for the token right away.
- **Choose grants**: the token gets only the resources, roles, or permissions you pick. Each grant works like an [API key grant](/docs/authorization/api-keys#how-api-keys-fit-into-authorization): a resource, plus roles, roles adjusted by hand, or hand-picked permissions.

Either way, every check combines the token's access with **yours at that moment**. If you lose a role, the tokens that rely on it lose it too, and if your user is deactivated, all your tokens stop working.

You can only grant what you hold yourself: roles you have on that resource or one above it, and permissions you have there.

## Using the UI

Open your user menu (your initials, top right) and select **User settings**. Walk through the page below:

<GuidedTour
  alt="User settings, recreated as an HTML scene with a step-by-step walkthrough of personal access tokens"
  steps={[
    {
      title: '1. Find your tokens',
      body: 'Every token that acts as you, including the ones AI agents get when you connect them. Show access says what each one can do, and ⋮ edits or deletes it. Click New token to create one.',
      anchor: 'pat-list',
      placement: 'top',
    },
    {
      title: '2. Name it and set when it expires',
      body: 'Use a name that says where the token runs. A token lives a year at most: you can extend it later, but never shorten it.',
      anchor: 'pat-identification',
      placement: 'bottom',
    },
    {
      title: '3. Choose what it can do',
      body: 'Same access as me follows your roles as they change. Choose grants limits it to the resources, roles, or permissions you pick.',
      anchor: 'pat-access',
      placement: 'top',
      align: 'end',
    },
    {
      title: '4. Generate it and copy it right away',
      body: "The token is shown only once. Copy it and store it somewhere safe before closing this dialog: it can't be retrieved later.",
      anchor: 'pat-created',
      placement: 'bottom',
    },
  ]}
>
  <UserSettingsScene />
</GuidedTour>

:::warning Save your token securely
The token is **displayed only once**, right after you generate it. Copy it and store it in a secure location, as it cannot be retrieved later.
:::

To change a token, open its **⋮** menu and click **View or edit**. You can rename it, change its access and tags, and extend its expiration. **Delete** removes it for good, and whatever uses it stops working right away.

A token shows **Expiring soon** in its last 7 days. Once it expires, you can't edit it or extend it anymore, only delete it.

## Using the API

You manage personal access tokens with your own login session, never with an API key: requests authenticated by any API key, a personal access token included, are rejected. To get a session token for these requests, open your user menu and click **Copy session token**.

The CLI has no commands for personal access tokens, so the examples below use cURL.

### Create a token

Send a [POST request](/docs/api/pat-create) to `https://api.nullplatform.com/pat`. This one creates a token with your own access:

```bash
curl -L -X POST 'https://api.nullplatform.com/pat' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{
    "name": "local-scripts",
    "expires_at": "2027-01-06T00:00:00Z",
    "access": "same_as_user",
    "tags": [
      { "key": "team", "value": "platform" }
    ]
  }'
```

Where:

- `expires_at` is required. It must be in the future and at most a year away.
- `access` is `same_as_user` for a token that follows your access, or `grants` (the default) for one limited to the grants you send.

To limit the token instead, send `grants` with `access` set to `grants`. A grant has the same shapes as in an [API key](/docs/authorization/api-keys#grant-access-to-api-keys): a role, custom actions, or roles adjusted with `inherits`. This one can only read what's in one account:

```json
{
  "name": "read-only-reports",
  "expires_at": "2027-01-06T00:00:00Z",
  "access": "grants",
  "grants": [
    { "nrn": "organization=1:account=2", "role_slug": "member" }
  ]
}
```

You'll receive a `201` response like this:

```json
{
  "id": 1234,
  "name": "local-scripts",
  "api_key": "AAAA.1234567890abcdef1234567890abcdefPTs=",  // Your new token.
  "masked_api_key": "AAAAxxxxxPTs=",
  "access": "same_as_user",
  "tags": [
    { "key": "team", "value": "platform" }
  ],
  "grants": [
    { "id": 5678, "nrn": "organization=1:account=2", "role_id": 700317756, "role_slug": "developer" }
  ],
  "personal": true,
  "owner_id": 42,
  "acting_user_id": 42,
  "last_used_at": null,
  "expires_at": "2027-01-06T00:00:00.000Z",
  "expired": false,
  "created_at": "2026-10-08T00:00:00.000Z",
  "updated_at": "2026-10-08T00:00:00.000Z"
}
```

Where:

- `api_key` is your new token. It's returned only in this response.
- `grants` is what the token can do. For a `same_as_user` token, those are your own grants at this moment.
- `acting_user_id` is you: the user the token acts as.

:::warning Save your token securely
The token is **displayed only once**. Make sure to store it in a secure location, as it cannot be retrieved later.
:::

### Use the token

A personal access token works like an API key: exchange it for an access token with a [POST request](/docs/api/access-token-create) to `https://api.nullplatform.com/token`. See [Generate an access token](/docs/authorization/api-keys#generate-an-access-token).

```bash
curl -L -X POST 'https://api.nullplatform.com/token' \
  -H 'Content-Type: application/json' \
  -d '{
    "api_key": "AAAA.1234567890abcdef1234567890abcdefPTs="
  }'
```

Tools that take an API key, like the `np` CLI with `--api-key` or the MCP server's `X-API-Key` header, take a personal access token too.

### List your tokens

Send a [GET request](/docs/api/pat-list) to `https://api.nullplatform.com/pat`. You only ever see your own tokens:

```bash
curl -L 'https://api.nullplatform.com/pat?search=mcp&status=active,expiring_soon&sort=name:asc' \
  -H 'Authorization: Bearer <token>'
```

These query parameters are all optional:

- `search` matches a token's name, or the key or value of one of its tags.
- `status` takes one or more of `active`, `expiring_soon` (expires within 7 days), and `expired`, separated by commas.
- `expires_at:range` takes two dates, `from,to`. `expires_at:gte` and `expires_at:lte` take one.
- `sort` is `name:asc`, `name:desc`, `last_used_at:asc_nulls_last`, or `last_used_at:desc_nulls_last`.
- `limit` (30 by default, 100 at most) and `offset` page through the results.

### Update a token

Send a [PATCH request](/docs/api/pat-update) to `https://api.nullplatform.com/pat/<id>` with what you want to change: `name`, `tags`, `access`, `grants`, or `expires_at`.

```bash
curl -L -X PATCH 'https://api.nullplatform.com/pat/1234' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{
    "expires_at": "2027-04-06T00:00:00Z"
  }'
```

A few rules apply:

- `expires_at` can only move later, up to a year from now. An expired token can't be extended.
- `grants` replaces all of the token's grants.
- Switching to `same_as_user` drops the token's grants. Switching back to `grants` requires the grants it should have.

### Delete a token

Send a [DELETE request](/docs/api/pat-delete) to `https://api.nullplatform.com/pat/<id>`:

```bash
curl -L -X DELETE 'https://api.nullplatform.com/pat/1234' \
  -H 'Authorization: Bearer <token>'
```

You'll receive a `204` response. The token stops working right away, including any access token already issued with it.

## Next steps

- [Connect an AI assistant](/docs/mcp-server): the MCP server creates a personal access token for each connection
- [Manage your API keys](/docs/authorization/api-keys): keys for shared automation that belong to a machine user
- [Roles](/docs/authorization/roles): what each role allows
