# Users and API keys

> CREATE, ALTER and DROP USER and API KEY — the SQL statements that manage password logins and API keys on a NYXDB node.

Users and API keys are managed with credential statements. The gateway
classifies these statements before query history and before the relational
parser, so they never reach the query compiler and history records only their
redacted form. For how the resulting logins work, see
[Authentication](/docs/concepts/authentication).

## Where credential statements run

- On an account session, over HTTP `POST /sql` or a WebSocket session.
- Application sessions read and subscribe; credentials are managed on account sessions.
- Managing another principal's users or keys needs the `credential_manage`
  administrative permission; a user may create their own API key.

## Grammar

| Statement | Effect |
| --- | --- |
| `CREATE USER name [KIND HUMAN \| SERVICE] PASSWORD ?` | Creates a user with a password. `KIND` defaults to `HUMAN`. |
| `ALTER USER name PASSWORD ?` | Replaces the password. |
| `ALTER USER name ENABLE \| DISABLE` | Enables or disables the user. |
| `DROP USER name` | Disables the user (the same as `ALTER USER name DISABLE`). |
| `CREATE API KEY label FOR USER name [EXPIRES IN n HOURS \| DAYS]` | Creates an API key and returns its secret once. |
| `ALTER API KEY label FOR USER name ENABLE \| DISABLE` | Enables or disables the key. |
| `DROP API KEY label FOR USER name` | Disables the key. |

A password is passed as a bound parameter, `PASSWORD ?`, so it never appears
in statement text or history. Names may be quoted (`"Data Team"`).

## Create a user

```sql
CREATE USER analyst PASSWORD ?;
```

The password travels as the statement's parameter. User names are unique, and
passwords have a minimum length. The new user can log in at `POST /auth/password` at once but holds no
permission until a role grants one; see [Governance](/docs/operations/governance).

A service principal is declared with `KIND SERVICE`:

```sql
CREATE USER analyst KIND SERVICE PASSWORD ?;
```

## Rotate a password

```sql
ALTER USER analyst PASSWORD ?
```

After the rotation the new password logs in, and the session opened with the
old password ends.

## Disable and re-enable a user

```sql
DROP USER reporter
```

```sql
ALTER USER reporter ENABLE
```

`DROP USER` ends every session of the user and disables its password and API
keys. `ALTER USER … ENABLE` lets the user log in again.

## Create an API key

```sql
CREATE API KEY reporting FOR USER analyst EXPIRES IN 30 DAYS
```

The result is one row whose `api_key` column holds the secret, a string that
starts with `nyxk1.`. It is returned once and never stored in readable form.
Exchange it for a bearer at `POST /auth/api-key`.

- `EXPIRES IN` takes a positive count of `HOURS` or `DAYS`, up to ten years.
- Key labels are unique per user.

## Disable an API key

```sql
DROP API KEY reporting FOR USER analyst
```

After the drop the key no longer exchanges for a bearer, and the sessions it
opened end on their next operation (401). Sessions opened with the user's
password keep working.

## Observe credentials

`system.credentials` lists the credentials of each principal with their kind
(for example password and API key) and status. It carries no digest, salt or
secret. See [System relations](/docs/operations/system-tables).

---

Source: https://nyxdb.io/docs/sql/users-and-keys/
