#Запись вне МИС (Import)
Сценарий Import нужен, когда врач записывает приём в smartica.ai, не открывая МИС. Типичные случаи: запись с телефона на выезде или запись во время обхода.
Позже врач открывает МИС, находит эту запись в списке и привязывает её к приёму.
Если врач работает за компьютером с открытой МИС, используйте Запуск из МИС, протокол присылаем мы (Launch).
#Чем Import отличается от Launch
| Launch | Import | |
|---|---|---|
| С чего начинается | Кнопка в карточке приёма МИС | Запись в smartica.ai, позже форма в МИС |
| Когда известен ID приёма МИС | Сразу, в SSO-запросе | Позже, в момент привязки |
| Откуда берутся поля бланка | Обычно GET у вашей МИС |
Всегда из тела запроса на привязку |
| Нужен ли SSO | Да | Нет |
| Типичная ситуация | Врач за рабочим местом | Приёмы «в поле», обходы, выезды |
Оба сценария используют один и тот же platform и один и тот же API-ключ клиники. Режим доставки (push или pull) тоже общий для всего подключения.
Сценарии можно включить одновременно.
#Не перепутайте два идентификатора
В Import два идентификатора.
| Поле | Чей ID | Где находится | Пример |
|---|---|---|---|
smartica_encounter_id |
smartica.ai | В адресе запроса | 7f3a9c2e-4b1e-4a8d-9c3f-2e1a8b4d6f0c |
encounter_id |
ваша МИС | В теле запроса | 12345 |
smartica_encounter_id ставьте в адрес запроса. encounter_id ставьте в тело запроса.
#Как это работает по шагам
- Врач записывает приём в smartica.ai. Появляется стенограмма.
- Позже врач открывает в МИС форму «Импорт из smartica.ai».
- Ваш бэкенд запрашивает у smartica.ai список записей, ожидающих привязки.
- Врач выбирает нужную запись в списке. Врач указывает приём МИС для этой записи.
- Ваш бэкенд отправляет запрос на привязку. В этом запросе бэкенд передаёт название бланка и поля бланка.
- smartica.ai заполняет протокол.
- Результат попадает в МИС. В режиме
pushsmartica.ai присылаетPUT. В режимеpullвы забираете протокол. В этом режиме вы отправляете подтверждение.
Интерфейс выбора находится в вашей МИС. smartica.ai только отдаёт список и принимает привязку.
"title": "Приём 26 мая, 14:30",
"status": "awaiting_import"
#Базовый адрес и авторизация
Все запросы этого сценария идут от вас к smartica.ai:
https://app.smartica.ai/api/v1/integrations/{platform}
{platform} — идентификатор вашей клиники, выданный при подключении. Заголовки:
Authorization: Bearer <API-ключ клиники>
Accept: application/json
Ключ тот же, что для SSO в сценарии Launch. Храните ключ только на сервере.
Все ошибки приходят в одном формате:
{
"error": "encounter_taken",
"message": "Этот приём МИС уже привязан к другой записи."
}
При ошибке валидации в ответ добавляется объект errors с ошибками по полям.
#Шаг 1. Получить список записей
GET /api/v1/integrations/{platform}/encounters?user_email=doctor@clinic.ru&user_full_name=Иванов%20Иван%20Иванович&status=awaiting_import&limit=50
Authorization: Bearer <API-ключ клиники>
Accept: application/json
#Параметры запроса
| Параметр | Обязательный | Описание |
|---|---|---|
user_email |
да | Email врача. В списке только записи этого врача |
user_full_name |
почти всегда | ФИО врача |
status |
да | awaiting_import для формы выбора |
since |
нет | Записи старше этой даты не входят в список. Самая ранняя дата — 90 дней назад |
limit |
нет | Число записей в ответе. По умолчанию 50, максимум 100 |
cursor |
нет | Маркер следующей страницы из предыдущего ответа |
Передавайте user_full_name в каждом запросе. Если аккаунта врача ещё нет и для клиники включено автосоздание, smartica.ai создаёт аккаунт врача по этому ФИО.
Если вы не передали since, smartica.ai возвращает записи за последние 30 дней.
Если врача с таким email нет и вы не передали user_full_name, ответ 404 doctor_not_found. Пустой список значит, что врач есть, а записей нет.
#Ответ 200
{
"encounters": [
{
"smartica_encounter_id": "7f3a9c2e-4b1e-4a8d-9c3f-2e1a8b4d6f0c",
"title": "Приём 26 мая, 14:30",
"recorded_at": "2026-05-26T14:30:11+00:00",
"duration_sec": 742,
"status": "awaiting_import"
},
{
"smartica_encounter_id": "b2c1d0e9-8f7a-4b6c-9d5e-1a2b3c4d5e6f",
"title": "Приём 26 мая, 15:05",
"recorded_at": "2026-05-26T15:05:42+00:00",
"duration_sec": 313,
"status": "awaiting_import"
}
],
"next_cursor": null
}
| Поле | Описание |
|---|---|
smartica_encounter_id |
ID записи в smartica.ai |
title |
Заголовок записи для списка |
recorded_at |
Время записи в формате ISO 8601 |
duration_sec |
Длительность в секундах. Может быть null |
status |
В этом ответе всегда awaiting_import |
next_cursor |
Маркер следующей страницы или null, если список кончился |
Подставьте smartica_encounter_id в адрес запроса на шаге 2.
#Постраничный обход
Если next_cursor не null, передайте next_cursor в параметре cursor следующего запроса. Не разбирайте содержимое cursor.
GET /api/v1/integrations/{platform}/encounters?user_email=doctor@clinic.ru&status=awaiting_import&cursor=eyJjcmVhdGVkX2F0IjoiMjAyNi0wOC0wNyAxNDozMDoxMS4wMDAwMDAiLCJzbWFydGljYV9lbmNvdW50ZXJfaWQiOiI3ZjNhOWMyZS00YjFlLTRhOGQtOWMzZi0yZTFhOGI0ZDZmMGMifQ==
Повторяйте запрос, пока next_cursor не станет null.
#Список по другим статусам
Для режима pull или для мониторинга передайте другое значение status. В ответе появляются два дополнительных поля:
{
"encounters": [
{
"smartica_encounter_id": "7f3a9c2e-4b1e-4a8d-9c3f-2e1a8b4d6f0c",
"title": "Приём 26 мая, 14:30",
"recorded_at": "2026-05-26T14:30:11+00:00",
"duration_sec": 742,
"status": "ready",
"encounter_id": "12345",
"revision": 1
}
],
"next_cursor": null
}
#Шаг 2. Привязать запись к приёму МИС
POST /api/v1/integrations/{platform}/encounters/{smartica_encounter_id}/import
Authorization: Bearer <API-ключ клиники>
Content-Type: application/json
Accept: application/json
{
"user_email": "doctor@clinic.ru",
"user_full_name": "Иванов Иван Иванович",
"encounter_id": "12345",
"template": "Кардиолог",
"fields": [
{ "id": "complaints", "label": "Жалобы" },
{ "id": "diagnosis_primary", "label": "Диагноз (основной)" }
]
}
#Поля тела запроса
| Поле | Обязательное | Описание |
|---|---|---|
user_email |
да | Email врача, которому принадлежит запись |
user_full_name |
почти всегда | ФИО врача |
encounter_id |
да | ID приёма или документа в вашей МИС. Только цифры или UUID |
template |
да | Название бланка или специальности |
fields |
да | Непустой массив до 80 полей. Обязательны id и label. type необязателен. Типы описаны в статье Типы полей бланка |
rebind |
нет | true для смены encounter_id |
Передавайте user_full_name в каждом запросе. Если аккаунта врача ещё нет и для клиники включено автосоздание, smartica.ai создаёт аккаунт врача по этому ФИО.
Отдельного запроса за списком бланков нет. Передайте template и fields в этом запросе.
type необязателен. Если вы его передали, value в протоколе приходит в этом типе. Правила типов описаны в статье Типы полей бланка. Ошибка в описании поля даёт ответ 422.
#Ответ 202 Accepted
Код ответа 202, не 200, потому что заполнение протокола начинается асинхронно. Готового протокола в этом ответе нет.
{
"smartica_encounter_id": "7f3a9c2e-4b1e-4a8d-9c3f-2e1a8b4d6f0c",
"encounter_id": "12345",
"status": "processing",
"revision": 0
}
После успешной привязки запись исчезает из списка awaiting_import.
Повторный запрос с той же парой smartica_encounter_id и encounter_id возвращает тот же ответ. Вторая привязка не создаётся.
Если в бланке есть поля с одинаковым id, в ответ добавляется массив warnings. Привязка проходит. smartica.ai не заполняет часть полей. Подробности смотрите в разделе Дубликаты id в бланке.
#Перепривязка
Если врач привязал запись не к тому приёму МИС, отправьте запрос заново с новым encounter_id и rebind: true. В ответе добавляется previous_encounter_id:
{
"smartica_encounter_id": "7f3a9c2e-4b1e-4a8d-9c3f-2e1a8b4d6f0c",
"encounter_id": "67890",
"previous_encounter_id": "12345",
"status": "processing",
"revision": 1
}
Если при перепривязке изменились template или fields, smartica.ai заполняет протокол заново.
Без rebind: true привязка к другому encounter_id возвращает 409 already_imported.
#Пример клиента
В примере две операции. Сначала запрос списка записей со статусом awaiting_import. Затем привязка выбранной записи к приёму МИС. Ключ берётся из окружения. platform берётся из конфигурации.
$base = 'https://app.smartica.ai/api/v1/integrations/'.getenv('SMARTICA_PLATFORM');
$headers = [
'Authorization' => 'Bearer '.getenv('SMARTICA_SSO_KEY'),
'Accept' => 'application/json',
];
// 1. Список записей, ожидающих привязки. Листаем по next_cursor.
$encounters = [];
$cursor = null;
do {
$response = $http->get($base.'/encounters', [
'headers' => $headers,
'query' => array_filter([
'user_email' => $doctor->email,
'status' => 'awaiting_import',
'limit' => 50,
'cursor' => $cursor,
]),
]);
$page = json_decode((string) $response->getBody(), true);
$encounters = array_merge($encounters, $page['encounters']);
$cursor = $page['next_cursor'];
} while ($cursor !== null);
// 2. Привязка выбранной записи к приёму МИС.
$response = $http->post($base.'/encounters/'.$smarticaEncounterId.'/import', [
'headers' => $headers,
'json' => [
'user_email' => $doctor->email,
'encounter_id' => (string) $encounter->id,
'template' => $encounter->form->name,
'fields' => $fields, // [['id' => ..., 'label' => ...], ...]
],
]);
// 202 Accepted — заполнение началось, результата здесь ещё нет.
const base = `https://app.smartica.ai/api/v1/integrations/${process.env.SMARTICA_PLATFORM}`;
const headers = {
Authorization: `Bearer ${process.env.SMARTICA_SSO_KEY}`,
Accept: 'application/json',
};
// 1. Список записей, ожидающих привязки. Листаем по next_cursor.
const encounters = [];
let cursor = null;
do {
const query = new URLSearchParams({
user_email: doctor.email,
status: 'awaiting_import',
limit: '50',
...(cursor ? { cursor } : {}),
});
const page = await fetch(`${base}/encounters?${query}`, { headers }).then((r) => r.json());
encounters.push(...page.encounters);
cursor = page.next_cursor;
} while (cursor !== null);
// 2. Привязка выбранной записи к приёму МИС.
await fetch(`${base}/encounters/${smarticaEncounterId}/import`, {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify({
user_email: doctor.email,
encounter_id: String(encounter.id),
template: encounter.form.name,
fields, // [{ id, label }, ...]
}),
});
// 202 Accepted — заполнение началось, результата здесь ещё нет.
base = f"https://app.smartica.ai/api/v1/integrations/{os.environ['SMARTICA_PLATFORM']}"
headers = {
"Authorization": f"Bearer {os.environ['SMARTICA_SSO_KEY']}",
"Accept": "application/json",
}
# 1. Список записей, ожидающих привязки. Листаем по next_cursor.
encounters = []
cursor = None
while True:
params = {"user_email": doctor.email, "status": "awaiting_import", "limit": 50}
if cursor:
params["cursor"] = cursor
page = httpx.get(f"{base}/encounters", headers=headers, params=params, timeout=30).json()
encounters.extend(page["encounters"])
cursor = page["next_cursor"]
if cursor is None:
break
# 2. Привязка выбранной записи к приёму МИС.
httpx.post(
f"{base}/encounters/{smartica_encounter_id}/import",
headers=headers,
json={
"user_email": doctor.email,
"encounter_id": str(encounter.id),
"template": encounter.form.name,
"fields": fields, # [{ "id": ..., "label": ... }, ...]
},
timeout=30,
)
# 202 Accepted — заполнение началось, результата здесь ещё нет.
var baseUrl = $"https://app.smartica.ai/api/v1/integrations/{platform}";
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("SMARTICA_SSO_KEY"));
// 1. Список записей, ожидающих привязки. Листаем по next_cursor.
var encounters = new List<PartnerEncounter>();
string? cursor = null;
do
{
var url = $"{baseUrl}/encounters?user_email={Uri.EscapeDataString(doctor.Email)}"
+ $"&status=awaiting_import&limit=50"
+ (cursor is null ? "" : $"&cursor={Uri.EscapeDataString(cursor)}");
var page = await httpClient.GetFromJsonAsync<EncounterPage>(url);
encounters.AddRange(page!.Encounters);
cursor = page.NextCursor;
}
while (cursor is not null);
// 2. Привязка выбранной записи к приёму МИС.
var response = await httpClient.PostAsJsonAsync(
$"{baseUrl}/encounters/{smarticaEncounterId}/import",
new
{
user_email = doctor.Email,
encounter_id = encounter.Id.ToString(),
template = encounter.Form.Name,
fields // [{ id, label }, ...]
});
// 202 Accepted — заполнение началось, результата здесь ещё нет.
String baseUrl = "https://app.smartica.ai/api/v1/integrations/" + platform;
String auth = "Bearer " + System.getenv("SMARTICA_SSO_KEY");
// 1. Список записей, ожидающих привязки. Листаем по next_cursor.
List<PartnerEncounter> encounters = new ArrayList<>();
String cursor = null;
do {
String url = baseUrl + "/encounters"
+ "?user_email=" + URLEncoder.encode(doctor.getEmail(), StandardCharsets.UTF_8)
+ "&status=awaiting_import&limit=50"
+ (cursor == null ? "" : "&cursor=" + URLEncoder.encode(cursor, StandardCharsets.UTF_8));
HttpRequest request = HttpRequest.newBuilder(URI.create(url))
.header("Authorization", auth)
.header("Accept", "application/json")
.GET()
.build();
EncounterPage page = objectMapper.readValue(
httpClient.send(request, BodyHandlers.ofString()).body(), EncounterPage.class);
encounters.addAll(page.encounters());
cursor = page.nextCursor();
} while (cursor != null);
// 2. Привязка выбранной записи к приёму МИС.
Map<String, Object> payload = Map.of(
"user_email", doctor.getEmail(),
"encounter_id", String.valueOf(encounter.getId()),
"template", encounter.getForm().getName(),
"fields", fields // [{ id, label }, ...]
);
HttpRequest importRequest = HttpRequest.newBuilder(
URI.create(baseUrl + "/encounters/" + smarticaEncounterId + "/import"))
.header("Authorization", auth)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(payload)))
.build();
// 202 Accepted — заполнение началось, результата здесь ещё нет.
httpClient.send(importRequest, BodyHandlers.ofString());
Функция ЗапросКSmartica(Метод, Путь, Тело = Неопределено)
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + Константы.SmarticaКлючКлиники.Получить());
Заголовки.Вставить("Accept", "application/json");
Если Тело <> Неопределено Тогда
Заголовки.Вставить("Content-Type", "application/json");
КонецЕсли;
Соединение = Новый HTTPСоединение(
"app.smartica.ai", 443, , , , 30, Новый ЗащищенноеСоединениеOpenSSL);
База = "/api/v1/integrations/" + Константы.SmarticaPlatform.Получить();
Запрос = Новый HTTPЗапрос(База + Путь, Заголовки);
Если Тело <> Неопределено Тогда
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Тело);
Запрос.УстановитьТелоИзСтроки(Запись.Закрыть(), КодировкаТекста.UTF8);
КонецЕсли;
Ответ = ?(Метод = "GET", Соединение.Получить(Запрос), Соединение.ОтправитьДляОбработки(Запрос));
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Результат = ПрочитатьJSON(Чтение, Истина);
Чтение.Закрыть();
Возврат Новый Структура("Код, Данные", Ответ.КодСостояния, Результат);
КонецФункции
// 1. Список записей, ожидающих привязки.
Список = ЗапросКSmartica("GET",
"/encounters?user_email=" + КодироватьСтроку(Врач.Email, СпособКодированияСтроки.КодировкаURL)
+ "&status=awaiting_import&limit=50");
// 2. Привязка выбранной записи к приёму МИС.
Поля = Новый Массив;
Поля.Добавить(Новый Структура("id, label", "complaints", "Жалобы"));
Поля.Добавить(Новый Структура("id, label", "diagnosis_primary", "Диагноз (основной)"));
Тело = Новый Структура;
Тело.Вставить("user_email", Врач.Email);
Тело.Вставить("encounter_id", Строка(Приём.Код));
Тело.Вставить("template", "Кардиолог");
Тело.Вставить("fields", Поля);
Итог = ЗапросКSmartica("POST", "/encounters/" + ВыбранныйUUID + "/import", Тело);
#Статусы записи
status |
Что означает | Что делать |
|---|---|---|
awaiting_import |
Стенограмма есть. К приёму МИС ещё не привязана | Покажите запись врачу в форме выбора |
processing |
Привязка принята. Идёт заполнение протокола | Подождите |
ready |
Протокол готов | При pull заберите протокол. При push ничего не делайте. smartica.ai присылает протокол сама |
accepted |
Протокол доставлен в МИС | Готово |
failed |
Заполнение не удалось | Обратитесь в поддержку |
#Шаг 3. Получить результат
Дальше действуйте по режиму доставки подключения.
#Режим push
Ничего не делайте. Когда протокол готов, smartica.ai сама вызывает ваш PUT, как в сценарии Launch. Контракт описан в статье Запись протокола в карту.
#Режим pull: забрать протокол
Опрашивайте записи со статусом ready. Запрос, ответ 200 и правило пустых полей описаны в статье Готовый протокол.
Запомните revision из ответа. Номер нужен на следующем шаге.
#Режим pull: подтвердить получение
После того как вы успешно сохранили протокол у себя, отправьте подтверждение:
POST /api/v1/integrations/{platform}/encounters/{smartica_encounter_id}/ack
Authorization: Bearer <API-ключ клиники>
Content-Type: application/json
{
"revision": 1
}
Ответ 200:
{
"smartica_encounter_id": "7f3a9c2e-4b1e-4a8d-9c3f-2e1a8b4d6f0c",
"status": "accepted",
"revision": 1
}
Отправьте подтверждение только после того, как протокол сохранён в МИС. Пока подтверждения нет, smartica.ai считает приём недоставленным, и врач видит это в интерфейсе.
Повторное подтверждение той же ревизии безопасно. smartica.ai возвращает тот же ответ.
#Что если ревизия устарела
Пока вы сохраняли протокол, врач мог дописать приём. Тогда smartica.ai заполняет протокол заново и увеличивает revision. Подтверждение старой ревизии отклоняется:
{
"error": "revision_mismatch",
"message": "Ревизия устарела — заберите протокол заново.",
"revision": 4
}
Код ответа 409. В поле revision приходит актуальный номер. Заберите протокол заново. Подтвердите новую ревизию. Обновите данные, которые уже сохранили. Сохранённая копия устарела.
Если врач после сохранения поправил протокол в МИС, пришлите итог отдельным запросом. Возьмите номер ревизии из ответа GET или из заголовка PUT. Порядок запроса описан в статье Протокол после правки врача.
#Правила, которые нельзя нарушить
- Одна запись smartica.ai привязывается к одному приёму МИС. Сменить приём можно только через
rebind. - Один
encounter_idвашей МИС занимает одна запись smartica.ai. Вторая привязка к этомуencounter_idвозвращаетencounter_taken. - Привязать можно только запись со стенограммой. Если стенограммы нет, ответ
no_transcript.
#Ошибки
| HTTP | error |
Причина | Что делать |
|---|---|---|---|
401 |
invalid_bearer_key |
Ключ неверен или не передан | Проверьте API-ключ клиники. Не повторяйте запрос автоматически |
404 |
wrong_host |
Базовый адрес не совпадает с адресом контура | Возьмите адрес из статьи Тестовая площадка |
404 |
doctor_not_found |
Врача с таким email нет в вашей клинике. Создать врача нельзя | Проверьте email. Передайте user_full_name. Повторите запрос. Если ошибка остаётся, автосоздание для клиники выключено. Напишите в поддержку smartica.ai |
404 |
encounter_not_found |
Запись не найдена или принадлежит другому врачу | Проверьте smartica_encounter_id и user_email |
403 |
email_in_other_organization |
Email уже относится к другой организации в smartica.ai | Напишите в поддержку smartica.ai. Попросите перенести аккаунт |
409 |
no_transcript |
У записи ещё нет стенограммы | Подождите. Повторите запрос |
409 |
already_imported |
Запись уже привязана к другому приёму МИС | Если запись нужно перепривязать, передайте rebind: true |
409 |
encounter_taken |
Этот encounter_id уже занят другой записью |
Выберите другой приём МИС |
409 |
revision_mismatch |
Вы подтверждаете устаревшую ревизию | Заберите протокол заново. Подтвердите актуальную ревизию |
410 |
encounter_deleted |
Врач удалил запись в smartica.ai | Уберите запись из очереди. Ничего не сохраняйте |
422 |
validation_failed |
Ошибка в полях, в том числе нет ФИО для создания врача. Или ошибка в формате encounter_id |
Исправьте поля. Подробности смотрите в объекте errors |
429 |
— | Превышен лимит запросов | Учтите заголовок Retry-After. Снизьте частоту опроса |
Точные значения лимитов смотрите в статье Лимиты.
#Чеклист
- Список
awaiting_importзапрашивается с бэкенда. Ключ не попадает в браузер - В запросе списка и в запросе привязки всегда передаётся
user_full_name - Реализован постраничный обход по
next_cursor - В форме врач выбирает и запись smartica.ai, и приём МИС
- В запросе на привязку передаются
templateи непустойfields - Привязка выполняется по одной записи за раз
- Привязанные записи не показываются в списке повторно
- При
pushреализован приёмPUT - При
pullреализованы забор протокола и подтверждение. В подтверждении передаётся актуальнаяrevision - Поля, которых нет в
fields, при записи не очищаются - Обрабатывается
409 revision_mismatch. Перед новым подтверждением протокол забирается заново