Ana içeriğe geç

GraphQL Entegrasyon Rehberi

Bu doküman, InsurUp Agent Panel’deki aşağıdaki liste ekranlarına karşılık gelen GraphQL API’sini harici CRM sistemlerine entegre etmek için hazırlanmıştır:

Agent Panel ekranıURL
Müşterilerhttps://app.insurup.com/customers
Vakalarhttps://app.insurup.com/cases
Tekliflerhttps://app.insurup.com/proposals
Poliçelerhttps://app.insurup.com/policies

İlgili dokümanlar:

  • HTML sürüm (tarayıcı): graphql-crm-list-integration.html
  • Kimlik doğrulama ve OAuth: login-with-insurup-integration.md
  • Güvenlik ve izinler: standards/12-security-and-secrets.md

1. Genel bakış

InsurUp’da liste ve arama işlemleri REST ile değil GraphQL üzerinden yapılır. Agent Panel (app.insurup.com) bu sorguları doğrudan Web API’ye gönderir.

KaynakURLAçıklama
GraphQL endpointPOST https://api.insurup.com/graphqlListe, filtre, arama, sayfalama
GraphQL şema (SDL)GET https://api.insurup.com/graphql/schemaAnonim erişilebilir şema dosyası
Tek kayıt detayıRESTÖrn. GET /customers/{id}, GET /proposals/{id}
POST https://api.insurup.com/graphql
Authorization: Bearer {access_token}
Content-Type: application/json
{
"query": "...",
"variables": { }
}

2. Kimlik doğrulama ve yetkilendirme

2.1 Token

  • Her istekte giriş yapmış agent kullanıcısının access_token değeri kullanılmalıdır.
  • Tek bir servis hesabı token’ı ile tüm personel adına istek atılmamalıdır (audit ve yetki kaybı).
  • Detay: login-with-insurup-integration.md

2.2 OAuth scope (token seviyesi)

Harici OAuth client için granular scope’lar:

Ekran / veriOkuma scope’u
Müşterilercustomer:read
Tekliflerproposal:read
Poliçelerpolicy:read
Vakalarcase:read
Profilme:read

Tam CRM senkronu için InsurUp’un Agent Panel ile aynı core-api scope’unu client’a tanımlaması gerekebilir.

Örnek granular scope listesi (authorize / token):

openid profile email offline_access customer:read proposal:read policy:read case:read me:read

Örnek tam erişim:

openid profile email offline_access core-api

Kaynak: InsurUpApiScopes (src/Packages/InsurUp.Api.Contracts/src/InsurUpApiScopes.cs)

2.3 Agent rol izinleri (veri seviyesi)

GraphQL yalnızca kimlik doğrulama yapmaz; MongoDB sorguları agent rol izinleri ve permission scope ile filtrelenir:

PermissionAçıklama
customers:readMüşteri listesi
cases:readVaka listesi
proposals:readTeklif listesi
policies:readPoliçe listesi

Her izin şu kapsamlardan birine bağlanabilir:

  • All — acentedeki tüm kayıtlar
  • Own — yalnızca kullanıcının oluşturduğu / temsil ettiği kayıtlar
  • Branch — şube kapsamındaki kayıtlar

Agent owner ise tüm veriye erişir.

Kaynak: AgentUserPermissions (src/Common/Permissions/.../AgentUserPermissions.cs)

2.4 PII maskeleme

Kimlik numarası, e-posta, telefon, plaka, poliçe numarası gibi alanlar acente mask ayarına göre kısmen gizlenebilir (AgentBasedMask, MaskedRedact). Entegrasyonda ham değer bekleniyorsa acente mask konfigürasyonunu kontrol edin.

2.5 Hata kodları

HTTPAnlam
401Token geçersiz veya süresi dolmuş
403Scope veya rol izni yetersiz
404Kayıt yok veya kullanıcının scope’u dışında (filtrelenmiş)

3. Sorgu adları ve kod eşlemesi

HotChocolate, C# metot adlarını camelCase GraphQL alanına çevirir. Agent Panel yeni (*New) sorguları kullanır.

Agent Panel GraphQLResourceC# metotGraphQL root fieldModel tipi
customersNewGetCustomersNewcustomersNewQueryCustomerModel
casesNewGetCasesNewcasesNewQueryCaseModel
proposalsNewGetProposalsNewproposalsNewQueryProposalsResult
policiesNewGetPoliciesNewpoliciesNewQueryPoliciesResult
policiesExpandedGetPoliciesExpandedpoliciesExpandedQueryPoliciesExpandedResult

Eski sorgular (offset paging): customers, cases, proposals, policies — yeni entegrasyonlarda kullanılmamalı.

Kaynak dosyalar:

  • CustomerQuery.cs
  • CaseQuery.cs
  • ProposalQuery.cs
  • PolicyQuery.cs

4. Ortak sorgu parametreleri

Tüm *New sorguları cursor pagination ve aynı filtre/arama sözlüğünü destekler:

ParametreAçıklama
firstSayfa boyutu
afterSonraki sayfa cursor’ı (pageInfo.endCursor)
filterAlan bazlı filtre (eq, contains, gte, in, …)
searchAtlas Search (autocomplete, or, …)
orderSıralama (ör. createdAt: DESC, searchScore: DESC)

Dönüş yapısı:

{
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
# seçilen alanlar
}
}

Filter input tipleri (şemada):

  • QueryCustomerModelFilterInput
  • QueryCaseModelFilterInput
  • QueryProposalsResultFilterInput
  • QueryPoliciesResultFilterInput

Şemayı indirmek için:

curl -s https://api.insurup.com/graphql/schema -o insurup-schema.graphql

5. Müşteriler (customersNew)

5.1 Yetki

KatmanGereksinim
OAuthcustomer:read veya core-api
Rolcustomers:read

5.2 Kullanılabilir alanlar

AlanTipNot
idUUID
nameStringArama / sıralama
typeCustomerType
identityNumberStringBireysel / yabancı
taxNumberStringKurumsal
primaryEmailString
primaryPhoneNumberString
primaryPhoneNumberCountryCodeInt
cityText, cityValueString
districtText, districtValueString
createdAtDateTimeVarsayılan sıralama
creationChannelChannel
birthDateDate
gender, educationStatus, nationality, maritalStatus, jobEnum
passportNumberString
agentBranchIdString
agentBranchObjectid, name, parentId, parentName
consentsListconsentType, isActive
emailCount, phoneCountInt
vehicleCount, propertyCountIntResolver (ek sorgu)
proposalCount, policyCount, caseCountIntResolver
searchScoreFloatYalnızca search aktifken

5.3 Örnek sorgu — liste

query CustomersList(
$first: Int!
$after: String
$filter: QueryCustomerModelFilterInput
$search: QueryCustomerModelSearchInput
$order: [QueryCustomerModelSortInput!]
) {
customersNew(
first: $first
after: $after
filter: $filter
search: $search
order: $order
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
id
name
type
identityNumber
taxNumber
primaryEmail
primaryPhoneNumber
primaryPhoneNumberCountryCode
cityText
districtText
createdAt
creationChannel
birthDate
gender
educationStatus
nationality
maritalStatus
job
passportNumber
agentBranchId
agentBranch {
id
name
parentId
parentName
}
consents {
consentType
isActive
}
emailCount
phoneCount
vehicleCount
propertyCount
proposalCount
policyCount
caseCount
searchScore
}
}
}

5.4 Örnek variables — filtre

{
"first": 50,
"filter": {
"name": { "contains": "Mehmet" }
},
"order": [{ "createdAt": "DESC" }]
}

5.5 Örnek variables — autocomplete arama

Agent Panel ile uyumlu arama:

{
"first": 20,
"search": {
"or": [
{ "name": { "autocomplete": { "value": "ahmet", "score": { "boost": 3.0 } } } },
{ "identityNumber": { "autocomplete": { "value": "ahmet" } } },
{ "taxNumber": { "autocomplete": { "value": "ahmet" } } },
{ "primaryEmail": { "autocomplete": { "value": "ahmet" } } },
{ "primaryPhoneNumber": { "autocomplete": { "value": "ahmet" } } }
]
},
"order": [{ "searchScore": "DESC" }]
}

5.6 Tek kayıt — REST

GET https://api.insurup.com/customers/{customerId}
Authorization: Bearer {access_token}

Scope: customer:read


6. Vakalar (casesNew)

6.1 Yetki

KatmanGereksinim
OAuthcase:read veya core-api
Rolcases:read

6.2 Kullanılabilir alanlar (özet)

GrupAlanlar
Vakaid, ref, type, status, mainState, subState, productBranch, channel, createdAt
Alt tiplercancelSubType, saleOpportunitySubType, endorsementSubType, complaintSubType
KullanıcıcreatedByName, createdById, createdByEmail, createdByType
TemsilrepresentedByName, representedById, representedByEmail, representedByType
İlişkipolicyCount, proposalCount, lastProposalDate, lastPolicyDate, policyEndDate
GüncellemelastUpdateDate, lastUpdatedByName, lastUpdatedById, …
ÖncelikpriorityScore, priorityRuleHits (ruleName, score, label, description)
MüştericustomerId, customerName, customerType, customerIdentity, iletişim ve adres alanları
AraçvehiclePlateCode, vehicleModelBrandText, vehicleChassisNumber, …
KonutpropertyNumber, propertySquareMeter, propertyDaskPolicyNumber, …
DiğerassetType, assetId, sourceCaseId, advertisingSource, advertisingCampaign, agentBranch

6.3 Örnek sorgu — liste

query CasesList(
$first: Int!
$after: String
$filter: QueryCaseModelFilterInput
$search: QueryCaseModelSearchInput
$order: [QueryCaseModelSortInput!]
) {
casesNew(
first: $first
after: $after
filter: $filter
search: $search
order: $order
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
id
ref
type
status
cancelSubType
saleOpportunitySubType
endorsementSubType
complaintSubType
mainState
subState
productBranch
channel
createdAt
createdByName
createdById
createdByEmail
createdByType
representedByName
representedById
representedByEmail
representedByType
policyEndDate
assetType
assetId
sourceCaseId
policyCount
proposalCount
lastProposalDate
lastPolicyDate
lastUpdateDate
lastUpdatedByName
lastUpdatedById
lastUpdatedByEmail
lastUpdatedByType
priorityScore
priorityRuleHits {
ruleName
score
label
description
}
customerId
customerName
customerType
customerIdentity
customerCityText
customerCityValue
customerDistrictText
customerDistrictValue
customerPrimaryPhoneNumber
customerPrimaryPhoneCountryCode
customerPrimaryEmail
customerBirthDate
customerPassportNumber
customerJob
vehiclePlateCode
vehiclePlateCity
vehicleModelBrandText
vehicleModelBrandValue
vehicleModelTypeText
vehicleModelTypeValue
vehicleModelYear
vehicleUtilizationStyle
vehicleEngineNumber
vehicleChassisNumber
vehicleRegistrationDate
vehicleFuelType
vehicleSeatNumber
vehicleDocumentSerialCode
vehicleDocumentSerialNumber
propertyNumber
propertySquareMeter
propertyConstructionYear
propertyDamageStatus
propertyFloorNumber
propertyStructure
propertyUtilizationStyle
propertyOwnershipType
propertyDaskPolicyNumber
advertisingSource
advertisingCampaign
agentBranchId
agentBranch {
id
name
parentId
parentName
}
searchScore
}
}
}

6.4 Örnek variables

{
"first": 50,
"order": [{ "createdAt": "DESC" }]
}

7. Teklifler (proposalsNew)

7.1 Yetki

KatmanGereksinim
OAuthproposal:read veya core-api
Rolproposals:read

7.2 Kullanılabilir alanlar (özet)

AlanAçıklama
idTeklif ID (ObjectId string)
productBranch, state, channel
insurerCustomerId, insuredCustomerId
productsCount, succeedProductsCount, successRate
createdAt, agentUserCreatedBy
lowestPremium, highestPremium
insuredCustomerName, insuredCustomerIdentityNumber, insuredCustomerTaxNumber
Sigortalı iletişim / adresinsuredCustomerCityText, insuredCustomerPhoneNumber, insuredCustomerEmail, …
AraçvehiclePlateCode, vehicleModelBrandText, vehicleId, …
KonutpropertyId
ŞubeagentBranchId, agentBranch

7.3 Örnek sorgu — liste

query ProposalsList(
$first: Int!
$after: String
$filter: QueryProposalsResultFilterInput
$search: QueryProposalsResultSearchInput
$order: [QueryProposalsResultSortInput!]
) {
proposalsNew(
first: $first
after: $after
filter: $filter
search: $search
order: $order
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
id
productBranch
state
insurerCustomerId
insuredCustomerId
productsCount
succeedProductsCount
createdAt
agentUserCreatedBy {
id
name
email
}
successRate
insuredCustomerName
insuredCustomerIdentityNumber
insuredCustomerTaxNumber
insuredCustomerType
lowestPremium
highestPremium
channel
insuredCustomerCityText
insuredCustomerCityValue
insuredCustomerDistrictText
insuredCustomerDistrictValue
insuredCustomerPhoneNumber
insuredCustomerPhoneNumberCountryCode
insuredCustomerEmail
vehiclePlateCode
vehiclePlateCity
vehicleDocumentSerialCode
vehicleDocumentSerialNumber
vehicleModelBrandText
vehicleModelBrandValue
vehicleModelTypeText
vehicleModelTypeValue
vehicleModelYear
vehicleFuelType
utilizationStyle
insuredCustomerBirthDate
vehicleId
propertyId
agentBranchId
agentBranch {
id
name
parentId
parentName
}
}
}
}

7.4 Örnek variables

{
"first": 20,
"order": [{ "createdAt": "DESC" }]
}

7.5 Tek kayıt — REST

GET https://api.insurup.com/proposals/{proposalId}
GET https://api.insurup.com/proposals/{proposalId}/products
Authorization: Bearer {access_token}

Scope: proposal:read


8. Poliçeler (policiesNew / policiesExpanded)

8.1 Yetki

KatmanGereksinim
OAuthpolicy:read veya core-api
Rolpolicies:read

8.2 policiesNew vs policiesExpanded

SorguKullanım
policiesNewVarsayılan liste — poliçe başına bir satır
policiesExpandedZeyil satırları açılmış görünüm ($unwind Versions)

policiesExpanded ek alanlar: netPremiumChange, grossPremiumChange, commissionChange

8.3 Kullanılabilir alanlar (özet)

GrupAlanlar
Poliçeid, state, productBranch, channel, campaign
PrimnetPremium, grossPremium, commission, *TL, currency, exchangeRate, paymentType, installmentNumber
TarihcreatedAt, startDate, endDate, arrangementDate
ŞirketinsuranceCompanyId, insuranceCompanyName, insuranceCompanyLogo, productId, productName
NumaralarinsuranceCompanyProposalNumber, insuranceCompanyPolicyNumber, renewalNumber, endorsementNumber, endorsementType, updateReasonText, endorsementTimestamp
Sigortalı / sigorta ettirenİsim, kimlik, vergi, şehir, ilçe, doğum tarihi alanları
Araç / konutPlaka, model, vehicleId, propertyId, daskPolicyNumber, …
KullanıcıcreatedBy, representedBy
ŞubeagentBranchId, agentBranch

8.4 Örnek sorgu — policiesNew

query PoliciesList(
$first: Int!
$after: String
$filter: QueryPoliciesResultFilterInput
$search: QueryPoliciesResultSearchInput
$order: [QueryPoliciesResultSortInput!]
) {
policiesNew(
first: $first
after: $after
filter: $filter
search: $search
order: $order
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
id
insurerCustomerId
insuredCustomerId
installmentNumber
productBranch
netPremium
grossPremium
commission
paymentType
currency
exchangeRate
netPremiumTL
grossPremiumTL
commissionTL
insuranceCompanyProposalNumber
insuranceCompanyPolicyNumber
renewalNumber
endorsementNumber
endorsementType
updateReasonText
endorsementTimestamp
createdAt
startDate
endDate
arrangementDate
state
insuredCustomerName
insuredCustomerIdentityNumber
insuredCustomerTaxNumber
insuredCustomerType
insuredCustomerCityText
insuredCustomerCityValue
insuredCustomerDistrictText
insuredCustomerDistrictValue
insuredCustomerBirthDate
insurerCustomerName
insurerCustomerIdentityNumber
insurerCustomerTaxNumber
insurerCustomerCityText
insurerCustomerCityValue
insurerCustomerDistrictText
insurerCustomerDistrictValue
insurerCustomerBirthDate
vehiclePlateCode
vehiclePlateCity
vehicleDocumentSerialCode
vehicleDocumentSerialNumber
vehicleModelBrandText
vehicleModelBrandValue
vehicleModelTypeText
vehicleModelTypeValue
vehicleModelYear
vehicleFuelType
productId
productName
insuranceCompanyId
insuranceCompanyName
insuranceCompanyLogo
createdBy {
id
name
email
}
representedBy {
id
name
email
}
propertyNumber
daskOldPolicyNumber
daskPolicyNumber
vehicleId
propertyId
channel
campaign
agentBranchId
agentBranch {
id
name
parentId
parentName
}
}
}
}

8.5 Örnek variables

{
"first": 50,
"order": [{ "createdAt": "DESC" }]
}

8.6 Tek kayıt — REST

GET https://api.insurup.com/policies/{policyId}
GET https://api.insurup.com/policies/{policyId}/document
Authorization: Bearer {access_token}

Scope: policy:read


9. REST vs GraphQL özeti

EkranListe / arama (CRM senkron)Detay / yazma
MüşterilercustomersNewPOST/GET/PUT/DELETE /customers
VakalarcasesNewCase REST uçları
TekliflerproposalsNewPOST/GET /proposals, ürünler
PoliçelerpoliciesNew veya policiesExpandedGET /policies, manuel poliçe

10. Önerilen entegrasyon akışı

1. Login with InsurUp (OIDC + PKCE) → personel access_token
2. GET /agent-users/me → rol ve permission listesi (kendi CRM UI yetkilendirmesi)
3. Periyodik veya sayfalı GraphQL çekimi:
- customersNew / casesNew / proposalsNew / policiesNew
- after cursor ile tüm sayfalar
4. Detay ihtiyacında REST GET (tek kayıt, ürünler, belge)
5. Token süresi dolunca refresh_token
6. Yazma işlemleri REST + ilgili write scope (customer:write, …)

11. Referanslar

KaynakKonum
OAuth ve tokendocs/login-with-insurup-integration.md
OAuth scope sabitlerisrc/Packages/InsurUp.Api.Contracts/src/InsurUpApiScopes.cs
Agent izinlerisrc/Common/Permissions/.../AgentUserPermissions.cs
GraphQL sorgularısrc/Modules/*/Application/GraphQL/Queries/*Query.cs
GraphQL modellerisrc/Modules/*/*.GraphQLModels/
Agent Panel grid kaynaklarıInsurUp.Apps.AgentPanelCustomersPage.razor, CaseGrid.razor, ProposalGrid.razor, PolicyGrid.razor
Tablo entegrasyon demosuhttps://github.com/InsurUp/ts-toolkit/tree/main/packages/table-adapter-core/demos/vanilla/ts

12. Kontrol listesi

  • OAuth client oluşturuldu; gerekli scope’lar tanımlı (customer:read, proposal:read, policy:read, case:read veya core-api)
  • Login with InsurUp implemente edildi; token personel session’ında
  • POST https://api.insurup.com/graphql ile dört liste sorgusu test edildi
  • Sayfalama (first + after) ile tam veri çekimi doğrulandı
  • Rol izinleri (customers:read, …) ve scope (All/Own/Branch) beklentiyle uyumlu
  • PII maskeleme davranışı anlaşıldı
  • Detay senkronu için REST uçları dokümante edildi
  • Üretim şeması: GET /graphql/schema ile güncel alan listesi alındı