Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/entegrasyon/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ InsurUp ile sistemlerinizi entegre ederken kullanabileceğiniz başlıca rehberl
- [InsurUp ile Giriş (OAuth 2.0 / OIDC) Entegrasyon Rehberi](/entegrasyon/insurup-ile-giris-oauth-entegrasyonu): Kendi uygulamanıza "InsurUp ile Giriş" eklemek için OAuth istemcisi oluşturma, Authorization Code + PKCE akışı ve token kullanımı.
- [InsurUp ile Giriş: Uygulama Desenleri ve Sorun Giderme](/entegrasyon/insurup-ile-giris-uygulama-desenleri-ve-sorun-giderme): SPA ve sunucu (BFF) desenleri, örnek kurulum ve sık karşılaşılan sorunların (scope/`core-api`, proxy yönlendirme, çıkış, oturum geri yükleme) çözümleri.
- [Müşteri Belgesi PDF Entegrasyon Rehberi](/entegrasyon/musteri-belgesi-pdf): Teklif ürünlerinden müşteriye sunum için PDF belgesi oluşturma ve indirme.
- [MERNIS ve TRAMER Sorgusu (B2B API)](/entegrasyon/mernis-tramer-sorgusu): Servis hesabı ile access token alma ve bu token'la MERNIS (kimlik) ve TRAMER (araç/poliçe) sorgularını yapma rehberi.

## GraphQL CRM Liste Entegrasyonu

Expand Down
350 changes: 350 additions & 0 deletions docs/entegrasyon/mernis-tramer-sorgusu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@
---
title: "MERNIS ve TRAMER Sorgusu (B2B API)"
sidebar_position: 11
slug: /entegrasyon/mernis-tramer-sorgusu
---

# InsurUp B2B API — Token Alma, MERNIS ve TRAMER Sorgusu

Bu doküman, bir B2B entegrasyonunun InsurUp API üzerinden **erişim token'ı (access token)** almasını ve bu token ile **MERNIS** (kimlik sorgulama) ve **TRAMER** (araç/poliçe sorgulama) isteklerini nasıl yapacağını anlatır.

---

## Özet

| Konu | Cevap |
|---|---|
| Token nasıl alınır? | **OAuth 2.0 `client_credentials`** akışı ile (servis hesabı) |
| Servis hesabı mı, OAuth kullanıcı akışı mı? | **Servis hesabı (client_credentials)** — makineden-makineye (M2M) entegrasyon için |
| MERNIS endpoint | `POST /customers/external-lookup` |
| TRAMER endpoint | `POST /customers/{CustomerId}/vehicles/external-lookup` |
| Gerekli OAuth scope | `core-api` |

> **Servis hesabı nedir, nasıl oluşturulur?**
> Servis hesabı; bir insan kullanıcı yerine yazılımın/otomasyonun API'ye erişmesini sağlayan, kullanıcı oturumu gerektirmeyen bir hesap türüdür. Bu doküman, elinizde bir servis hesabı (`client_id` + `client_secret`) olduğunu varsayar. Hesabı Agent Panel üzerinden nasıl oluşturacağınız, secret'ı nasıl saklayacağınız ve yönetim adımları için: [Servis Hesabı Oluşturma ve Kullanım Kılavuzu](/entegrasyon/servis-hesabi-olusturma).

---

## Base URL'ler

| Ortam | Servis | URL |
|---|---|---|
| Production | Kimlik doğrulama (AuthServer) | `https://auth.insurup.com` |
| Production | REST API (WebApi) | `https://api.insurup.com` |

> **Not:** REST istekleri hem `https://api.insurup.com/...` hem de `https://api.insurup.com/api/...` biçiminde çalışır; `/api/*` yolları otomatik olarak köke yönlendirilir. Bu dokümanda `/api/` öneki kullanılmıştır.

---

## Adım 1 — Servis hesabı ile access token alma

Bu adım için bir servis hesabına ait `client_id` (`sa-...` biçiminde) ve `client_secret` gerekir. Henüz oluşturmadıysanız, Agent Panel'den oluşturma adımları için [Servis Hesabı Oluşturma ve Kullanım Kılavuzu](/entegrasyon/servis-hesabi-olusturma)'na bakın.

Elinizdeki `client_id` ve `client_secret` ile token endpoint'ine `client_credentials` isteği gönderin.

```
POST https://auth.insurup.com/connect/token
Content-Type: application/x-www-form-urlencoded
```

Gövde (form-urlencoded):

```
grant_type=client_credentials
client_id=sa-019f8dfa88c67bbb9bd500ae8c90f40d
client_secret={size verilen secret}
scope=core-api
```

cURL örneği:

```bash
curl -X POST "https://auth.insurup.com/connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=sa-019f8dfa88c67bbb9bd500ae8c90f40d" \
-d "client_secret={SECRET}" \
-d "scope=core-api"
```

Örnek yanıt:

```json
{
"access_token": "eyJhbGciOiJ...",
"token_type": "Bearer",
"expires_in": 1800,
"scope": "core-api"
}
```

**Önemli notlar:**

- Dönen `access_token`, sonraki tüm isteklerde `Authorization: Bearer {access_token}` başlığıyla kullanılır.
- Access token süresi **30 dakikadır** (`expires_in: 1800`). `client_credentials` akışında **refresh token yoktur**; token süresi dolduğunda bu adımı tekrarlayarak yeni token alın.
- `client_secret` yalnızca servis hesabı oluşturulurken **bir kez** gösterilir. Kaybederseniz sıfırlanması (rotate) gerekir.
- Erişim yetkisi (hangi verilere dokunabileceğiniz) servis hesabınıza tanımlı **rol/izinlerle** belirlenir; token isteğindeki `scope` her zaman `core-api`'dir.

---

## Adım 2 — MERNIS sorgusu (kimlik doğrulama / ön dolum)

MERNIS sorgusu, TCKN (veya VKN/YKN) üzerinden kişi/kurum bilgilerini getirir. Bu endpoint bir müşteri **oluşturmaz**; sorgu sonucunu döner, isterseniz müşteri oluştururken kullanırsınız.

```
POST https://api.insurup.com/api/customers/external-lookup
Authorization: Bearer {access_token}
Content-Type: application/json
```

İstek gövdesi, müşteri tipine göre `$type` alanı ile ayrışır: `individual` (bireysel), `company` (kurumsal), `foreign` (yabancı).

### Bireysel (T.C. vatandaşı)

| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| `$type` | string | Evet | `"individual"` olmalı |
| `identityNumber` | number | Evet | 11 haneli TCKN |
| `birthDate` | string (`YYYY-MM-DD`) | Hayır | Verilmezse sistem doğum tarihini önce sorgular |

```json
{
"$type": "individual",
"identityNumber": 11111111111,
"birthDate": "1985-05-12"
}
```

### Kurumsal

| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| `$type` | string | Evet | `"company"` olmalı |
| `taxNumber` | string | Evet | Vergi No (VKN) |

```json
{
"$type": "company",
"taxNumber": "1234567890"
}
```

### Yabancı

| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| `$type` | string | Evet | `"foreign"` olmalı |
| `identityNumber` | string | Evet | Yabancı kimlik no / pasaport |
| `birthDate` | string (`YYYY-MM-DD`) | Evet | Zorunlu |

```json
{
"$type": "foreign",
"identityNumber": "99123456789",
"birthDate": "1990-01-15"
}
```

### Örnek yanıt (bireysel)

```json
{
"$type": "individual",
"fullName": "Ada Lovelace",
"gender": "FEMALE",
"email": "ada@example.com",
"phoneNumber": { "number": "5321234567", "countryCode": 90 },
"maritalStatus": "MARRIED",
"birthDate": "1985-05-12",
"city": { "value": "34", "text": "İstanbul" },
"district": { "value": "1234", "text": "Kadıköy" }
}
```

cURL örneği:

```bash
curl -X POST "https://api.insurup.com/api/customers/external-lookup" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{"$type":"individual","identityNumber":11111111111,"birthDate":"1985-05-12"}'
```

---

## Adım 3 — Müşteriyi oluşturma / bulma (CustomerId edinme)

TRAMER sorgusu bir `CustomerId` gerektirir. Bu yüzden **önce müşteri sistemde olmalı**; yoksa oluşturursunuz, varsa bulursunuz. Akış şöyledir: müşteriyi oluşturur (`POST /customers`) veya mevcut kaydı bulur (`GET /customers/{TCKN|VKN}`), dönen `id` (GUID) değerini alırsınız; ardından bu `id`'yi TRAMER isteğinin URL'sinde `{CustomerId}` olarak kullanırsınız. Yani `CustomerId`, müşteri kaydı ile araç/TRAMER sorgusunu birbirine bağlayan referanstır.

### 3a — Müşteri oluşturma

```
POST https://api.insurup.com/api/customers
Authorization: Bearer {access_token}
Content-Type: application/json
```

İstek gövdesi, MERNIS'te olduğu gibi `$type` ile ayrışır (`individual` / `company` / `foreign`).

Bireysel:

```json
{
"$type": "individual",
"identityNumber": "11111111111",
"birthDate": "1985-05-12",
"fullName": "Ada Lovelace"
}
```

Kurumsal:

```json
{
"$type": "company",
"title": "ÖRNEK LTD. ŞTİ.",
"taxNumber": "1234567890"
}
```

> **İpucu — `fillMissingFields`:** İstek gövdesine `"fillMissingFields": true` eklerseniz, sistem müşteri oluştururken eksik alanları MERNIS/SBM'den otomatik doldurur. Böylece Adım 2'yi ayrıca çağırmadan tek istekte hem oluşturma hem ön dolum yapabilirsiniz.

**Yanıt — CustomerId burada döner (HTTP 201):**

```json
{
"id": "019f1234-5678-7abc-def0-123456789abc"
}
```

Bu `id`, bir sonraki adımda TRAMER isteğinin URL'sinde `{CustomerId}` olarak kullanılır.

> **Not — Aynı TCKN/VKN zaten varsa:** `POST /customers` mevcut müşteriyi döndürmez; **duplicate hatası** verir. Müşterinin zaten var olma ihtimali varsa önce 3b ile bulun, yoksa oluşturun.

cURL örneği:

```bash
curl -X POST "https://api.insurup.com/api/customers" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{"$type":"individual","identityNumber":"11111111111","birthDate":"1985-05-12"}'
```

### 3b — Mevcut müşteriyi bulma

Müşteri zaten kayıtlıysa, GUID / TCKN / VKN ile tekil olarak çekip `id`'yi alabilirsiniz:

```
GET https://api.insurup.com/api/customers/{CustomerId|TCKN|VKN}
Authorization: Bearer {access_token}
```

`{CustomerId}` yerine müşterinin GUID'i, **11 haneli TCKN'si** veya **VKN'si** verilebilir.

---

## Adım 4 — TRAMER sorgusu (araç / poliçe sorgusu)

Elinizde Adım 3'ten gelen `CustomerId` ile artık TRAMER sorgusu yapabilirsiniz. TRAMER; plaka (ve varsa ruhsat seri no) üzerinden aracın model, poliçe ve TRAMER bilgilerini getirir.

> **Önemli — Müşteri kaydı zorunludur:**
> TRAMER sorgusu, kimlik bilgilerini (bireysel için TCKN + doğum tarihi, kurumsal için VKN) **request gövdesinden değil**, URL'deki `{CustomerId}` ile bağlı **sistemdeki müşteri kaydından** okur. Bu nedenle sorgudan önce müşterinin sistemde kayıtlı olması gerekir (bkz. Adım 3). Bireysel/yabancı müşteride **doğum tarihi**, kurumsalda **VKN** kayıtlı değilse sorgu hata verir.

```
POST https://api.insurup.com/api/customers/{CustomerId}/vehicles/external-lookup
Authorization: Bearer {access_token}
Content-Type: application/json
```

İstek gövdesi:

| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| `plate` | object | Evet | `{ "city": 1–81, "code": "ABC123" }` |
| `plate.city` | number | Evet | İl plaka kodu (1–81) |
| `plate.code` | string | Evet | Plakanın harf+rakam kısmı |
| `documentSerial` | object | Hayır | Verilmezse sistem ruhsat seri no'yu sorgular |
| `documentSerial.code` | string | (verilirse) | 2 harf (örn. `"AB"`) |
| `documentSerial.number` | string | (verilirse) | 6 hane (örn. `"123456"`) |

```json
{
"plate": {
"city": 34,
"code": "ABC123"
},
"documentSerial": {
"code": "AB",
"number": "123456"
}
}
```

### Örnek yanıt

```json
{
"registrationDate": "2020-03-15",
"firstRegistrationDate": "2020-03-20",
"plate": { "city": 34, "code": "ABC123" },
"documentSerial": { "code": "AB", "number": "123456" },
"model": {
"year": 2020,
"brand": { "value": "100", "text": "TOYOTA" },
"type": { "value": "200", "text": "COROLLA 1.6" }
},
"chassis": "CHASSIS123",
"chassisIsMasked": false,
"engine": "ENGINE123",
"engineIsMasked": false,
"fuelType": "GASOLINE",
"price": 150000,
"currency": "TRY",
"kaskoOldPolicy": {
"insuranceCompanyPolicyNumber": "12345678",
"insuranceCompanyRenewalNumber": 0,
"insuranceCompanyReference": "001",
"agentNumber": "AG123",
"endDate": "2026-03-15"
},
"trafikOldPolicy": null,
"utilizationStyle": "PRIVATE",
"seatNumber": 5
}
```

**Yanıt hakkında notlar:**

- `chassisIsMasked` / `engineIsMasked` `true` ise ilgili değer maskelenmiştir (örn. `"W***8"`); bu maskeli değeri kaydetmeyin.
- `model` yerine `partialModel` dönebilir (model yılı maskeliyse yalnızca marka/tip gelir).

cURL örneği:

```bash
curl -X POST "https://api.insurup.com/api/customers/019f1234-5678-7abc-def0-123456789abc/vehicles/external-lookup" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{"plate":{"city":34,"code":"ABC123"},"documentSerial":{"code":"AB","number":"123456"}}'
```

---

## Önerilen uçtan uca akış

```
1) POST /connect/token → access token al (scope: core-api)
2) POST /api/customers/external-lookup → (opsiyonel) MERNIS ile kimlik bilgisi ön dolum
3) GET /api/customers/{TCKN|VKN} → müşteri var mı? Varsa CustomerId'yi al
4) (müşteri yoksa) POST /api/customers → müşteri oluştur, yanıttaki { "id": ... } = CustomerId
5) POST /api/customers/{CustomerId}/vehicles/external-lookup → TRAMER (plaka +ruhsat seri no) sorgusu
```

---

## Yetkilendirme ve hata durumları

| Durum | Açıklama |
|---|---|
| `401 Unauthorized` | Token yok, geçersiz veya süresi dolmuş. Adım 1'i tekrarlayın. |
| `403 Forbidden` | Servis hesabınızın bu işlem için rol/izni yok. |
| Kimlik bilgisi eksik | TRAMER için müşterinin doğum tarihi (bireysel/yabancı) veya VKN (kurumsal) kaydı eksikse sorgu hata verir; müşteri kaydını tamamlayın. |
Loading