---
updatedAt: 2026-10-27T09:32:01.000Z
agentTools:
  projectIndex: https://developers.solidstudio.io/llms.txt
---

# Authorization

# Public API — Authentication

Every Public API request is authenticated with an **API key** and authorized against the **permissions** granted to that key through roles. This guide covers the headers, key lifecycle, and the permission model.

## Obtaining the key

Public API keys are self-managed and can be generated by Administrators directly in Solidstudio CPMS Admin Panel. Navigate to General Settings -> API Keys -> Generate API Key to create a new API Key

## Sending the key

Pass the key in the `x-api-key` header:

```bash
curl -s \
  -H "x-api-key: $API_KEY" \
  "https://<host>/api/v1/charging-stations"
```

The raw `Authorization: <key>` header (no `Bearer` prefix) is still accepted for backwards compatibility only. Migrate to `x-api-key`.

## Key lifecycle

* Keys are provisioned by a platform administrator and shown **once** at creation — only a bcrypt hash and a 4-character preview are stored server-side. Store the key in a secrets manager; it cannot be recovered later.
* Keys have an **expiry date**. An expired key is deactivated on its first use after expiry and all subsequent requests return `401`.
* **Legacy keys** still work but are deprecated. Responses authenticated with one carry the header:

  ```
  X-API-Deprecation: This API key uses a deprecated format. Please rotate to a new key.
  ```

  Rotate to a new key when you see it.

### Authentication failures

| Response           | Cause                                                                    |
| ------------------ | ------------------------------------------------------------------------ |
| `401 Unauthorized` | Header missing, key unknown, key deleted, or key expired                 |
| `403 Forbidden`    | Key valid, but its roles do not grant the endpoint's required permission |

## Permission model

Authorization is role-based:

```mermaid
flowchart LR
    K[API key] -->|has many| R[Roles]
    R -->|grant| P["Permissions<br/>resource:action"]
    P -->|checked per endpoint| E["Endpoint<br/>@RequirePermission"]
```

* Permissions are flat strings in `resource:action` form, e.g. `session:read`, `charging-station:remote-control`, `webhook:manage`.
* Every endpoint declares the permission it requires.
* A key's effective permissions are the union of all its roles' permissions.

Grant keys the minimum set they need: a monitoring integration needs `session:read` + `cdr:read`, not `system:root`.

### Discovering permissions and roles

With a key that has `system:manage-iam`:

```bash
# All permission names known to the system
curl -s -H "x-api-key: $API_KEY" "https://<host>/api/v1/iam/permissions"

# Roles, optionally with their permissions
curl -s -H "x-api-key: $API_KEY" "https://<host>/api/v1/iam/roles?include=permissions"
```

### Managing roles via the API

The IAM endpoints (`/api/v1/iam`, permission `system:manage-iam`) support the full role lifecycle:

| Operation                  | Endpoint                                            |
| -------------------------- | --------------------------------------------------- |
| Create role                | `POST /iam/roles`                                   |
| Update role                | `PATCH /iam/roles/:id`                              |
| Delete role                | `DELETE /iam/roles/:id`                             |
| Replace role permissions   | `PUT /iam/roles/:id/permissions`                    |
| Add permissions            | `POST /iam/roles/:id/permissions`                   |
| Remove one permission      | `DELETE /iam/roles/:id/permissions/:permissionName` |
| Assign roles to an API key | `/api-keys` endpoints                               |
| Assign roles to a user     | `/users` endpoints                                  |

Two safety rules apply:

* **System roles are immutable** — built-in roles cannot be edited or deleted (`403`).
* **Grant ceiling** — a caller can only grant permissions it holds itself; adding a permission your own key lacks is rejected.

## Security recommendations

* Call the API host-to-host only; never embed keys in client-side code.
* Use one key per integration so keys can be rotated and revoked independently, and usage attributed (`lastUsedAt` is tracked per key).
* Set expiry dates and rotate before them; treat `X-API-Deprecation` as an action item.

<br />