# Create a Personal Access Token

> Source: https://agilitycms.com/docs/developers/create-personal-access-token

A Personal Access Token (PAT) lets the Agility CLI, your own scripts and a CI pipeline call the Management API without opening a browser to sign in. There's no screen for tokens in the Agility app yet, so you create one by calling the Management API once, signed in as yourself. These steps take about five minutes.

A token acts as the user who created it, with that user's permissions on every instance they can reach. It expires on the date you set, at most two years after you create it, and each user can have up to 10 active tokens. A token is tied to the user who created it: when that user is suspended or removed, their tokens stop working.

## Before you start

- **The Agility CLI 1.2.** Install it with `npm install -g @agility/cli`, or run it with `npx @agility/cli`. You use it only to sign in.
- **A macOS or Linux terminal** with `curl` and `python3`. The commands in step 2 read the CLI's stored sign-in from the system keychain, and they're written for macOS and Linux.
- **An Agility user with access to the instances** the token will work with. The token gets that user's permissions, so use the account your automation should act as.

## Steps

### 1. Sign in with the CLI

```bash
agility login
```

A browser window opens at Agility's sign-in page, and the CLI waits up to 60 seconds for you to finish. When you do, the CLI stores the sign-in in your system keychain and prints `You are now logged in`. Carry on with the next steps straight away, because the stored sign-in expires.

If you've stored a Personal Access Token with the CLI on this machine before, run `agility logout` first. Otherwise `agility login` uses the stored token and doesn't open the browser.

### 2. Copy the sign-in token into a shell variable

On macOS:

```bash
AGILITY_OAUTH=$(security find-generic-password -s "agility-cli" -a "cli-auth-token:prod" -w \
  | python3 -c "import sys, json; print(json.load(sys.stdin)['access_token'])")
```

On Linux (GNOME Keyring or another Secret Service keyring):

```bash
AGILITY_OAUTH=$(secret-tool lookup service agility-cli account cli-auth-token:prod \
  | python3 -c "import sys, json; print(json.load(sys.stdin)['access_token'])")
```

macOS may ask for permission to read the keychain item. Check the variable is set without printing it:

```bash
test -n "$AGILITY_OAUTH" && echo "Signed in" || echo "No sign-in found: run agility login again"
```

### 3. Set the Management API URL for your region

Use the URL for the region your instances are in. The last characters of an instance GUID tell you the region:

| GUID ends in | Management API URL |
| --- | --- |
| `u` | `https://mgmt.aglty.io` |
| `us2` | `https://mgmt-usa2.aglty.io` |
| `c` | `https://mgmt-ca.aglty.io` |
| `e` | `https://mgmt-eu.aglty.io` |
| `a` | `https://mgmt-aus.aglty.io` |

```bash
AGILITY_MGMT="https://mgmt.aglty.io"
```

If your instance GUID has no region letter at the end, contact Agility Support to confirm its region.

### 4. Create the token

Give the token a name that says what it's for, and an expiry date:

```bash
curl -s -X POST "$AGILITY_MGMT/api/v1/tokens/create" \
  -H "Authorization: Bearer $AGILITY_OAUTH" \
  -H "Content-Type: application/json" \
  -d '{ "Name": "ci-content-sync", "ExpiryDate": "2027-10-29T00:00:00Z" }'
```

- `Name` is required: 1 to 100 characters, and different from your other tokens' names.
- `ExpiryDate` is optional. Leave it out and the token expires two years from now, which is the longest allowed.

### 5. Copy the token from the response

A successful request returns status `201` and a body like this:

```json
{
  "tokenID": "550e8400-e29b-41d4-a716-446655440000",
  "name": "ci-content-sync",
  "expiryDate": "2027-10-29T00:00:00Z",
  "createdDate": "2026-10-29T14:02:11Z",
  "enabled": true,
  "lastUsedDate": null,
  "isExpired": false,
  "daysUntilExpiration": 364,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "notice": "This is the only time you will see this token. Please save it securely."
}
```

Copy the `token` value now. The API never returns it again, so if you lose it, delete the token and create a new one. Keep the `tokenID`: you need it to rename, disable or delete the token later.

### 6. Store the token and clear the sign-in

Save the token as a secret in your CI system or password manager, then remove the sign-in token from your shell:

```bash
unset AGILITY_OAUTH
```

## Use the token

With the CLI, pass the token as `--token` or set `AGILITY_TOKEN`:

```bash
AGILITY_TOKEN="<your token>" agility pull --sourceGuid="<instance guid>" --headless
```

Your own scripts send it to the Management API in the `Authorization` header, as `Bearer <your token>`.

For pipelines, see the [CLI CI/CD Integration Guide](/docs/developers/cli-ci-cd-integration-guide). For how the CLI picks which credential to use, see [Authentication](/docs/developers/cli-reference#authentication) in the CLI command reference.

## Manage your tokens

Token management also needs the browser sign-in from steps 1 and 2: a token can't create, list or change tokens. With `AGILITY_OAUTH` and `AGILITY_MGMT` set:

```bash
# List your tokens (names, expiry dates, last use; never the token values)
curl -s "$AGILITY_MGMT/api/v1/tokens/list" -H "Authorization: Bearer $AGILITY_OAUTH"

# Rename a token, or disable it with "Enabled": false
curl -s -X PUT "$AGILITY_MGMT/api/v1/tokens/<tokenID>/update" \
  -H "Authorization: Bearer $AGILITY_OAUTH" \
  -H "Content-Type: application/json" \
  -d '{ "Enabled": false }'

# Delete a token you no longer need
curl -s -X DELETE "$AGILITY_MGMT/api/v1/tokens/<tokenID>/delete" \
  -H "Authorization: Bearer $AGILITY_OAUTH"
```

## Limits

| Limit | Value |
| --- | --- |
| Active tokens per user | 10 |
| Longest expiry | 2 years from creation |
| Token creations | 5 an hour |
| List requests | 10 a minute |

Going over a limit returns status `429` with a message that says which one.

## Troubleshooting

| What you see | What to do |
| --- | --- |
| `security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.` | You aren't signed in. Run `agility login` again |
| `401` from `tokens/create` | The sign-in has expired, or `AGILITY_OAUTH` is empty. Repeat steps 1 and 2 |
| `403` from `tokens/create` | You sent a Personal Access Token instead of the browser sign-in. Tokens can't create tokens |
| `400` | The name is missing or longer than 100 characters, or the expiry date is more than two years away |
| `429` | You've reached 10 active tokens or 5 creations in the last hour. Delete a token you don't use, or wait |

## Related

- [Personal Access Tokens](/docs/developers/personal-access-tokens): what tokens are and the rules that apply to them
- [Agility CLI](/docs/developers/cli)
- [CLI CI/CD Integration Guide](/docs/developers/cli-ci-cd-integration-guide)

---

## Related pages

- [Content Fetch API](https://agilitycms.com/docs/developers/content-fetch-api.md)
- [Content Sync API](https://agilitycms.com/docs/developers/content-sync-api.md)
- [Content Management API](https://agilitycms.com/docs/developers/content-management-api.md)
- [GraphQL API](https://agilitycms.com/docs/developers/graphql-api.md)
- [CLI - CI/CD Integration Guide](https://agilitycms.com/docs/developers/cli-ci-cd-integration-guide.md)
- [Testing on Swagger](https://agilitycms.com/docs/developers/testing-on-swagger.md)
- [GraphQL & Rest API Filtering](https://agilitycms.com/docs/developers/graphql-operators.md)
- [AgilityCLI (Command Line Interface)](https://agilitycms.com/docs/developers/cli.md)
- [Personal Access Tokens](https://agilitycms.com/docs/developers/personal-access-tokens.md)
- [Content Delivery & CDN Architecture](https://agilitycms.com/docs/developers/content-delivery-and-cdn-architecture.md)
- [Image Transformation Reference](https://agilitycms.com/docs/developers/image-transformation-reference.md)
- [Fetch API Status Codes and Caching](https://agilitycms.com/docs/developers/fetch-api-status-codes-and-caching.md)
- [Field Types and What the APIs Return](https://agilitycms.com/docs/developers/field-types-api-reference.md)
- [Content Sync Explained](https://agilitycms.com/docs/developers/content-sync-explained.md)
- [Agility CLI Command Reference](https://agilitycms.com/docs/developers/cli-reference.md)
- [CLI Reference: agility pull](https://agilitycms.com/docs/developers/cli-pull.md)
- [CLI Reference: agility sync and push](https://agilitycms.com/docs/developers/cli-sync.md)
- [CLI Reference: agility reverse-sync](https://agilitycms.com/docs/developers/cli-reverse-sync.md)
- [CLI Reference: agility workflows](https://agilitycms.com/docs/developers/cli-workflows.md)
- [CLI Reference: agility login and logout](https://agilitycms.com/docs/developers/cli-login-logout.md)
- [Test Your Agility Integration in CI](https://agilitycms.com/docs/developers/test-agility-integration-in-ci.md)
- [CLI Reference: agility verify](https://agilitycms.com/docs/developers/cli-verify.md)

Index of every docs page: https://agilitycms.com/docs/llms.txt
