Provider API v2.1 — руководство для интеграторов лабораторий

Подключение лаборатории к Provider API v2.1: авторизация, заявки, статусы и передача результатов.

Версия: v2.1 (расширяет v1, полностью совместима «снизу вверх») 

Аудитория: разработчики на стороне лаборатории/интегратора (REST). 

Назначение: единая инструкция «с нуля до первого результата» — как подключиться, авторизоваться, забрать заявку из очереди клиники и вернуть результат анализа.

Что нового в v2.1. Эндпоинт POST /result-values научился принимать три необязательных поля: человекочитаемое title, норму reference_range и отметку отклонения flag. Если их не передавать — поведение не отличается от v1. Ни один URL, ни один обязательный параметр не менялись, миграция интеграции не требуется. Подробности — в разделе 6.1.

Документ обезличен. Все секреты, имена сервисов, домены клиник и идентификаторы заявок приведены как плейсхолдеры: {service_name}, {rest_api_key}, {billing_authkey}, {clinic_host}, {request_id}, {analyze_id}. Реальные значения выдаются при онбординге.


Содержание

  1. Термины и плейсхолдеры
  2. Онбординг и ключи
  3. Авторизация
  4. Общий сценарий работы
  5. Статусы заявки
  6. Типы результата: html и values 6.1. Нормы и отметка отклонения — новое в v2.1
  7. Эндпоинты — контракт и примеры
  8. Ошибки
  9. Требования на стороне клиники
  10. Postman
  11. Приложение A. Примеры curl
  12. Приложение B. Контакты поддержки

1. Термины и плейсхолдеры

ПлейсхолдерЧто этоГде используется
{service_name}Идентификатор вашего сервиса-провайдераЗаголовок X-SERVICE-NAME
{rest_api_key}REST-ключ Provider APIЗаголовок X-SERVICE-REST-API-KEY
{billing_authkey}Ключ для billing-api (получение списка доменов)GET lab-domains/{billing_authkey}
{clinic_host}Хост конкретной клиники (CRM-инстанс)Базовый URL всех вызовов Provider API
{request_id}ID заявки на исследованиеТело запросов take/waiting/result-*
{analyze_id}ID анализа внутри заявкиТело запросов result-*

Заявка (request) — единица работы: один питомец, один провайдер, набор анализов. Анализ (analyze) — отдельная позиция внутри заявки. Результат отправляется по каждому анализу отдельно; когда заполнены все анализы заявки — заявка переходит в done.


2. Онбординг и ключи

Для интеграции используются два разных ключа:

  1. {billing_authkey} — выдаётся billing-сервисом. Нужен только для того, чтобы получить список клиник (хостов), подключивших вашу лабораторию.
  2. {rest_api_key} — REST-ключ вашего сервиса. Используется во всех вызовах Provider API вместе с {service_name}.

Оба ключа и {service_name} выдаются при онбординге. Храните их как секреты, не публикуйте в репозиториях и клиентских приложениях.

2.1. Получение списка доменов клиник

Перед вызовом Provider API нужно узнать, на каком {clinic_host} работать. Список доступных вам клиник возвращает billing-api:

GET https://{billing_host}/lab-domains/{billing_authkey}

Ответ — перечень доменов клиник, которые подключили вашу лабораторию и активировали интеграцию. Каждый элемент содержит хост клиники, который далее подставляется как {clinic_host}.

{
  "success": true,
  "data": [
    { "host": "{clinic_host}", "title": "..." }
    // ...другие клиники
  ]
}

Выбор {clinic_host}: дальнейшая работа (list → take → result) ведётся отдельно по каждой клинике. Заявки одной клиники недоступны под хостом другой.


3. Авторизация

Все запросы к Provider API авторизуются двумя HTTP-заголовками:

X-SERVICE-NAME: {service_name}
X-SERVICE-REST-API-KEY: {rest_api_key}

Базовый URL для всех эндпоинтов:

https://{clinic_host}/rest/api/provider-lab-requests/...

Если хотя бы один заголовок отсутствует или ключ неверный — 401 UNAUTHORIZED. Если для клиники не подключён тариф/аддон или не включена интеграция — ответ маскируется под 404 NOT_FOUND (см. раздел 8).


4. Общий сценарий работы

lab-domains            → получить список {clinic_host}
        │
        ▼
GET  list              → увидеть очередь заявок клиники (taken/tranzit/waiting)
        │
        ▼
POST take              → взять заявку в работу:  taken → tranzit
        │
        ▼
POST waiting (опц.)    → пометить «ожидаем результат»:  tranzit → waiting
        │
        ▼
POST result-html       → отправить результат по анализу
   или result-values     (повторять для каждого analyze_id заявки)
        │
        ▼
   когда заполнены все анализы → заявка автоматически переходит в done

Минимальный happy path: list → take → result-*. Шаг waiting нужен, когда результат готовится не сразу (длинная аналитика): он явно фиксирует, что заявка взята и ожидает результата.


5. Статусы заявки

СтатусЗначениеВиден в list?
takenСоздана клиникой, ещё не взята провайдеромДа
tranzitВзята провайдером в работу (take)Да
waitingОжидает результата (waiting)Да
doneВсе анализы заполнены — завершенаНет
cancelled / deleted / errorТерминальныеНет (для провайдера = «не найдена»)

Правила переходов:

  • take: taken → tranzit. Идемпотентен — повторный вызов для заявки в tranzit или waiting вернёт текущий статус без ошибки. Для done409 ALREADY_TAKEN. Других целевых статусов у take нет — из taken можно попасть только в tranzit.
  • waiting: tranzit → waiting. Идемпотентен для waiting. Из taken или done409 INVALID_STATUS_TRANSITION (сначала нужно take). Других переходов в waiting нет — попасть в этот статус можно только из tranzit.
  • Результаты (result-html/result-values) принимаются только из tranzit или waiting. Из других статусов → 409 INVALID_STATUS_TRANSITION.
  • done не вызывается отдельным эндпоинтом — он выставляется автоматически, как только заполнен последний анализ заявки. Шаг waiting для этого не обязателен: заявка может дойти до done напрямую из tranzit (если результаты отправлены без промежуточной пометки ожидания) либо из waiting. Итоговый путь всегда один из двух: tranzit → done или tranzit → waiting → done.
  • Заявка в done гарантированно имеет все свои analyze_id заполненными (это и есть условие перехода в done). Поэтому повторная отправка результата по любому анализу такой заявки всегда вернёт 409 ALREADY_FILLED, а не 409 INVALID_STATUS_TRANSITION — проверка «анализ уже заполнен» выполняется раньше проверки статуса заявки. На практике INVALID_STATUS_TRANSITION для результатов возникает только у заявки в статусе taken (в ней по определению нет заполненных анализов, так как заполнение возможно лишь из tranzit/waiting).
  • Терминальные статусы для провайдера выглядят как 404 NOT_FOUND.

6. Типы результата: html и values

Результат по анализу можно отправить в одном из двух форматов:

  • result-html — готовый HTML-фрагмент (например, отрендеренный бланк/таблица результатов). Подходит, когда лаборатория формирует визуальное представление сама.
  • result-values — структурированный набор «параметр → значение → ед. измерения». Подходит для машиночитаемых показателей.

Важно: формат фиксируется за заявкой по первому результату. Если первый результат отправлен как html, остальные анализы этой же заявки тоже должны идти html (и наоборот). Смешение → 409 INCOMPATIBLE_RESULT_FORMAT.

Оба формата поддерживают необязательные поля file_link, measured_at, comment.


6.1. Нормы и отметка отклонения — новое в v2.1

Раньше result-values отдавал плоскую таблицу «показатель / значение / единица», а название показателя печаталось техническим кодом (UREA вместо «Мочевина»), потому что сервер приводит name к верхнему регистру для внутреннего ключа. Врачу приходилось самому держать в голове нормы и искать отклонение глазами.

В v2.1 у каждого элемента values появились три необязательных поля:

ПолеТипЧто даёт
titlestringЧеловекочитаемое название показателя для таблицы результата. name при этом остаётся техническим ключом и никуда не делся — он по-прежнему уходит в историю показателей
reference_rangeobjectНорма показателя — числовая или текстовая (см. ниже)
flagstringОтметка отклонения, если её нельзя вычислить автоматически (см. «Кто выставляет отметку» ниже)

Все три поля опциональны и независимы друг от друга. Можно прислать только title, только reference_range, всё вместе или ничего — как раньше.


6.1.1. title — человекочитаемое название

{ "name": "UREA", "title": "Мочевина", "value": "9.1", "unit": "ммоль/л" }

Если title не прислан — в таблице, как и раньше, печатается name. Ограничение: не длиннее 255 символов.


6.1.2. reference_range — норма

Норма прикладывается к конкретному показателю и бывает трёх видов:

Вид нормыКак передаётсяПримерКак отображается
Двусторонний интервалmin и max{ "min": 2.5, "max": 8.32 }2.5 – 8.32
Одностороннийтолько minили только max{ "max": 100 }до 100


{ "min": 57 }от 57
Качественная (текстовая)text{ "text": "не обнаружено" }не обнаружено

Норму присылает провайдер и только он. Референс зависит от вида животного, возраста, пола, прибора и метода — всё это лаборатория знает о конкретном пациенте лучше клиники. Кстати, вид, порода, пол, дата рождения и вес питомца уже приходят провайдеру в ответе GET /list (раздел 7.1) — именно для того, чтобы можно было подобрать нужный интервал перед отправкой результата.

Правила валидации (нарушение → 400 INVALID_PAYLOAD с указанием, в каком показателе проблема):

  • min и max — числа, разделитель дробной части — точка.
  • Нельзя присылать text вместе с min/max — норма либо числовая, либо текстовая.
  • min не может быть больше max.
  • text — не длиннее 100 символов.
  • reference_range не может быть пустым объектом {} — если нормы нет, просто не передавайте поле вовсе.

Если норма не прислана ни у одного показателя заявки — колонка «Норма» в таблице результата не появляется вообще, таблица остаётся трёхколоночной, как в v1. Это относится ко всей заявке целиком, не построчно: если норму передали хотя бы у одного показателя, колонка появляется для всех строк — просто у показателей без нормы она будет пустой.


6.1.3. flag — отметка отклонения

Допустимые значения: normal, low, high, critical_low, critical_high, abnormal. Любое другое значение — ошибка 400 INVALID_PAYLOAD, а не молчаливое игнорирование.

critical_low / critical_high — это панические результаты (калий, глюкоза, лактат и подобные), при которых лаборатория обязана немедленно связаться с врачом. В таблице они выделяются заметнее обычного отклонения, поэтому передавайте их осознанно, а не «на всякий случай».

6.1.4. Кто выставляет отметку отклонения

Сервер сам считает отметку везде, где это возможно, и подставляет присланный flag только там, где вычислить нечем:

  1. Числовая норма, значение — число. Сервер сравнивает сам: ниже minlow, выше maxhigh, иначе normal. Присланный flag при этом игнорируется — кромеcritical_low/critical_high: критичность по границам не вычисляется, её знает только лаборатория, поэтому такой flag побеждает вычисленное значение.
  2. Числовая норма, но значение не парсится числом (например, "< 5" или "следы"). Норма в таблице показывается, но отметку сервер не ставит — что означает «< 5» относительно интервала, он решать не должен. Если нужна отметка — пришлите flag явно.
  3. Текстовая норма, flag не прислан. Сервер сравнивает value с текстом нормы (без учёта регистра и пробелов по краям): совпало → normal, не совпало → abnormal.
  4. Текстовая норма и flag прислан. Побеждает flag. Это нужно для шкал, где строковое сравнение врёт: норма «единичные в поле зрения», результат «3–4 в поле зрения» — строки не совпадают, но это не отклонение. Такую логику знает только интегратор.
  5. Нормы нет вовсе. Колонка «Норма» пустая, отметки нет — поведение не отличается от v1.

6.1.5. Примеры на каждый случай

Двусторонняя норма, отклонение сервер посчитает сам:

{ "name": "UREA", "title": "Мочевина", "value": "9.1", "unit": "ммоль/л",
  "reference_range": { "min": 2.5, "max": 8.32 } }

Односторонняя норма («до 100»):

{ "name": "ALT", "title": "АЛТ", "value": "112", "unit": "Ед/л",
  "reference_range": { "max": 100 } }

Качественный результат — сервер сам сравнит строки и поставит отклонение:

{ "name": "DIRO_AG", "title": "Дирофиляриоз, антиген", "value": "обнаружено",
  "reference_range": { "text": "не обнаружено" } }

Шкала, где строковое сравнение обмануло бы — побеждает присланный flag:

{ "name": "URINE_WBC", "title": "Лейкоциты в осадке мочи", "value": "3–4 в п/з",
  "reference_range": { "text": "единичные в поле зрения" },
  "flag": "normal" }

Критическое значение — панический порог по границам не вычислить:

{ "name": "K", "title": "Калий", "value": "8.2", "unit": "ммоль/л",
  "reference_range": { "min": 3.5, "max": 5.8 },
  "flag": "critical_high" }

Без новых полей — как в v1, ничего не меняется:

{ "name": "HEMOLYSIS", "value": "отсутствует" }

Так делать нельзя — текстовая и числовая норма одновременно, 400 INVALID_PAYLOAD:

{ "name": "GLU", "value": "5.4",
  "reference_range": { "min": 3.3, "text": "норма" } }

6.1.6. Как это выглядит в медкарте

Ниже — два реальных скриншота карточки медкарты (не макет), полученные одним и тем же запросом POST /result-values с разным набором полей.

Без title/reference_range/flag (как в v1, если ничего не менять): таблица остаётся трёхколоночной, показатель печатается техническим кодом (GLU, AST).

Результат без новых полей v2.1

С title, reference_range и flag (новое в v2.1): появляется колонка «Норма», у показателя печатается человекочитаемое название, отклонения выделены полужирным со стрелкой (/), критическое значение — двойной стрелкой и красным цветом.

Результат с title, reference_range и flag v2.1

Оформление — рамки, отступы, серая шапка, числа по правому краю — верстается инлайн-стилями внутри HTML, который уходит в описание медкарты, поэтому одинаково переживает и редактор карточки, и печатную форму.


7. Эндпоинты — контракт и примеры

Общие правила:

  • Тело POST-запросов — JSON (Content-Type: application/json).
  • Все ответы — JSON. Успех: "success": true. Ошибка: "success": false + error_code + messages[].

7.1. GET /list — очередь заявок

Параметры строки запроса (все необязательные):

ПараметрТипПо умолчаниюОграничения
statusstringвсе из taken,tranzit,waitingтолько одно из taken, tranzit, waiting
limitint50от 1 до 200
offsetint00

Запрос:

GET /rest/api/provider-lab-requests/list?status=taken&limit=50&offset=0
Host: {clinic_host}
X-SERVICE-NAME: {service_name}
X-SERVICE-REST-API-KEY: {rest_api_key}

Ответ 200:

{
  "success": true,
  "total": 1,
  "data": {
    "labanalysisrequest": [
      {
        "id": {request_id},
        "status": "taken",
        "sample_number": 12345,
        "create_date": "2024-01-15 10:30:00",
        "comment": "...",
        "pet": {
          "id": 0,
          "alias": "...",
          "type": "...",
          "breed": "...",
          "sex": "...",
          "birthdate": "...",
          "weight": "..."
        },
        "analyzes": [
          { "id": {analyze_id}, "code": "...", "title": "...", "filled": 0 }
        ]
      }
    ]
  }
}
  • total — общее число заявок по фильтру (для пагинации), независимо от limit/offset.
  • analyzes[].filled1, если по анализу уже принят результат, иначе 0.

7.2. POST /take — взять заявку в работу

Тело:

{ "request_id": {request_id} }

Ответ 200:

{
  "success": true,
  "messages": ["Request accepted"],
  "data": { "request_id": {request_id}, "request_status": "tranzit" }
}

7.3. POST /waiting — пометить ожидание результата

Тело:

{ "request_id": {request_id} }

Ответ 200:

{
  "success": true,
  "messages": ["Request moved to waiting"],
  "data": { "request_id": {request_id}, "request_status": "waiting" }
}

7.4. POST /result-html — результат в формате HTML

Тело:

ПолеТипОбяз.Ограничения
request_idintда> 0
analyze_idintдаанализ должен принадлежать заявке
htmlstringдане пусто; ≤ 1 МБ; без <script>/<iframe>/on*=-атрибутов
file_linkstringнетURL только с разрешённого файлового хоста (см. 8)
measured_atstringнетISO 8601, напр. 2024-01-15T10:30:00+02:00
commentstringнетпроизвольный текст

HTML дополнительно санитизируется на сервере (вырезаются неразрешённые теги и атрибуты). Разрешён ограниченный набор форматирующих тегов и таблиц.

Запрос:

POST /rest/api/provider-lab-requests/result-html
Host: {clinic_host}
Content-Type: application/json
X-SERVICE-NAME: {service_name}
X-SERVICE-REST-API-KEY: {rest_api_key}

{
  "request_id": {request_id},
  "analyze_id": {analyze_id},
  "html": "<table><tr><td>Hemoglobin</td><td>140 g/L</td></tr></table>",
  "measured_at": "2024-01-15T10:30:00+02:00",
  "comment": "..."
}

Ответ 200:

{
  "success": true,
  "messages": ["Result saved"],
  "data": {
    "request_id": {request_id},
    "analyze_id": {analyze_id},
    "medcard_id": 0,
    "is_all_filled": false,
    "request_status": "waiting"
  }
}
  • is_all_filledtrue, когда это был последний незаполненный анализ заявки.
  • request_status — станет done, как только is_all_filled = true.

7.5. POST /result-values — структурированный результат

Тело:

ПолеТипОбяз.Ограничения
request_idintда> 0
analyze_idintдаанализ должен принадлежать заявке
valuesarrayданепустой массив объектов (см. ниже)
file_linkstringнетURL только с разрешённого файлового хоста
measured_atstringнетISO 8601
commentstringнетпроизвольный текст

Каждый элемент values:

ПолеТипОбяз.Ограничения
namestringда≤ 255 симв.; приводится к верхнему регистру и остаётся техническим ключом истории показателей; уникален в пределах values
valuestringда≤ 255 симв.
unitstringнет≤ 50 симв.
titlestringнетv2.1. ≤ 255 симв.; человекочитаемое название для таблицы (если не прислано — печатается name)
reference_rangeobjectнетv2.1.{ min?, max?, text? } — норма показателя, см. раздел 6.1.2
flagstringнетv2.1. одно из: normal, low, high, critical_low, critical_high, abnormal — см. раздел 6.1.3

Запрос (базовый вариант, как в v1 — работает без изменений):

POST /rest/api/provider-lab-requests/result-values
Host: {clinic_host}
Content-Type: application/json
X-SERVICE-NAME: {service_name}
X-SERVICE-REST-API-KEY: {rest_api_key}

{
  "request_id": {request_id},
  "analyze_id": {analyze_id},
  "values": [
    { "name": "HGB", "value": "140", "unit": "g/L" },
    { "name": "WBC", "value": "8.5", "unit": "10^9/L" }
  ],
  "measured_at": "2024-01-15T10:30:00+02:00"
}

Запрос (с нормами и названиями — новое в v2.1):

POST /rest/api/provider-lab-requests/result-values
Host: {clinic_host}
Content-Type: application/json
X-SERVICE-NAME: {service_name}
X-SERVICE-REST-API-KEY: {rest_api_key}

{
  "request_id": {request_id},
  "analyze_id": {analyze_id},
  "values": [
    { "name": "HGB", "title": "Гемоглобин", "value": "140", "unit": "g/L",
      "reference_range": { "min": 120, "max": 180 } },
    { "name": "WBC", "title": "Лейкоциты", "value": "8.5", "unit": "10^9/L",
      "reference_range": { "min": 6, "max": 17 } },
    { "name": "K", "title": "Калий", "value": "8.2", "unit": "ммоль/л",
      "reference_range": { "min": 3.5, "max": 5.8 }, "flag": "critical_high" }
  ],
  "measured_at": "2024-01-15T10:30:00+02:00"
}

Ответ 200: структура идентична result-html (см. 7.4) — новые поля на форму ответа не влияют, они меняют только оформление таблицы в медкарте.


8. Ошибки

Формат тела ошибки одинаков для всех эндпоинтов:

{
  "success": false,
  "error_code": "NOT_FOUND",
  "messages": ["Заявка не найдена"]
}

8.1. По HTTP-кодам

HTTPerror_codeКогда возникаетЧто делать
401UNAUTHORIZEDНет одного из заголовков или неверный {rest_api_key}Проверить заголовки и ключ
404NOT_FOUNDАддон/интеграция выключены; провайдер не найден; заявка не найдена/в терминальном статусе; анализ не принадлежит заявкеПроверить статус заявки и настройки клиники (раздел 9)
400INVALID_PAYLOADНевалидные/отсутствующие поля, нарушены длины/формат measured_at, недопустимый status/limit/offset. v2.1: сюда же попадают ошибки title (> 255 симв.), reference_range (текст с границами вместе, пустой объект, min > max, нечисловые min/max, text > 100 симв.) и неизвестное значение flagИсправить тело/параметры
400INVALID_HTMLВ html есть запрещённые элементы/атрибутыУбрать <script>/<iframe>/on*=
400INVALID_FILE_LINKfile_link не URL или хост не из разрешённого спискаИспользовать допустимый файловый хост
400DUPLICATE_KEYSПовтор name внутри valuesСделать ключи уникальными
409ALREADY_TAKENtake для уже завершённой (done) заявкиЗаявка закрыта, действий не требуется
409INVALID_STATUS_TRANSITIONНедопустимый переход (waiting из taken/done; результат — из taken). Для заявки в done вместо этого кода приходит ALREADY_FILLED (см. ниже)Привести заявку к нужному статусу (takewaiting)
409INCOMPATIBLE_RESULT_FORMATСмешение html и values в одной заявкеИспользовать формат первого результата
409ALREADY_FILLEDПо анализу результат уже отправлен, в т.ч. любой повторный результат по завершённой (done) заявке — все её анализы гарантированно заполнены, и эта проверка выполняется раньше проверки статусаНе отправлять повторно

8.2. Особый случай: 200total = 0

GET /list вернул success: true, но total: 0 и пустой labanalysisrequest. Это не ошибка авторизации — ключи приняты. Причины:

  • по клинике нет заявок в выбранном status;
  • интеграция включена не для той клиники, по чьему {clinic_host} идёт запрос;
  • на стороне клиники не активирована интеграция в настройках (раздел 9).

Проверьте: правильный ли {clinic_host}, создана ли заявка на провайдера, включена ли интеграция per-клиника.


9. Требования на стороне клиники

Чтобы заявки клиники стали видны через Provider API, на стороне клиники должны выполняться все условия:

  1. Подключён тариф/аддон вашей лаборатории (биллинг).
  2. Включена интеграция в настройках клиники: «Настройки» → «Интеграция с сервисами» → карточка вашей лаборатории (по имени {service_name}) → переключатель «Вкл». Технически это глобальный флаг сервиса (service.{service_name}) и per-клиника флаг интеграции — один и тот же тумблер на экране ниже.

Включение интеграции в настройках клиники

  1. Создана заявка в модуле «Лаборатория» на вашего провайдера — она появляется в очереди в статусе taken. Заявка создаётся из карточки приёма/медкарты («Взятие анализа» → «Создать анализ»): сотрудник клиники указывает питомца, провайдера и нужные анализы из каталога, привязанного к этому провайдеру.

Создание заявки на анализ в модуле «Лаборатория»

Если интеграция выключена или заявок нет — провайдер увидит 404 NOT_FOUND на адресные операции и total = 0 в list.


10. Postman

Готовая коллекция: provider-api-v1.postman_collection.json.

Импортируйте коллекцию и задайте переменные окружения (Environment):

ПеременнаяЗначение
clinic_hostхост клиники (без протокола), например {clinic_host}
service_name{service_name}
rest_api_key{rest_api_key}
billing_hostхост billing-api
billing_authkey{billing_authkey}
request_idID заявки для take/waiting/result
analyze_idID анализа для result

Секреты в коллекцию не зашиты — все значения берутся из переменных окружения.


Приложение A. Примеры curl

# 0. Список доменов клиник
curl -s "https://{billing_host}/lab-domains/{billing_authkey}"

# 1. Очередь заявок клиники
curl -s "https://{clinic_host}/rest/api/provider-lab-requests/list?status=taken&limit=50" \
  -H "X-SERVICE-NAME: {service_name}" \
  -H "X-SERVICE-REST-API-KEY: {rest_api_key}"

# 2. Взять заявку в работу
curl -s -X POST "https://{clinic_host}/rest/api/provider-lab-requests/take" \
  -H "X-SERVICE-NAME: {service_name}" \
  -H "X-SERVICE-REST-API-KEY: {rest_api_key}" \
  -H "Content-Type: application/json" \
  -d '{"request_id": {request_id}}'

# 3. (опционально) Пометить ожидание результата
curl -s -X POST "https://{clinic_host}/rest/api/provider-lab-requests/waiting" \
  -H "X-SERVICE-NAME: {service_name}" \
  -H "X-SERVICE-REST-API-KEY: {rest_api_key}" \
  -H "Content-Type: application/json" \
  -d '{"request_id": {request_id}}'

# 4a. Результат в формате HTML
curl -s -X POST "https://{clinic_host}/rest/api/provider-lab-requests/result-html" \
  -H "X-SERVICE-NAME: {service_name}" \
  -H "X-SERVICE-REST-API-KEY: {rest_api_key}" \
  -H "Content-Type: application/json" \
  -d '{
        "request_id": {request_id},
        "analyze_id": {analyze_id},
        "html": "<table><tr><td>HGB</td><td>140 g/L</td></tr></table>",
        "measured_at": "2024-01-15T10:30:00+02:00"
      }'

# 4b. Результат в формате values
curl -s -X POST "https://{clinic_host}/rest/api/provider-lab-requests/result-values" \
  -H "X-SERVICE-NAME: {service_name}" \
  -H "X-SERVICE-REST-API-KEY: {rest_api_key}" \
  -H "Content-Type: application/json" \
  -d '{
        "request_id": {request_id},
        "analyze_id": {analyze_id},
        "values": [
          {"name": "HGB", "value": "140", "unit": "g/L"},
          {"name": "WBC", "value": "8.5", "unit": "10^9/L"}
        ],
        "measured_at": "2024-01-15T10:30:00+02:00"
      }'

# 4c. Результат в формате values с нормами и названием (v2.1)
curl -s -X POST "https://{clinic_host}/rest/api/provider-lab-requests/result-values" \
  -H "X-SERVICE-NAME: {service_name}" \
  -H "X-SERVICE-REST-API-KEY: {rest_api_key}" \
  -H "Content-Type: application/json" \
  -d '{
        "request_id": {request_id},
        "analyze_id": {analyze_id},
        "values": [
          {"name": "HGB", "title": "Гемоглобин", "value": "140", "unit": "g/L",
           "reference_range": {"min": 120, "max": 180}},
          {"name": "K", "title": "Калий", "value": "8.2", "unit": "ммоль/л",
           "reference_range": {"min": 3.5, "max": 5.8}, "flag": "critical_high"}
        ],
        "measured_at": "2024-01-15T10:30:00+02:00"
      }'

Приложение B. Контакты поддержки

По вопросам подключения, выдачи ключей и работы Provider API обращайтесь в поддержку Vetmanager по официальным каналам, указанным в вашем договоре/онбординге.


Документ относится к Provider API v2.1. v2.1 полностью совместим с v1: интеграция, которая не использует title/reference_range/flag, продолжает работать без изменений. Внутренние детали деплоя и инфраструктуры намеренно опущены.

Powered by