# Authentication

The Paymee gateway uses **two distinct credentials**. Keep both server-side and
never expose them in browser or mobile clients.

| Credential | Format | Where it's used |
| --- | --- | --- |
| **Secret API key** | `sk_live_…` (live mode), `sk_test_…` (test mode) | The `Authorization` header on every API request |
| **Webhook secret** | `whsec_…` | Verifying the signature on webhooks you receive — see [Webhooks](/guides/webhooks/) |

Both are issued from your **Paymee merchant dashboard**:

- **Test keys** (`sk_test_…`) are available in the dashboard and can be retrieved
  while you build.
- **Live keys** (`sk_live_…`) require an approved business verification (KYB) and
  are shown **once** at creation — store them securely (e.g. a secrets manager)
  and rotate from the dashboard if lost.

## Authorize a request

Pass your secret key as a Bearer token:

```http
POST /api/v1/gateway/sessions/ HTTP/1.1
Host: api.paymee.online
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
```

## Test vs. live is decided by the key

There is **one base URL** for everything:

```
https://api.paymee.online/api/v1
```

You do **not** use a separate host for testing — the **key prefix determines the
mode** on the same host:

- `sk_test_…` → **test mode** (no real money; use [test cards](/guides/testing/)).
- `sk_live_…` → **live mode** (real payments).

:::caution
Treat secret keys like passwords. Don't commit them to source control, embed
them in front-end code, or log them. Rotate immediately if exposed.
:::

## Errors

A missing, malformed, expired, or revoked key returns `401 Unauthorized` as an
[RFC 9457 problem document](/guides/errors/):

```json
{
  "type": "https://api.paymee.online/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Invalid or expired API key."
}
```

Source: https://docs.paymee.online/guides/authentication/
