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

# Обзор

> Авторизация запросов к Partner API

Partner API позволяет управлять подписками ваших пользователей в Ai-Seven со стороны вашего сервиса.

**База:** `https://aisevenai.ru/api/v1/partner`

## Авторизация

Запросы подписываются тем же приватным ключом, что и токены входа пользователей. Отдельные API-ключи не выдаются.

```text theme={null}
Authorization: Bearer <JWT>
```

### Формат токена

```json theme={null}
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "<ваш kid>"
}
```

```json theme={null}
{
  "aud": "ai-seven:api"
}
```

<ParamField body="aud" type="string" required>
  Всегда `ai-seven:api`. Отличает токен API от токена входа пользователя — они не взаимозаменяемы.
</ParamField>

Больше в payload ничего не требуется: токен представляет вашу компанию, а не конкретного пользователя. Срок жизни не ограничен — подпишите токен один раз и укажите в конфигурации своего сервиса.

<Warning>
  Не используйте токен входа пользователя (`aud: "ai-seven:sso"`) для запросов к Partner API — такие запросы отклоняются.
</Warning>

### Генерация токена

<CodeGroup>
  ```python Python theme={null}
  import jwt  # pip install pyjwt[crypto]

  token = jwt.encode(
      {"aud": "ai-seven:api"},
      open("private.pem").read(),
      algorithm="RS256",
      headers={"kid": "<ваш kid>"},
  )
  ```

  ```javascript Node.js theme={null}
  import jwt from "jsonwebtoken";
  import { readFileSync } from "fs";

  const token = jwt.sign({ aud: "ai-seven:api" }, readFileSync("private.pem"), {
    algorithm: "RS256",
    keyid: "<ваш kid>",
  });
  ```

  ```php PHP theme={null}
  <?php
  use Firebase\JWT\JWT;

  $token = JWT::encode(
      ['aud' => 'ai-seven:api'],
      file_get_contents('private.pem'),
      'RS256',
      '<ваш kid>'
  );
  ```
</CodeGroup>

## Ошибки авторизации

Возвращаются любым эндпоинтом Partner API.

| Код   | Сообщение                        | Причина                                                                    |
| ----- | -------------------------------- | -------------------------------------------------------------------------- |
| `401` | Невалидный токен                 | Заголовок токена не разбирается — токен повреждён или обрезан              |
| `401` | Не указан kid                    | В заголовке токена отсутствует `kid`                                       |
| `401` | Невалидный токен                 | Заголовок `Authorization` отсутствует, неверная подпись или неверный `aud` |
| `401` | Ключ не найден или деактивирован | Неизвестный `kid`, либо ключ или интеграция отключены                      |
| `401` | Истёк срок действия токена       | В токен добавлен `exp`, и он уже наступил                                  |
| `500` | Публичный ключ не задан          | Внутренняя ошибка конфигурации — свяжитесь с нами                          |

<Note>
  Поле `exp` в токене Partner API не требуется. Если вы его добавите, мы будем его учитывать — токен перестанет работать после истечения срока.
</Note>

## Эндпоинты

<CardGroup cols={2}>
  <Card title="Подписки" icon="shopping-cart" href="/partner-api/subscriptions">
    Список доступных пакетов и выдача подписки пользователю.
  </Card>
</CardGroup>
