> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mannco.store/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> API key login (POST /user/login), JWT usage, Authorization header, and errors

## API login (`POST /user/login`)

Use this to obtain a JWT for all documented routes that require **Connected + API**.

<Card title="POST /user/login" icon="key">
  Exchanges an **API key** for a **JWT** used on subsequent calls.
</Card>

```
POST https://api.mannco.store/user/login
```

**Authentication:** none (you send the key in the body).

### Request body

The router accepts **JSON** (`Content-Type: application/json`) or **`application/x-www-form-urlencoded`**. Required field:

<ParamField body="apiKey" type="string" required>
  API key from your Mannco.store account settings.
</ParamField>

#### JSON example

```json theme={null}
{ "apiKey": "your-api-key" }
```

#### Form example

```
apiKey=your-api-key
```

### Success response

```json theme={null}
{
  "err": false,
  "success": true,
  "content": {
    "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}
```

Use **`content.jwt`** (there is no `data` wrapper).

### JWT claims (decoded payload)

| Claim                 | Type    | Description                              |
| --------------------- | ------- | ---------------------------------------- |
| `iss`                 | string  | Always `"API"`                           |
| `sub`                 | string  | User Steam64 ID                          |
| `exp`                 | number  | Expiry (Unix), about 31 days after issue |
| `iat`                 | number  | Issued-at (Unix)                         |
| `jti`                 | string  | Token id                                 |
| `ip`                  | string  | Client IP at login time                  |
| `proxy`               | boolean | Proxy context                            |
| `API`                 | boolean | Always `true` for this flow              |
| `country`             | string  | ISO country code                         |
| `steamid`             | string  | Steam ID (backend format)                |
| `roles` / `rolesHash` |         | Role data                                |

### Errors (loginAPI.php)

| Response type | Typical HTTP | content                            |
| ------------- | ------------ | ---------------------------------- |
| `error`       | 300          | Missing required parameter: apiKey |
| `forbidden`   | 403          | Invalid API key                    |
| `forbidden`   | 403          | Country blocked                    |

### Examples

```bash cURL theme={null}
curl -X POST https://api.mannco.store/user/login \
  -H "Content-Type: application/json" \
  -d '{"apiKey":"your-api-key"}'
```

```javascript JavaScript theme={null}
const res = await fetch("https://api.mannco.store/user/login", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ apiKey: "your-api-key" }),
});
const data = await res.json();
const jwt = data.content.jwt;
```

```python Python theme={null}
import requests

r = requests.post(
    "https://api.mannco.store/user/login",
    json={"apiKey": "your-api-key"},
)
data = r.json()
jwt = data["content"]["jwt"]
```

<Note>
  Store the JWT securely. When it expires, call POST /user/login again with your API key.
</Note>

***

## Using the JWT

For endpoints that require **Connected + API**, send:

```
Authorization: Bearer <jwt>
```

The server may also accept a session cookie in browser contexts; for API clients, **Bearer** is the intended method.

### IP binding

The JWT is tied to the **IP address** at login. If your client IP changes (VPN, mobile network, proxy), requests may fail authentication. Use a stable egress IP or the same network as when you obtained the token.

### Routes without a logged-in user

Some routes only have the `api` filter (no `connected`). Public item endpoints may work without a Bearer token. **GET /user/store/{identifier}** does not require a user JWT. For **your** account data, always send the Bearer token from **POST /user/login**.

***

## 2FA vs API JWT

Server routes marked with **2fa** accept a JWT from **POST /user/login** without sending a 2FA header: **requires2FA** succeeds when **isAPI** is true. If you use a **web session** instead of the API JWT, 2FA rules apply as on the website.
