# API

### General

* **Base URL**: depends on your deployment (relative paths are used below).
* **Format**: `application/json` for both requests and responses.
* **CORS**: `GET, POST, PUT, OPTIONS` allowed; headers — any (controllers use `yii\filters\Cors`).
* **HTTP status codes**: business status is often returned in the body (`success`, `rc`, `msg`, etc.). HTTP codes are generally `200`; auth/access errors may return `401/403` (see endpoint notes).

#### Terms & Entities

* **provider\_code** — 8 characters `[A-Za-z0-9]{8}` (Provider ID).
* **auth\_key** — 32 characters `[-_A-Za-z0-9]{32}` (Provider auth key).
* **install\_code** — 12 characters `[A-Za-z0-9]{12}` (Installation code).
* **domain\_hash** — 64 characters `[a-z0-9]{64}` (SHA-256 of the subscription domain, lowercase hex).

#### Device headers (used by client calls)

Some endpoints require device headers:

* `X-HWID`: device HWID (required where noted).
* `X-Device-OS`: OS name (e.g., `iOS`, `Android`, `macOS`, `Windows`).
* `X-Ver-OS`: OS version.
* `X-Device-model`: device model.
* `X-Domain-Hash`: 64-hex SHA-256 of the subscription domain (required where noted).
* `User-Agent`: standard user agent.

> Note: legacy `X-Device-Info` (concatenation of device fields) is temporarily supported for backward compatibility, but prefer separate `X-Device-OS` / `X-Ver-OS` / `X-Device-model`.

***

### 1) Provider / Installation API

#### GET `/api/provider`

**Purpose:** Record a device hit and return the provider status.

**Query**

* `id` *(string, required)* — `provider_code` (8 chars).

**Headers (required)**

* `X-Domain-Hash`
* Recommended: `X-HWID`, `X-Device-OS`, `X-Ver-OS`, `X-Device-model`, `User-Agent`.

**Logic:**

* Validates `provider_code` and `X-Domain-Hash`.
* If the domain is bound to the provider, saves an event (`hwid`, device info, user agent).
* Returns current provider status.

**200 Response**

```json
{
  "status": "basic" | "extended"
}
```

> Value comes from `Users::provider_status`. On failed validation, the server still returns `status` (usually `basic`).

**Example**

```bash
curl -G '/api/provider' \
  --data-urlencode 'id=Ab12Cd34' \
  -H 'X-Domain-Hash: 0123abcd...ff' \
  -H 'X-HWID: DEVICE-123' \
  -H 'X-Device-OS: iOS' \
  -H 'X-Ver-OS: 17.5' \
  -H 'X-Device-model: iPhone15,2'
```

***

#### GET `/api/install`

**Purpose:** Validate an `install_code`, decide whether import is allowed, and return provider data.

**Query**

* `id` *(string, required)* — `install_code` (12 chars).

**Headers (required)**

* `X-Domain-Hash`
* Recommended: `X-HWID`, `X-Device-OS`, `X-Ver-OS`, `X-Device-model`, `User-Agent`.

**Logic (simplified):**

* Validates `install_code` and `X-Domain-Hash`.
* Looks up `UserInstall` record and its domain.
* Computes `import`:
  * `true` if:
    * the same `install_code` previously succeeded for this `HWID`, **or**
    * the installation limit isn’t exhausted (`install_count < install_limit`), in which case the counter is incremented;
  * `false` otherwise.
* Returns provider code and status.

**200 Success Example**

```json
{
  "providerid": "Ab12Cd34",
  "status": "extended",
  "import": true
}
```

**200 (invalid input example)**

```json
{
  "import": false
}
```

**Example**

```bash
curl -G '/api/install' \
  --data-urlencode 'id=ABCDEF123456' \
  -H 'X-Domain-Hash: 0123abcd...ff' \
  -H 'X-HWID: DEVICE-123'
```

***

#### GET `/api/add-install`

**Purpose:** Create (or check existence of) an `install_code` for a provider.

**Query**

* `auth_key` *(string, required)* — 32 chars.
* `provider_code` *(string, required)* — 8 chars.
* `install_limit` *(int, required)* — `1..100`.
* `install_code` *(string, optional)* — 12 chars. If omitted, it will be generated.

**Responses**

* Created:

  ```json
  { "rc": 1, "msg": "Ok", "install_code": "ABCDEF123456" }
  ```
* Already exists:

  ```json
  { "rc": 2, "msg": "Install code exists" }
  ```
* Errors (auth/validation/limits):

  ```json
  { "rc": 0, "msg": "Auth error | Install limit error | Max install code created | Unknown error" }
  ```

**Example**

```bash
curl -G '/api/add-install' \
  --data-urlencode 'provider_code=Ab12Cd34' \
  --data-urlencode 'auth_key=AbcdEfghIjklMnopQrstuVwxyz_1234' \
  --data-urlencode 'install_limit=10'
```

***

#### GET `/api/add-domain`

**Purpose:** Bind a subscription domain to a provider.

**Query**

* `auth_key` *(string, required)* — 32 chars.
* `provider_code` *(string, required)* — 8 chars.
* `domain_name` *(string, optional)* — human-readable domain (URL-decoded).
* `domain_hash` *(string, required)* — lowercase SHA-256 of the domain (64 hex).

**Responses**

* Returns the result object from `ProviderDomain::addProviderDomain(...)->getLastResult()`. On errors:

  ```json
  { "rc": 0, "msg": "Auth error | Domain hash error | Unknown error" }
  ```

**Example**

```bash
curl -G '/api/add-domain' \
  --data-urlencode 'provider_code=Ab12Cd34' \
  --data-urlencode 'auth_key=AbcdEfghIjklMnopQrstuVwxyz_1234' \
  --data-urlencode 'domain_hash=0123abcd...ff' \
  --data-urlencode 'domain_name=sub.example.com'
```

***

### 2) Bulk Push Notifications

#### POST `/api-notification/send-notification`

**Access:** requires an **active subscription** and the **Enterprise** plan.\
**Auth:** `auth_key` in query.

**Query**

* `auth_key` *(string, required)* — 32 chars.

**Body (JSON)**

```json
{
  "PushNotificationForm": {
    "title": "Optional title",
    "body": "<p>HTML text with allowed tags</p>",
    "locales": [
      { "lang": "en", "title": "Title EN", "body": "Body EN" },
      { "lang": "ru", "title": "Заголовок RU", "body": "Текст RU" }
    ],
    "background_image": "https://.../bg.jpg",
    "link": "https://example.com",
    "type_push": "custom-type",
    "expire_days": 7,
    "send_now": true,
    "send_date": "2025-08-20",
    "send_time": "13:00"
  },

  "os": ["iOS","Android"],   // target OSes (when not targeting by HWID)
  "hwid": "HWID1,HWID2"      // up to 5 HWIDs, comma-separated
}
```

**Constraints & Validation**

* The message is serialized to JSON and base64-encoded; **base64 size ≤ 4096 bytes**.
* If **not** sending to specific HWIDs and you’re **not admin**, anti-spam applies: at most **once every 5 minutes** for a “broadcast”.
* Regular provider:
  * with `hwid` — HWIDs are filtered to your provider’s devices; if none found → error.
  * with `os` — send only to your own devices. If none → error.

**Responses**

```json
{ "success": true }
```

```json
{ "success": false, "error": "This feature requires an active subscription | This feature requires Enterprise plan | Message too large (max 4096 bytes) | Device with this HWID not found | No devices found for selected OS and your provider IDs | ..." }
```

**Example**

```bash
curl -X POST '/api-notification/send-notification?auth_key=AbcdEfghIjklMnopQrstuVwxyz_1234' \
  -H 'Content-Type: application/json' \
  -d '{
    "PushNotificationForm": {
      "title": "Hello",
      "body": "<p>World</p>",
      "send_now": true,
      "expire_days": 3
    },
    "os": ["iOS","Android"]
  }'
```

***

#### POST `/api-notification/cancel/{id}`

**Purpose:** Cancel a previously scheduled notification.\
**Auth:** requires **panel login** (cookie session; uses `Yii::$app->user->identity`).

**Rules:**

* You can cancel only your own notification (`sender_id = current user`).
* You cannot cancel **less than 10 minutes** before scheduled send time.

**Responses**

```json
{ "success": true }
```

```json
{ "success": false, "error": "Notification not found | You cannot cancel notification less than 10 minutes before scheduled time | Failed to cancel notification" }
```

***

### 3) Remote Control Commands

#### POST `/api-remote/send-command`

**Access:** requires an **active subscription** and **Pro** or **Enterprise** plan.\
**Auth:** `auth_key` in query.

**Query**

* `auth_key` *(string, required)* — 32 chars.

**Body (JSON)**

Two command types:

1. **Import data**

```json
{
  "action_type": "import-data",
  "import_data": "raw string to import",   // will be base64-encoded into "input-data"

  "send_now": true,
  "send_date": "2025-08-20",
  "send_time": "13:00",

  "specific_device": false,
  "hwid": "HWID1,HWID2",      // required when specific_device=true; up to 5
  "os": ["iOS","Android"]     // if not specific_device and not send_to_all
}
```

2. **Set settings**

```json
{
  "action_type": "set-settings",
  "settings": { "log_level": 'info', "featureX": true },

  "send_now": false,
  "send_date": "2025-08-21",
  "send_time": "09:30",

  "specific_device": true,
  "hwid": "HWID-ABC123"
}
```

**Validation**

* `specific_device=true` ⇒ `hwid` is required; otherwise `HWID is required for specific device`.
* If **not** `specific_device` and **not** `send_to_all`, `os` must be non-empty; otherwise `Select at least one OS or enable specific device`.
* For `set-settings` — `settings` is required and must be valid JSON (as a string).
* For `import-data` — `import_data` is required (string).

**Payload construction**

```json
{
  "remote-control-type": "import-data" | "set-settings",
  "providerid": "<your provider_code>"
  // + either "input-data": "<base64>" (for import-data),
  // + or arbitrary key–value pairs from settings (for set-settings)
}
```

**Targeting**

* `specific_device=true`: active HWIDs are checked.
* Otherwise: by OS, within the provider’s own devices.

**Responses**

```json
{ "success": true, "message": "Command saved successfully" }
```

```json
{ "success": false, "error": "This feature requires Pro or Enterprise plan | HWID is required for specific device | Select at least one OS or enable specific device | Device with this HWID not found | Failed to save command" }
```

**Example**

```bash
curl -X POST '/api-remote/send-command?auth_key=AbcdEfghIjklMnopQrstuVwxyz_1234' \
  -H 'Content-Type: application/json' \
  -d '{
    "action_type": "set-settings",
    "settings": "{\"log_level\":\"debug\"}",
    "specific_device": true,
    "hwid": "HWID-1"
  }'
```

***

### Additional Notes

* **Allowed HTML tags** in notification `body` are whitelisted (typical set: `a,b,big,blockquote,br,cite,del,dfn,div,em,i,img,li,p,s,small,span,strike,strong,sub,sup,tt,u,ul`; allowed attributes: `href,title,src,alt`; `target="_blank"` is allowed).
* **OS values** — strings stored in `DeviceToken.os_type`. Common: `iOS`, `Android`, `macOS`, `Windows` (use what the client actually writes).
* **Limits**:
  * `send-notification`: broadcast without `hwid` — at most once every **5 minutes** (non-admins).
  * Notification payload after base64 — **≤ 4096 bytes**.
  * HWIDs in targeted sends — up to **5** per request.

***

#### Validation Regex Summary

| Field           | Regex                 |
| --------------- | --------------------- |
| `provider_code` | `^[A-Za-z0-9]{8}$`    |
| `auth_key`      | `^[-_A-Za-z0-9]{32}$` |
| `install_code`  | `^[A-Za-z0-9]{12}$`   |
| `domain_hash`   | `^[a-z0-9]{64}$`      |
| `install_limit` | integer `1..100`      |
