Kontrak API aman untuk integrasi AI pada data sensitif bukan sekadar soal menambahkan autentikasi. Tantangan utamanya adalah memastikan data yang dikirim ke layanan AI benar-benar minimum, dapat diaudit, dapat diulang dengan aman saat retry, dan tidak bocor melalui error, log, atau callback. Dalam konteks seperti second opinion MRI, backend harus memperlakukan model AI sebagai komponen terisolasi dengan akses terbatas, bukan sebagai tujuan pengiriman seluruh rekam medis.

Artikel ini membahas pola desain kontrak API yang praktis untuk integrasi AI pada data sensitif: pemisahan metadata dan payload sensitif, penggunaan signed URL berumur pendek, audit trail, consent, versioning kontrak, idempotency key untuk submit analysis, retry yang aman, webhook callback tervalidasi, dan model error yang tidak membocorkan data.

Tujuan desain: batasi akses, batasi data, batasi dampak

Pada sistem analisis MRI atau data medis serupa, kontrak API sebaiknya dirancang dengan tiga tujuan utama:

  • Batasi akses: layanan AI hanya mendapat akses ke data yang diperlukan untuk satu pekerjaan tertentu.
  • Batasi data: kirim metadata minimum, jangan campur seluruh identitas pasien ke payload inferensi.
  • Batasi dampak: jika terjadi retry, timeout, callback palsu, atau kebocoran log, dampaknya tetap kecil dan dapat ditelusuri.

Prinsip ini mendorong arsitektur yang memisahkan sistem klinis internal, penyimpanan objek untuk file citra, dan layanan AI eksternal. Backend Anda menjadi policy enforcement point yang mengontrol apa yang boleh keluar dan apa yang boleh masuk kembali.

Arsitektur referensi untuk second opinion MRI

Arsitektur yang aman biasanya mengikuti alur berikut:

  1. Sistem internal menerima permintaan analisis dari aplikasi klinis.
  2. Backend memverifikasi consent, otorisasi, dan status studi.
  3. Backend membuat job analisis internal dengan ID acak yang tidak mengandung identitas pasien.
  4. File MRI disimpan di object storage internal.
  5. Backend membuat signed URL baca berumur pendek hanya untuk objek yang diperlukan.
  6. Backend mengirim request ke layanan AI berisi referensi job, metadata minimum, dan URL sementara.
  7. Layanan AI memproses data lalu mengirim hasil melalui webhook atau endpoint hasil terpisah.
  8. Backend memverifikasi callback, menyimpan hasil, dan menulis audit trail.

Poin pentingnya: layanan AI tidak perlu mengetahui identitas pasien yang sebenarnya. Ia cukup menerima analysis_id, tipe modalitas, informasi teknis yang relevan, dan akses sementara ke file.

Rancang kontrak API: metadata terpisah dari payload sensitif

Kenapa harus dipisah

Kesalahan umum adalah mengirim semua data ke satu endpoint dalam satu JSON besar, misalnya nama pasien, tanggal lahir, nomor rekam medis, catatan dokter, dan file citra sekaligus. Ini berbahaya karena:

  • permukaan kebocoran lebih besar,
  • log reverse proxy atau APM bisa menangkap payload,
  • retry akan mengulang pengiriman data sensitif dalam jumlah besar,
  • lebih sulit menerapkan kontrol akses granular.

Lebih aman jika kontrak memisahkan:

  • metadata operasional: ID analisis, modalitas, wilayah anatomi, versi model yang diminta, callback URL, consent reference;
  • payload sensitif: file MRI atau artefak medis, diakses melalui signed URL sementara;
  • identitas pasien internal: tetap berada di sistem Anda dan tidak keluar ke vendor AI kecuali benar-benar diperlukan.

Contoh request submit analysis

{
  "contract_version": "2025-06-01",
  "analysis_id": "anl_7f3b1bca4f6e4c6e9f8d2a41",
  "idempotency_key": "0f6d2c2e-7f0e-4f89-9f0d-f1db5c3e7a14",
  "requested_at": "2026-06-28T10:15:00Z",
  "analysis_type": "mri_second_opinion",
  "input": {
    "modality": "MRI",
    "anatomy": "brain",
    "study_ref": "std_2c8b1d1b",
    "object_urls": [
      {
        "url": "https://storage.example.com/object/...",
        "expires_at": "2026-06-28T10:20:00Z",
        "content_type": "application/dicom",
        "sha256": "4f2c...ab9d"
      }
    ]
  },
  "consent": {
    "status": "granted",
    "consent_ref": "consent_9a12d3",
    "scope": ["ai_analysis_second_opinion"]
  },
  "callback": {
    "url": "https://api.hospital.example.com/ai/callbacks/analysis-result",
    "auth": {
      "type": "hmac-sha256",
      "key_id": "cb_key_2026_01"
    }
  }
}

Hal yang perlu diperhatikan dari contoh di atas:

  • analysis_id adalah ID eksternal yang aman dibagikan, bukan nomor rekam medis.
  • contract_version dipasang eksplisit agar perubahan skema bisa dikelola.
  • object_urls berisi URL sementara, bukan file biner yang disisipkan langsung ke request.
  • sha256 membantu verifikasi integritas file yang diambil vendor.
  • consent_ref mereferensikan bukti consent internal tanpa mengekspor seluruh dokumen consent.

Minimisasi data: kirim yang dibutuhkan, bukan yang tersedia

Untuk analisis AI pada data sensitif, minimisasi data harus diterapkan di level kontrak, bukan hanya kebijakan internal. Pertanyaan praktis yang perlu dijawab sebelum menambah field baru:

  • Apakah field ini benar-benar diperlukan oleh model atau proses orkestrasi?
  • Apakah field ini bisa diganti dengan ID acak atau kategori umum?
  • Apakah field ini cukup disimpan internal dan tidak perlu dikirim?
  • Apakah field ini akan ikut tertulis ke log, trace, atau dashboard pihak ketiga?

Contoh minimisasi:

  • Gunakan age_range atau adult/pediatric jika model tidak memerlukan tanggal lahir pasti.
  • Gunakan study_ref acak, bukan accession number asli jika tidak wajib.
  • Jangan kirim nama pasien, alamat, atau nomor identitas kecuali ada alasan klinis dan legal yang jelas.

Jika vendor AI meminta lebih banyak data “untuk debugging”, jadikan itu permintaan eksplisit dan sementara. Jangan ubah kontrak produksi agar selalu mengirim data tambahan hanya demi kenyamanan operasional.

Signed URL berumur pendek untuk payload sensitif

Mengapa tidak mengunggah langsung ke endpoint AI

Mengirim file DICOM besar langsung melalui endpoint submit bisa membuat retry mahal, memperbesar ukuran log transport, dan menyulitkan pembatasan akses. Signed URL memungkinkan backend memberikan akses baca yang sangat sempit:

  • hanya ke objek tertentu,
  • hanya untuk metode tertentu,
  • dengan waktu berlaku pendek,
  • tanpa memberi kredensial storage permanen ke vendor.

Praktik yang disarankan

  • Masa berlaku sesingkat mungkin, misalnya beberapa menit sesuai ukuran file dan SLA pengambilan.
  • Satu URL per objek atau per paket yang memang dibutuhkan.
  • Hindari URL yang bisa dipakai ulang untuk daftar objek lain.
  • Sertakan hash file atau ETag yang bisa diverifikasi.
  • Jika memungkinkan, batasi IP atau jaringan sumber, tetapi jangan mengandalkan ini sebagai satu-satunya kontrol.

Jika file sangat besar atau banyak, pertimbangkan paket objek yang dipersiapkan khusus untuk satu job. Namun jangan membuat satu URL arsip besar jika vendor sebenarnya hanya memerlukan subset data.

Consent dan otorisasi bukan detail administratif

Pada data sensitif, consent harus menjadi bagian eksplisit dari kontrak, walau isi lengkap dokumen consent tidak perlu dikirim. Backend sebaiknya memeriksa:

  • apakah consent tersedia,
  • apakah scope consent mencakup analisis AI ini,
  • apakah consent masih berlaku,
  • apakah ada dasar legal lain jika consent bukan mekanisme yang digunakan.

Secara kontrak, Anda bisa mengirim hanya referensi consent dan statusnya. Tujuannya bukan agar vendor menafsirkan legalitas, tetapi agar setiap request punya bukti bahwa validasi telah dilakukan oleh sistem pengendali data.

{
  "consent": {
    "status": "granted",
    "consent_ref": "consent_9a12d3",
    "scope": ["ai_analysis_second_opinion"],
    "validated_at": "2026-06-28T10:14:50Z"
  }
}

Kesalahan umum adalah memproses job lebih dulu lalu memeriksa consent belakangan. Untuk data sensitif, urutannya harus dibalik: validasi legal dan akses dulu, baru keluarkan data.

Versioning kontrak API

Integrasi AI cenderung berubah: format hasil, metadata tambahan, parameter model, atau mekanisme callback. Karena itu, versioning kontrak perlu eksplisit dan dapat diuji.

Pola yang aman

  • Tambahkan field contract_version pada body request dan response.
  • Dokumentasikan field wajib, opsional, dan field yang akan dihentikan.
  • Jaga kompatibilitas mundur untuk perubahan non-breaking.
  • Untuk perubahan breaking, terbitkan versi kontrak baru daripada diam-diam mengubah makna field lama.

Contoh perubahan breaking:

  • mengubah arti status completed,
  • mengganti struktur hasil dari satu objek menjadi array,
  • mengubah algoritme verifikasi callback tanpa transisi.

Kontrak yang berversi juga mempermudah audit. Saat ada insiden, Anda bisa menjawab job mana yang dibuat dengan skema tertentu dan bagaimana parser harus menanganinya.

Idempotency key untuk submit analysis dan retry aman

Masalah yang ingin dihindari

Submit analysis sering melewati jaringan, queue, dan sistem pihak ketiga. Timeout di sisi klien tidak selalu berarti vendor tidak menerima request. Tanpa idempotency, satu retry bisa membuat dua analisis terpisah untuk studi yang sama.

Cara kerja yang disarankan

Klien backend mengirim idempotency_key unik untuk satu niat bisnis, misalnya “submit analisis untuk studi ini dengan parameter ini”. Server vendor menyimpan hasil pertama untuk key tersebut selama periode tertentu, lalu mengembalikan respons yang konsisten jika request yang sama dikirim lagi.

{
  "contract_version": "2025-06-01",
  "analysis_id": "anl_7f3b1bca4f6e4c6e9f8d2a41",
  "idempotency_key": "0f6d2c2e-7f0e-4f89-9f0d-f1db5c3e7a14",
  "analysis_type": "mri_second_opinion"
}

Di sisi Anda, buat tabel atau storage dedikasi untuk mencatat:

  • idempotency key,
  • hash request yang relevan,
  • status submit,
  • response vendor pertama yang diterima,
  • waktu kedaluwarsa key.

Aturan penting

  • Jangan gunakan timestamp semata sebagai idempotency key.
  • Jangan daur ulang key untuk request dengan payload bisnis berbeda.
  • Jika payload berubah, gunakan key baru.
  • Jika vendor tidak mendukung idempotency secara native, implementasikan deduplikasi di sisi Anda sebelum mengirim ke vendor.

Retry yang aman

Retry aman berarti hanya mengulang operasi yang diketahui bisa diulang tanpa efek samping ganda. Praktiknya:

  • retry otomatis untuk timeout, 502, 503, 504, atau gangguan jaringan;
  • jangan retry buta untuk 4xx tanpa analisis sebab;
  • gunakan exponential backoff dengan jitter;
  • simpan korelasi antara retry dan job asli untuk audit.

Jika submit berhasil tetapi respons hilang, idempotency membuat permintaan ulang tetap aman. Tanpa itu, Anda berada dalam kondisi ambigu yang sulit dipulihkan.

Sync API vs async job: kapan memilih yang mana

Gunakan sync API jika

  • operasi benar-benar singkat dan deterministik,
  • payload kecil,
  • hasil dibutuhkan segera untuk alur UI interaktif,
  • tidak melibatkan file besar atau pemrosesan lama.

Gunakan async job jika

  • analisis memerlukan pengambilan file dari object storage,
  • waktu proses tidak dapat diprediksi singkat,
  • perlu retry terkontrol,
  • perlu callback atau polling status,
  • hasil akan melalui pemeriksaan tambahan sebelum dipakai.

Untuk second opinion MRI, async job hampir selalu lebih tepat. File besar, inference bisa memakan waktu, dan backend membutuhkan jejak audit yang lengkap. Pola umumnya:

  1. POST /analyses untuk membuat job,
  2. respons 202 Accepted dengan status awal,
  3. vendor memproses dan memanggil webhook hasil,
  4. klien internal dapat polling GET /analyses/{id} jika perlu.
{
  "analysis_id": "anl_7f3b1bca4f6e4c6e9f8d2a41",
  "status": "queued",
  "contract_version": "2025-06-01",
  "submitted_at": "2026-06-28T10:15:02Z"
}

Webhook callback yang tervalidasi

Jangan percaya callback hanya karena datang ke endpoint Anda

Webhook hasil adalah titik masuk data dari luar. Jika tidak diverifikasi, siapa pun yang tahu URL callback bisa mengirim status palsu atau hasil manipulatif. Validasi minimum yang disarankan:

  • verifikasi tanda tangan HMAC atau skema signature lain yang disepakati,
  • cek timestamp untuk mencegah replay lama,
  • cek analysis_id dan kecocokan vendor/job,
  • terapkan toleransi waktu yang wajar,
  • simpan event ID untuk mencegah pemrosesan ganda.

Contoh payload webhook

{
  "event_id": "evt_f3ab91f0",
  "event_type": "analysis.completed",
  "sent_at": "2026-06-28T10:22:41Z",
  "contract_version": "2025-06-01",
  "analysis_id": "anl_7f3b1bca4f6e4c6e9f8d2a41",
  "result": {
    "summary": "No acute intracranial abnormality detected.",
    "findings": [
      {
        "code": "no_acute_abnormality",
        "confidence": 0.94
      }
    ]
  }
}

Contoh verifikasi konsep

signature = HMAC_SHA256(secret, timestamp + "." + raw_request_body)
compare_constant_time(signature, header_signature)

Gunakan raw request body saat memverifikasi signature. Kesalahan umum adalah memverifikasi JSON yang sudah di-parse lalu di-serialize ulang; urutan field atau whitespace bisa berubah dan membuat verifikasi gagal.

Apa yang harus dilakukan setelah callback diterima

  • validasi signature dan timestamp,
  • cek apakah event_id sudah pernah diproses,
  • simpan payload asli terenkripsi atau di storage audit yang sesuai kebijakan,
  • ubah status job secara atomik,
  • hasilkan event internal untuk pipeline lanjutan.

Jika callback gagal diproses sementara, kembalikan status yang membuat vendor boleh retry sesuai kontrak. Namun pastikan endpoint Anda idempoten terhadap event yang sama.

Model error yang tidak membocorkan data

Error response sering diabaikan, padahal justru sering menjadi jalur kebocoran data. Hindari mengembalikan:

  • nama objek storage lengkap,
  • signed URL utuh,
  • potongan isi file,
  • identitas pasien,
  • stack trace internal.

Contoh error response yang aman

{
  "error": {
    "code": "INVALID_INPUT",
    "message": "Request tidak valid untuk kontrak yang digunakan.",
    "details": [
      {
        "field": "input.object_urls[0].expires_at",
        "issue": "expired_or_too_soon"
      }
    ],
    "request_id": "req_4a91c0e2d7"
  }
}

Response di atas cukup untuk debugging klien tanpa membocorkan data sensitif. Detail teknis mendalam sebaiknya ditulis ke log internal dengan redaksi yang aman.

Praktik logging yang aman

  • masking signed URL dan token otorisasi,
  • jangan log payload medis mentah secara default,
  • simpan request_id, analysis_id, dan kode error untuk korelasi,
  • gunakan level log yang berbeda untuk operasional dan forensik.

Audit trail: siapa mengirim apa, kapan, dan atas dasar apa

Audit trail yang baik membantu investigasi insiden, kepatuhan, dan debugging lintas sistem. Untuk setiap analisis, catat minimal:

  • siapa atau sistem mana yang memulai request,
  • waktu submit dan waktu callback,
  • versi kontrak,
  • vendor/model target jika relevan,
  • artefak data apa yang diizinkan keluar,
  • consent reference atau dasar legal,
  • idempotency key,
  • hasil validasi callback,
  • perubahan status job.

Audit trail tidak harus menyimpan seluruh payload di database transaksi utama. Sering kali lebih baik menyimpan ringkasan terstruktur di database aplikasi, dan payload lengkap terenkripsi di storage audit terpisah dengan retensi dan akses yang lebih ketat.

Contoh desain endpoint internal yang konsisten

Submit job

POST /v1/analyses
{
  "patient_ref": "pt_8d1a2c",
  "study_ref": "std_2c8b1d1b",
  "analysis_type": "mri_second_opinion"
}

Respons internal:

{
  "analysis_id": "anl_7f3b1bca4f6e4c6e9f8d2a41",
  "status": "preparing",
  "request_id": "req_4a91c0e2d7"
}

Di belakang layar, backend internal melakukan validasi consent, menyiapkan objek, membuat signed URL, lalu melakukan submit ke vendor.

Cek status job

GET /v1/analyses/anl_7f3b1bca4f6e4c6e9f8d2a41
{
  "analysis_id": "anl_7f3b1bca4f6e4c6e9f8d2a41",
  "status": "completed",
  "result_ref": "res_29ac4f",
  "updated_at": "2026-06-28T10:22:42Z"
}

Webhook hasil dari vendor

POST /ai/callbacks/analysis-result

Endpoint ini hanya menerima event dari vendor, diverifikasi tandatangannya, lalu memutakhirkan status job internal.

Checklist desain kontrak API aman

  • Identitas: gunakan ID acak eksternal, bukan identifier pasien asli.
  • Minimisasi data: kirim hanya field yang dibutuhkan AI.
  • Pemisahan data: metadata di JSON, file sensitif lewat signed URL sementara.
  • Consent: validasi sebelum submit, kirim referensi consent seperlunya.
  • Versioning: sertakan contract_version pada request dan response.
  • Idempotency: wajib untuk endpoint submit.
  • Retry: gunakan backoff dan retry hanya untuk kondisi yang aman.
  • Webhook security: verifikasi signature, timestamp, dan replay protection.
  • Error model: jangan bocorkan URL, token, payload medis, atau stack trace.
  • Audit trail: simpan request ID, analysis ID, status transisi, consent ref, dan hasil verifikasi callback.
  • Observability: korelasikan log dengan request_id tanpa menyimpan data sensitif mentah.
  • Retention: tetapkan kebijakan retensi hasil AI dan payload audit.

Anti-pattern umum

Mengirim seluruh rekam medis ke model

Ini biasanya terjadi karena “lebih mudah”. Dampaknya adalah perluasan data yang tidak terkendali dan sulit diaudit. Kirim hanya artefak yang diperlukan untuk analisis tertentu.

Menggunakan signed URL yang terlalu lama

URL berlaku berjam-jam atau berhari-hari memperbesar jendela risiko. Jika vendor butuh akses ulang, buat URL baru melalui alur terkontrol.

Callback tanpa verifikasi signature

Ini membuka peluang injeksi hasil palsu atau perubahan status job secara tidak sah.

Retry submit tanpa idempotency

Akibatnya job ganda, billing ganda, atau hasil tidak konsisten.

Mencampur detail internal ke error publik

Misalnya mengembalikan path object storage, SQL error, atau stack trace. Ini membantu penyerang dan memperbesar risiko kebocoran.

Menjadikan vendor AI sebagai source of truth status klinis

Hasil AI harus diperlakukan sebagai artefak terintegrasi yang divalidasi dan disimpan oleh sistem Anda, bukan satu-satunya sumber status yang dipercaya.

Tips implementasi dan debugging

Uji kontrak dengan payload yang sengaja rusak

Buat pengujian untuk URL kedaluwarsa, hash file salah, callback dengan signature salah, replay event, dan retry submit. Sistem yang aman perlu gagal dengan jelas tanpa membocorkan data.

Gunakan request ID di semua hop

Sertakan request_id dan analysis_id di log backend, worker, gateway, dan audit event. Ini mempercepat penelusuran saat ada timeout atau status tidak sinkron.

Pastikan parser tahan terhadap evolusi skema

Untuk callback hasil, parser sebaiknya toleran terhadap field tambahan yang tidak dikenal, selama kontrak mengizinkannya. Jangan membuat integrasi rapuh terhadap penambahan metadata non-breaking.

Pisahkan status transport dan status bisnis

HTTP 200 dari vendor hanya berarti request diterima endpoint, bukan analisis selesai. Simpan state machine yang jelas, misalnya preparing, submitted, processing, completed, failed, expired.

Penutup

Merancang kontrak API aman untuk integrasi AI pada data sensitif berarti memperlakukan data, alur retry, callback, dan audit sebagai bagian inti dari desain, bukan tambahan di akhir proyek. Dalam kasus seperti second opinion MRI, pola yang paling aman biasanya adalah async job dengan metadata minimal, payload melalui signed URL berumur pendek, consent yang tervalidasi, submit idempoten, callback bertanda tangan, dan error model yang steril dari data sensitif.

Jika Anda harus memilih satu prioritas awal, mulailah dari tiga hal ini: minimisasi data, idempotency, dan verifikasi callback. Tiga hal tersebut paling sering menentukan apakah integrasi AI Anda dapat dioperasikan dengan aman saat sistem nyata mulai menghadapi timeout, retry, dan insiden operasional.