Entegrasyon

Ssemora'yı REST API ile sistemlerinize bağlayın.

HBYS gibi dış sistemler bir muayenenin ses kaydını Ssemora'ya gönderebilir, işleme durumunu izleyebilir ve hekim onaylı raporu JSON ya da Word olarak alabilir.

Dört Adımda Entegrasyon

  1. Anahtar Alın

    Kurumunuz için kapsamları ve sınırları belirlenmiş bir API anahtarı oluşturulur. Bağlantıyı GET /integration/me ile deneyin.

  2. Muayeneyi Gönderin

    Ses dosyasını ve rıza beyanını POST /integration/encounters ile gönderin. Yanıt 202 ile gelir.

  3. Durumu İzleyin

    Muayeneyi sorgulayın. poll_after_sec doluyken işleme sürüyor demektir; bu değeri (3 sn) bekleme aralığı olarak kullanın.

  4. Raporu Alın

    Hekim onayladığında rapor JSON ya da Word olarak alınır. Onaylanmamış rapor için 409 report_not_approved döner.

Uç Noktalar

Tüm yollar /api/v1 önekiyle başlar; aşağıda önek yazılmamıştır. Kapsam sütunu, anahtarda bulunması gereken yetkiyi gösterir.

YöntemYolKapsamNe Yapar
GET/integration/me—Anahtarı ve kurumu tanıtır; bağlantıyı denemek için kullanılır.
POST/integration/encountersencounters:writeSes dosyası ve rıza ile muayene oluşturur (202).
GET/integration/encountersencounters:readMuayeneleri listeler; external_ref ve page ile süzülür.
GET/integration/encounters/{id}encounters:readMuayenenin işleme durumunu verir.
GET/integration/encounters/{id}/reportreports:readRaporu JSON olarak verir; kanıt aralıkları dahildir.
GET/integration/encounters/{id}/report.docxreports:readRaporu Word dosyası olarak verir.
DELETE/integration/encounters/{id}encounters:writeMuayeneyi siler. Onaylı muayene silinemez (409 invalid_state).

Muayene Oluştururken Gönderilen Alanlar

AlanZorunluAçıklama
audioEvetSes dosyası: webm, wav, mp3, m4a, mp4, ogg, opus, flac ya da aac.
consent_confirmedEvetHasta rızasının alındığına dair beyan; true olmalıdır. Beyan, denetim günlüğüne source=api ile yazılır.
external_refHayırKendi sisteminizdeki kayıt numarası (en çok 200 karakter, benzersiz). Aynı değerle ikinci muayene 409 duplicate_external_ref döndürür.
file_no, patient_ref, patient_name, subject_titleEn az biriMuayeneyi tanımlayan alanlar. Yanıtlarda hasta referansı maskelenir.
template_idHayırKullanılacak rapor şablonunun kimliği. Bulunamazsa 422 template_not_found.
subject_typeHayırMuayenenin konu türü.
physician_usernameHayırMuayenenin atanacağı hekimin kullanıcı adı. Bulunamazsa 422 physician_not_found.

Örnekler

Örneklerde $SEMORA_URL kurumunuzun adresini, $SEMORA_API_KEY anahtarınızı gösterir. Anahtarı adres satırına yazmayın; yalnızca Authorization başlığında gönderin.

1. Muayene Oluşturma (cURL)
curl -X POST "$SEMORA_URL/api/v1/integration/encounters" \
  -H "Authorization: Bearer $SEMORA_API_KEY" \
  -F "audio=@muayene.webm" \
  -F "consent_confirmed=true" \
  -F "external_ref=HBYS-2026-0001" \
  -F "file_no=A-1042"
Yanıt (202): İşleme Sürüyor
{
  "id": "6f1c2d3e-4a5b-6789-abcd-0123456789ab",
  "external_ref": "HBYS-2026-0001",
  "source": "api",
  "status": "processing",
  "progress_percent": null,
  "error_code": null,
  "subject_title": null,
  "file_no": "A-1042",
  "patient_ref_masked": null,
  "created_at": "2026-10-27T09:15:03.120000Z",
  "ended_at": "2026-10-27T09:15:03.101000Z",
  "poll_after_sec": 3,
  "links": {
    "self": "/api/v1/integration/encounters/6f1c2d3e-4a5b-6789-abcd-0123456789ab",
    "report": "/api/v1/integration/encounters/6f1c2d3e-4a5b-6789-abcd-0123456789ab/report",
    "report_docx": "/api/v1/integration/encounters/6f1c2d3e-4a5b-6789-abcd-0123456789ab/report.docx"
  }
}
2. Tüm Akış (Python)
import os
import time
import requests

BASE = os.environ["SEMORA_URL"]
HEADERS = {"Authorization": "Bearer " + os.environ["SEMORA_API_KEY"]}

with open("muayene.webm", "rb") as audio:
    r = requests.post(
        f"{BASE}/api/v1/integration/encounters",
        headers=HEADERS,
        data={"consent_confirmed": "true", "external_ref": "HBYS-2026-0001", "file_no": "A-1042"},
        files={"audio": audio},
    )
r.raise_for_status()
encounter = r.json()

# poll_after_sec dolu olduğu sürece muayene işleniyor.
while encounter["poll_after_sec"]:
    time.sleep(encounter["poll_after_sec"])
    encounter = requests.get(BASE + encounter["links"]["self"], headers=HEADERS).json()

# Hekim onaylayana kadar bu uç 409 report_not_approved döndürür.
report = requests.get(BASE + encounter["links"]["report"], headers=HEADERS)
print(report.status_code)
3. Raporu Alma (cURL)
# JSON
curl "$SEMORA_URL/api/v1/integration/encounters/$ENCOUNTER_ID/report" \
  -H "Authorization: Bearer $SEMORA_API_KEY"

# Word
curl "$SEMORA_URL/api/v1/integration/encounters/$ENCOUNTER_ID/report.docx" \
  -H "Authorization: Bearer $SEMORA_API_KEY" \
  -o rapor.docx

# Hekim onaylamadan taslağı görmek için
curl "$SEMORA_URL/api/v1/integration/encounters/$ENCOUNTER_ID/report?status=any" \
  -H "Authorization: Bearer $SEMORA_API_KEY"
Rapor Yanıtı (Kısaltılmış): Her Alan Kanıt Aralıklarını Taşır
{
  "encounter_id": "6f1c2d3e-4a5b-6789-abcd-0123456789ab",
  "external_ref": "HBYS-2026-0001",
  "encounter_status": "approved",
  "report_status": "onaylandi",
  "approved": true,
  "report": {
    "version": 1,
    "status": "onaylandi",
    "fields": {
      "anamnez": {
        "label": "Anamnez",
        "content": "Üç gündür süren öksürük…",
        "spans": [
          { "start": 120, "end": 168, "verified": true, "t_start": 12.4, "t_end": 19.0 }
        ],
        "attention": [],
        "edited": false
      }
    }
  },
  "text": "Anamnez\nÜç gündür süren öksürük…"
}

Her spans öğesi, cümlenin transkriptteki karakter aralığını (start, end) ve ses kaydındaki saniye aralığını (t_start, t_end) verir. attention alanı o bölümdeki dikkat öğelerini, edited hekimin düzenleyip düzenlemediğini gösterir.

Kimlik Doğrulama, Kapsamlar ve Sınırlar

Kimlik Doğrulama

Her istekte Authorization: Bearer smk_… başlığı gönderilir. Anahtarlar kurumunuz için Ssemora yönetimi tarafından oluşturulur; ad, kapsamlar, dakikalık sınır, azami dosya boyutu, isteğe bağlı son kullanma ve izinli IP/CIDR listesi oluşturulurken belirlenir. Anahtar yalnızca bir kez gösterilir.

Kapsamlar

  • encounters:write — muayene oluşturma (ses yükleme) ve silme.
  • encounters:read — muayene durumunu ve listesini okuma.
  • reports:read — raporu JSON ve Word olarak okuma.

Sınırlar

SınırDeğerAşılırsa
İstek hızıVarsayılan: anahtar başına dakikada 60 (6000'e kadar ayarlanabilir)429 rate_limited ve Retry-After başlığı
Dosya boyutuVarsayılan 25 MB (1–100 MB arası ayarlanabilir)413 payload_too_large
Ses biçimiwebm, wav, mp3, m4a, mp4, ogg, opus, flac, aac422 unsupported_audio_type
İzinli IP/CIDRİsteğe bağlı liste403 ip_not_allowed
Son kullanmaİsteğe bağlı tarih401 api_key_expired

Hata Sözleşmesi

Hatalar her zaman aynı JSON biçimindedir: ayrıntılı error nesnesi ile kısa code ve status alanları.

Örnek Hata (409)
{
  "error": {
    "code": "report_not_approved",
    "message": "Rapor henüz hekim tarafından onaylanmadı.",
    "details": {}
  },
  "code": "report_not_approved",
  "status": 409
}
DurumKodAnlamı
400consent_requiredconsent_confirmed=true gönderilmedi.
401missing_api_keyAuthorization: Bearer başlığı yok.
401invalid_api_keyAnahtar bulunamadı ya da biçimi geçersiz.
401api_key_revokedAnahtar iptal edilmiş.
401api_key_inactiveAnahtar pasifleştirilmiş.
401api_key_expiredAnahtarın son kullanma tarihi geçmiş.
403ip_not_allowedİstek, anahtarın izinli IP/CIDR listesi dışından geldi.
403insufficient_scopeAnahtarın bu uç için gereken kapsamı yok (details.required_scopes).
403tenant_inactiveKurum hesabı etkin değil.
404not_foundKaynak yok ya da bu anahtarın erişimi dışında.
405method_not_allowedBu yol için yöntem desteklenmiyor (Allow başlığına bakın).
409duplicate_external_refBu external_ref ile muayene zaten var (details.encounter_id).
409report_not_approvedRapor henüz hekim tarafından onaylanmadı; taslak için status=any.
409not_readyMuayene hâlâ işleniyor.
409processing_failedMuayene işlenemedi (details.error_code).
409invalid_stateMuayenenin durumu bu işleme izin vermiyor (ör. onaylı muayene silinemez).
413payload_too_largeDosya, anahtarın azami boyutunu aşıyor.
422validation_errorAlanlar geçersiz ya da eksik.
422unsupported_audio_typeSes biçimi desteklenmiyor.
422template_not_foundŞablon bulunamadı ya da etkin değil.
422physician_not_foundphysician_username bulunamadı ya da etkin değil.
429rate_limitedDakikalık istek sınırı aşıldı (Retry-After).

HBYS ile Bağlantı

Türkiye'de her hastanenin HBYS'si farklıdır. Bu yüzden Ssemora'ya tek bir ortak HBYS bağlantısı gömülmez: her kurum için o kurumun sistemine özgü bir bağlayıcı (adaptör) yazılır ve kurum ayarlarından seçilir. Bağlayıcının kimlik bilgileri kurum ayarlarında tutulur, kodun içine gömülmez.

Bağlayıcı arayüzü hasta sorgulama ve rapor kaydetme işlemlerini tanımlar. Tasarım kuralları şunlardır: aynı isteğin iki kez gitmemesi, kısmi başarının normal sayılması ve bir HBYS'nin yavaşlamasının uygulamayı kilitlememesi.

Bugünkü durum. Hazır bir HBYS bağlayıcısı yayımlamıyoruz; yalnızca arayüzü ve sınamaları örnekleyen bir örnek bağlayıcı vardır. Hangi HBYS'nin hedefleneceği, erişim bilgileri ve test ortamı kurumla birlikte planlanır. Bağlayıcıyı beklemeden de entegrasyon mümkündür: HBYS'niz muayeneyi API ile gönderir ve onaylı raporu geri alır.

Hiçbir veri, hekim onayı olmadan HBYS'ye gönderilmez.

Güvenlik Mimarisi

API'nin güvenlik özellikleri, anahtar düzeyinden veri düzeyine.

Anahtar Güvenliği

  • Anahtar yalnızca oluşturulurken bir kez gösterilir; Ssemora yalnızca SHA-256 özetini saklar.
  • Kapsam, isteğe bağlı son kullanma ve izinli IP/CIDR listesi anahtar başına tanımlanır.
  • Dakikalık istek sınırı anahtar başınadır.

Erişim Sınırı

  • Anahtar yalnızca kendi API ile oluşturduğu muayenelere dokunabilir.
  • Rapor uçları varsayılan olarak yalnızca hekim onaylı raporu verir.
  • Yanıtlarda hasta referansı maskelenir.

İzlenebilirlik

  • Rıza beyanı zorunludur ve denetim günlüğüne source=api ile yazılır.
  • API çağrı günlüğü 30 gün tutulur; istek gövdesi ve hasta verisi içermez.

Kurum İzolasyonu

  • Her kurum kendi izole örneğinde ve veritabanında çalışır; kurumlar arasında veri paylaşılmaz.
  • Anahtar tek bir kuruma bağlıdır; başka bir kurumun verisine erişemez.

Veri İşleme

Bir muayenenin verisi hangi adımda nerede işlenir?

AdımNeredeAyrıntı
Ses kaydıKurumun izole örneğindeVarsayılan olarak 7 gün sonra silinir (kurum ayarıyla en çok 30 gün). Transkript ve rapor kalır.
Ses tanımaVarsayılan olarak yerel (faster-whisper)Ham ses yapay zekâ sağlayıcısına gönderilmez. Bulut ses tanıma yalnızca "bulut serbest" politikasında ve açık onayla kullanılabilir.
KimliksizleştirmeHer zaman, politikadan bağımsızAd, T.C. kimlik no, dosya no, telefon, e-posta, adres, kurum adı ve kesin tarihler yer tutucuya çevrilir. Yaş, cinsiyet, klinik içerik ve "3 gündür" gibi göreli süreler korunur. Eşleme tablosu yalnızca tek istek boyunca bellekte tutulur; diske, günlüğe ya da önbelleğe yazılmaz.
Rapor ve öneri üretimiKurumun yapay zekâ politikasına göreBulut serbest ve yalnızca kimliksizleştirilmiş veri politikalarında kimliksiz metin bulut yapay zekâ sağlayıcılarına gönderilebilir. Yalnızca yerel model politikasında tüm aşamalar yerel modelde çalışır.
SonuçKurumun izole örneğindeRapor, transkript ve kanıt aralıkları saklanır; onay, silme ve ayar değişiklikleri denetim günlüğüne yazılır.

Artık risk. Doğrudan tanımlayıcılar kaldırılsa da çok küçük hasta popülasyonlarında (nadir hastalık, az hasta gören birim) dolaylı tanımlanabilirlik riski teorik olarak sıfırlanamaz. Bu nedenle yapay zekâ politikası kurum düzeyinde seçilir; yalnızca yerel model politikasında metin kurum dışına çıkmaz. Bu sayfa teknik bir özettir; sözleşme ve aydınlatma metinlerinin yerine geçmez.

Entegrasyonu Birlikte Planlayalım

Sisteminizi, hedeflediğiniz akışı ve sınırlarınızı anlatın; en uygun yolu birlikte belirleyelim.