Архитектура

Концепции

Ключевые принципы работы МедАссист API: асинхронная обработка, идемпотентность, биллинг, лимиты и безопасность

Always-Async обработка

Все запросы на обработку текста работают асинхронно:

  1. SubmitPOST /v1/text/process/{short|long}202 Accepted + request_id
  2. PollingGET /v1/requests/<request_id> до получения 200 OK

Это обеспечивает стабильность при любой нагрузке и длительности обработки. Клиент не зависит от времени ответа модели.

Рекомендуемый интервал polling: 2 секунды. Используйте заголовок Retry-After из ответа, если он присутствует.


Идемпотентность

Заголовок Idempotency-Key обязателен для всех запросов /v1/text/process/*.

Когда использовать тот же ключ

Используйте тот же Idempotency-Key только для ретрая того же самого запроса:

  • тот же endpoint
  • тот же текст
  • тот же API-ключ

Если body запроса изменился при том же ключе, сервер вернёт 409 Conflict.

Когда нужен новый ключ

  • Каждый новый запрос = новый Idempotency-Key
  • Если прошлый запрос завершился ошибкой и вы хотите повторить — используйте новый ключ
  • Повтор с тем же ключом после ошибки вернёт 409 Conflict

Рекомендация

Используйте UUID v4 для генерации ключей:

import uuid
idem = str(uuid.uuid4())
const idem = crypto.randomUUID();

Биллинг: prepaid-кредиты

МедАссист API работает по модели prepaid — кредиты пополняются заранее.

Как работает списание

  1. При отправке запроса система резервирует кредиты
  2. После успешной обработки резерв списывается (finalize)
  3. При ошибке обработки резерв возвращается

Проверка баланса

GET /v1/billing/balance
  • available_credits — доступно для новых запросов
  • reserved_credits — зарезервировано под выполняющиеся запросы
  • balance_credits — общий баланс (available + reserved)

При недостаточном балансе запрос вернёт 402 insufficient_funds.

История операций

GET /v1/billing/ledger

Каждая запись неизменяемая. Типы: topup (пополнение), charge (списание), adjustment (корректировка).

Для пополнения баланса обратитесь в поддержку.


Rate Limits (лимиты)

Лимиты применяются к количеству запросов в минуту и в день.

  • Повторные запросы по idempotency не тратят лимит
  • При превышении лимита сервер возвращает 429 rate_limited или 429 quota_exceeded
  • Polling-endpoint (GET /v1/requests/<id>) имеет отдельный лимит (по умолчанию 60/мин)

Конкретные значения лимитов зависят от вашего тарифа.


Zero-Log режим

Для аккаунтов с включённым режимом zero_log:

  • Входные и выходные тексты не сохраняются в базе данных
  • Результаты доступны через polling ограниченное время (TTL)
  • После истечения TTL результат удаляется безвозвратно
  • Повторный polling по request_id после истечения TTL вернёт ошибку
  • Повтор с тем же Idempotency-Key после истечения TTL вернёт 409 Conflict

Режим Zero-Log обеспечивает максимальную конфиденциальность обработанных данных.


Безопасность

API-ключи

  • Полный ключ показывается только один раз при выпуске (rotate)
  • Ключ бессрочный — действует до ротации
  • При ротации старый ключ деактивируется мгновенно
  • Один активный ключ на организацию

JWT-токены

  • Access token — короткоживущий (используется для кабинетных API)
  • Refresh token — передаётся через httpOnly cookie (недоступен из JS)
  • Refresh token ротируется при каждом обновлении

Рекомендации

  • Храните API-ключ в переменных окружения, не в коде
  • Не передавайте ключи через URL-параметры
  • Используйте HTTPS для всех запросов
  • При компрометации ключа — немедленно сделайте rotate

FAQ

Почему в ответах нет реального названия провайдера/модели?

Сервис не раскрывает внутренние идентификаторы провайдера. Вместо них используются публичные алиасы MedAssistModel1 и MedAssistModel2. Обе модели современные и топового уровня.

Почему я получаю 402 insufficient_funds?

Недостаточно кредитов. Для пополнения баланса обратитесь в поддержку.

Почему я получаю 500 server_misconfigured?

Ошибка конфигурации на стороне сервиса. Обратитесь в поддержку — мы оперативно исправим.

Почему я получаю 403 «Referer header is required»?

Для POST-запросов к /v1/auth/* требуется заголовок Referer: https://partner.medassistai.ru/. В curl и HTTP-клиентах его нужно указывать явно.

Почему я получаю JSON parse error?

Обычно это означает невалидный JSON: буквальные переводы строк внутри строки text. Используйте JSON-сериализацию вашего языка (см. Примеры кода — Многострочный текст).

Как связаться с поддержкой?

Через тикеты в личном кабинете (/cabinet/tickets/) или по согласованному каналу связи.

Обсудить подключение