# API keys and roles

> Create Kustomer API keys, understand machine users and role naming, and pick least-privilege roles for common integrations.

Source: https://developer.kustomer.com/docs/get-started/api-keys-and-roles

API keys are the standard way to authenticate server-side integrations. Each key is a long-lived bearer token tied to a machine user and a fixed set of roles.

## Create a key

#### Open the API keys page

Go to **Settings › Security › API Keys** and select **Add API Key**. You need admin access.

#### Name it after the integration

Use names such as `netsuite-sync-prod` so the machine user is recognizable on timelines and in audit logs.

#### Choose roles

Select every role the integration needs. **Roles can't be edited later.** To change them, create a new key.

#### Set expiry and IP restriction

Choose an expiry in days, or no expiry. Optionally, restrict the key to a CIDR range such as `203.0.113.0/24` so it only works from your servers.

#### Copy the token

The token is displayed once. Put it straight into your secrets manager.

_Figure: The Add API Key dialog in Kustomer settings with fields for name, roles, expiry and IP restriction. Settings › Security › API Keys › Add API Key._

## Machine users

Every key is backed by a **machine user**. Anything the key creates or updates shows that user as the author, so agents can see that "netsuite-sync-prod" updated an order rather than a person.

You can give the machine user an avatar so its activity is easy to recognize on timelines:

`PUT /v1/users/{id}` ([reference](https://developer.kustomer.com/api/access-management/update-user-by-id))

```bash title="cURL"
curl -X PUT "https://acme.api.kustomerapp.com/v1/users/$MACHINE_USER_ID" \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "avatarUrl": "https://cdn.example.com/netsuite.png" }'
```

Find the machine user's ID with `GET /v1/users/current` using the key itself.

## How roles are named

Roles are dot-separated strings that read from broad to specific:

```text
org . permission . customer . create
│     │            │          └─ action: read, create, update, delete (or write)
│     │            └─ resource: customer, conversation, kobject, klass, ...
│     └─ family: permission, user or admin
└─ scope: your org
```

| Family                 | Example                          | What it grants                                                                                         |
| ---------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `org.permission.*`     | `org.permission.customer.create` | One action on one resource. The most precise option and the one to prefer.                             |
| `org.user.*` (legacy)  | `org.user.customer.write`        | What an agent can do with a resource. `.write` usually covers create, update and delete, but not read. |
| `org.admin.*` (legacy) | `org.admin.klass.write`          | Admin-level configuration such as Klasses, schedules and metadata.                                     |

A role without an action, such as `org.user.brand`, grants every action in that family for the resource.

### Legacy roles

`org.user.*` and `org.admin.*` roles predate permission sets. They still work, and existing keys that hold them keep their access. For new keys, prefer `org.permission.*` roles: they grant one action at a time, so a key gets only what it needs.

In the API reference, legacy roles are listed after the others under a **Legacy** label, with a dashed outline. Most operations accept either kind, so you can switch a key to permission-set roles without losing access. A few accept only a legacy role, and their Authorization block says so. In [`/api/operations.json`](https://developer.kustomer.com/api/operations.json), each operation's `legacyRoles` lists which of its `roles` are legacy.

### Reading the roles on a reference page

Every operation in the [API reference](https://developer.kustomer.com/api) has an **Authorization** block, taken from the checks the API gateway enforces. Most list roles, usually in pairs of a [legacy role](#legacy-roles) and its permission-set equivalent. **Any one** of the listed roles is enough. For example, [Create customer](https://developer.kustomer.com/api/core-resources/create-customer) accepts `org.user.customer.write` or `org.permission.customer.create`.

A few operations show something else instead:

| Authorization block                         | Meaning                                                                                                                                              |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Any API key or signed-in user               | No specific role. Any valid credential works, for example [Get current user](https://developer.kustomer.com/api/access-management/get-current-user). |
| The token itself, or any one of these roles | A token can always read or revoke itself. Acting on another token needs one of the listed roles.                                                     |
| No authentication                           | Public. Send no `Authorization` header, as with the public knowledge base endpoints.                                                                 |

The same information is in each operation's Markdown twin and in [`/api/operations.json`](https://developer.kustomer.com/api/operations.json) (`access` and `roles`), so scripts and agents can check a key's roles before calling.

## Least-privilege recipes

| Integration                     | Roles                                                                                                                                                                |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Read-only reporting export      | `org.permission.customer.read`, `org.permission.conversation.read`, `org.permission.message.read`, `org.permission.search.create`                                    |
| CRM customer sync               | `org.permission.customer.read`, `org.permission.customer.create`, `org.permission.customer.update`, `org.permission.company.create`, `org.permission.company.update` |
| Order lookup via custom objects | `org.permission.kobject.read`, `org.permission.kobject.create`, `org.permission.kobject.update`, `org.permission.customer.read`                                      |
| Custom messaging channel        | `org.permission.customer.read`, `org.permission.customer.create`, `org.permission.conversation.create`, `org.permission.message.create`                              |
| Webhook and app administration  | `org.admin.apps` and the roles for any resources the app reads or writes                                                                                             |

Check each endpoint's reference page before relying on a recipe: the listed roles there are authoritative.

## Special-purpose keys

| Role           | Purpose                                                                                                                                                   |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `org.tracking` | Chat SDK keys. A chat key must have **exactly this one role**. Safe to embed in web pages and apps. See [Chat](https://developer.kustomer.com/docs/chat). |
| `org.hooks`    | Hook access, for systems that post into Kustomer hooks. See [Inbound webhooks](https://developer.kustomer.com/docs/events/inbound-webhooks).              |

List the top-level roles available to your org with:

`GET /v1/auth/roles` ([reference](https://developer.kustomer.com/api/access-management/get-auth-roles))

## Rotating keys

Keys can't be edited, so rotation means replacing:

1. Create a new key with the same roles.
2. Deploy it alongside the old one, then switch traffic over.
3. Watch the old key's last-used time in **Settings › Security › API Keys** (also in `lastAccessedAt` from `GET /v1/auth/tokens/current`) until it stops changing.
4. Delete the old key.

> **Expiring keys:** For anything that isn't a long-running production integration, set an expiry. A forgotten key that expired is not a key that leaked.
