# Authentication and keys

Every request is signed with an organization API key. The key defines exactly what you can read: permissions, workspaces, campaigns and message text.

## How to pass the key

Pass the key in the `Authorization` header with the `Bearer` scheme:

```http
GET /v1/me HTTP/1.1
Host: api.melioralab.io
Authorization: Bearer mel_live_AbCdEfGhIjKlMnOpQrStUvWxYz012345
```

A key looks like `mel_live_` followed by 32 Latin letters or digits. Session cookies from the Meliora app and other sign-in methods don't replace the key. A request with no key or an invalid key gets 401 `invalid_api_key`. After 20 responses with status 401 within 5 minutes, the IP address is blocked for 15 minutes, so don't retry an invalid key in a loop.

The key is not accepted in the request URL: a parameter like `?api_key=...` returns 400 `unknown_parameter`. If a key ever ends up in a URL, a proxy log or browser history, rotate it.

## Get access

The API is in early access, and keys are issued on request. Contact [Support](https://docs.melioralab.io/en/support/) and tell us which permissions, scope, expiration and IP addresses you need. We will enable API access for your organization, issue a key and help you with your first request. The full key is shared only once.

When the API section is enabled for your organization, keys are managed by an **Owner or Admin** with access to every workspace and campaign in the organization. Other members can view the section but can't change anything.

1. Open **Settings › Integrations**, then the **API** block.
2. If access is turned off, click "Enable API".
3. Click "Create key" and set a name, permissions and scope. Optionally, set an expiration date and allowed IP addresses.
4. Copy the key from the "The key will be shown only once" dialog.

API read access is available on the Pro plan and above. If your plan is lower, your subscription is inactive or your organization's access is suspended, requests get 403 with a reason code: `api_not_available`, `subscription_inactive` or `organization_suspended`.

An organization can have up to 10 active keys. This count includes keys that are still preparing and old keys during a rotation overlap period.

## Permissions

You choose permissions when you create a key and can change them with the "Edit" button.

| Permission | In Meliora | What it unlocks |
|---|---|---|
| `campaigns:read` | Campaigns | `GET /v1/campaigns`, `GET /v1/campaigns/{id}` |
| `leads:read` | Leads | `GET /v1/leads`, `GET /v1/leads/{id}` |
| `messages:read` | Conversations | `GET /v1/leads/{id}/messages` and message text in events |
| `events:read` | Events | `GET /v1/events` |

`GET /v1/me` and `GET /v1/workspaces` work with any set of permissions.

**Message text** is returned only if the key has the `messages:read` permission **and** the "Message text" checkbox is selected. The checkbox is off by default. Without it, `GET /v1/leads/{id}/messages` and event requests with `include_text=true` get 403 `scope_required`.

## Scope

Scope limits what data the key can see:

- **Workspaces:** all existing items or selected ones, up to 50.
- **Campaigns:** all campaigns in the selected workspaces or selected ones, up to 500.
- **Include future items:** when the scope is set to all items, the key also sees workspaces or campaigns created later. If you clear this checkbox, the scope is fixed to what exists at the moment you save it.

To the key, an object outside its scope does not exist: a request for it returns 404 `not_found`, just like a request for an object that doesn't exist. You can read the key's current scope in the `scope` field of the [`GET /v1/me`](https://docs.melioralab.io/en/reference/api-context/) response.

## Expiration and IP addresses

- **Expiration** is set in UTC. Once it passes, the key gets 401 `invalid_api_key`. Leave the field empty for a key that never expires. The expiration is returned in the `expires_at` field of `GET /v1/me`.
- **Allowed IPs** are set as addresses or CIDR ranges, IPv4 or IPv6, up to 50 entries. A request from any other address gets 403 `ip_not_allowed`. Leave the field empty to allow any address.

## New key preparation

Right after you create or rotate a key, it may be in the Preparing state. During this time, requests get 503 `integration_initializing` with a `Retry-After` header. Retry after the specified time. Preparation takes no longer than 15 minutes. If the key isn't ready by then, its state changes to Not prepared and requests get 401: issue a new key or contact Support.

## Rotation

The "Rotate" button issues a new secret with the same permissions and scope. Choose an overlap period:

| Overlap | What happens to the old key |
|---|---|
| No overlap | Revoked immediately |
| One day | Keeps working for 24 hours |
| Seven days | Keeps working for 7 days |

The overlap lets you update the key on all your servers with no downtime. Cursors issued to the old key keep working with the new one, as long as permissions and scope haven't changed.

## Editing and revoking

- **Changes** to permissions, scope or the "Message text" checkbox take effect immediately. Cursors issued before the change return 400 `cursor_mismatch` afterward: restart the list, and for the event feed, follow the [recovery steps](https://docs.melioralab.io/en/events-polling/#vosstanovlenie).
- **Revoking** stops the key immediately and permanently. You can't undo a revocation.
- **Disable API** turns off access for the whole organization with one button in the same section. While access is off, all keys get 403 `api_disabled`.

## Request log

The "Log" button next to a key shows the requests from the last 14 days: time, endpoint, status, error code and duration. Support can find a specific request by its `Request-Id` from the log.

## Storing your key

The key gives access to your organization's data. Treat it like a password:

- keep it in a secrets manager or in server environment variables, not in your repository;
- call the API only from a server: the key must never reach a browser or a mobile app;
- don't write the key to logs; to identify it, use its prefix and last 4 characters, which are shown in Meliora;
- give each integration its own key with the minimum permissions and scope it needs;
- if you suspect a leak, revoke the key immediately or rotate it with no overlap.
