Kişiler, firmalar ve dış kimlik
Kendi sisteminizdeki kullanıcı ve firma numaralarını dış kimlik olarak eşleyin; kişiyi dış kimlikle oluşturun veya güncelleyin, firmayı bağlayın, kullanım ve gelir sinyali gönderin.
Dış kimlik: kişi ve şirket
Kendi sisteminizdeki numaralar ClickFix'te dış kimlik (external_id) olarak tutulur. Kişi ve şirket dış kimlikleri ayrı alanlardır, birbirinden bağımsızdır ve organizasyon içinde tekildir:
| Kayıt | API alanı | Widget identify karşılığı | Sistem bağlamada |
|---|---|---|---|
| Kişi | external_id | user_id | {external_id} |
| Şirket | external_id | company.id | {company_external_id} |
PUT /v1/public-api/contacts/by-external-id kişiyi dış kimliğiyle oluşturur ya da günceller (201 oluşturuldu, 200 güncellendi). Eşleşme yalnız dış kimlikle yapılır; e-posta ya da telefon üzerinden başka bir kişi devralınmaz. Başka kişide olan bir kimlik 409 EXTERNAL_ID_EXISTS döner. Kişiyi önce API ile açıp sonra kullanıcı identify ile gelirse yeni kişi açılmaz, aynı kişiye bağlanır; temsilcinin müşteri siteye girmeden açtığı konuşma (contact_external_id ile) kullanıcı oturum açınca widget'ta görünür.
// Adım 2: kişi ve şirket için ayrı dış kimlik. user_id kişinin, company.id şirketin.
// @ts-check
ClickFix("identify", {
user_id: "1001", // API: contacts.external_id
user_hash: "SUNUCUDA_HESAPLANAN", // user_id + "\n" + company.id üzerinden imzalı
company: { id: "F-77", name: "Acme A.Ş.", domain: "acme.com.tr" }, // API: companies.external_id
});
ClickFix("on", "identify", ({ verified, company_verified }) =>
console.log("doğrulandı:", verified, "firma:", company_verified),
);// Adım 2: kişiyi dış kimliğiyle oluştur/güncelle, şirketi dış kimliğiyle bul.
import { createClient } from "@getclickfix/node";
const client = createClient({
baseURL: process.env.CLICKFIX_BASE_URL!, // https://api.getclickfix.com
apiKey: process.env.CLICKFIX_API_KEY!, // contacts:read, contacts:write, companies:read
});
// Aynı dış kimlikle ikinci çağrı yeni kişi açmaz, günceller (200); ilki 201 döner.
const contact = await client.request(
"/v1/public-api/contacts/by-external-id",
"put",
{ external_id: "1001", name: "Ayşe Yılmaz", email: "ayse@example.com" },
{ idempotencyKey: `user-1001-${Date.now()}` },
);
// Şirketin dış kimliği kişininkinden ayrıdır (widget: company.id).
const companies = await client.request(
"/v1/public-api/companies",
"get",
undefined,
{ query: { external_id: "F-77" } },
);
console.log(
JSON.stringify({ contact: contact.data, companies: companies.data }),
);package main
import (
"context"
"encoding/json"
"fmt"
"os"
"time"
clickfix "github.com/ClickSolveMainTR/clickfix-sdks/go"
)
// Adım 2: kişiyi dış kimliğiyle oluştur/güncelle, şirketi dış kimliğiyle bul.
func externalID(ctx context.Context) error {
client, err := clickfix.New(os.Getenv("CLICKFIX_BASE_URL"), os.Getenv("CLICKFIX_API_KEY"))
if err != nil {
return err
}
name, email := "Ayşe Yılmaz", "ayse@example.com"
key := fmt.Sprintf("user-1001-%d", time.Now().UnixNano())
res, err := client.PutV1PublicApiContactByExternalIdWithResponse(ctx,
&clickfix.PutV1PublicApiContactByExternalIdParams{IdempotencyKey: key},
clickfix.PutV1PublicApiContactByExternalIdJSONRequestBody{ExternalId: "1001", Name: &name, Email: &email})
if err != nil {
return err
}
if res.StatusCode() != 200 && res.StatusCode() != 201 { // 200 güncellendi, 201 oluşturuldu
return fmt.Errorf("clickfix: HTTP %d", res.StatusCode())
}
ext := "F-77" // şirketin dış kimliği (widget identify: company.id)
companies, err := client.GetV1PublicApiCompaniesWithResponse(ctx, &clickfix.GetV1PublicApiCompaniesParams{ExternalId: &ext})
if err != nil {
return err
}
return json.NewEncoder(os.Stdout).Encode(map[string]any{"contact": res.StatusCode(), "companies": companies.StatusCode()})
}<?php
// Adım 2: kişiyi dış kimliğiyle oluştur/güncelle, şirketi dış kimliğiyle bul.
require __DIR__.'/vendor/autoload.php'; // composer require clickfix/sdk guzzlehttp/guzzle
use ClickFix\Client;
$client = new Client(
getenv('CLICKFIX_BASE_URL'), // https://api.getclickfix.com
getenv('CLICKFIX_API_KEY'), // contacts:read, contacts:write, companies:read
);
// Aynı dış kimlikle ikinci çağrı yeni kişi açmaz, günceller (200); ilki 201 döner.
$contact = $client->contacts()->upsertByExternalId(
'1001',
['name' => 'Ayşe Yılmaz', 'email' => 'ayse@example.com'],
idempotencyKey: 'user-1001-'.(int) (microtime(true) * 1000),
);
// Şirketin dış kimliği kişininkinden ayrıdır (widget: company.id).
$company = $client->companies()->findByExternalId('F-77');
echo json_encode(['contact' => $contact, 'company' => $company]), PHP_EOL;# Adım 2: kişiyi dış kimliğiyle oluştur/güncelle (201 oluşturuldu, 200 güncellendi).
curl -sS --fail-with-body -X PUT "$CLICKFIX_BASE_URL/v1/public-api/contacts/by-external-id" \
-H "Authorization: Bearer $CLICKFIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: user-1001-$(date +%s)" \
-d '{ "external_id": "1001", "name": "Ayşe Yılmaz", "email": "ayse@example.com" }'
# Şirketi kendi dış kimliğiyle bul (kişi dış kimliğinden ayrıdır).
curl -sS --fail-with-body "$CLICKFIX_BASE_URL/v1/public-api/companies?external_id=F-77" \
-H "Authorization: Bearer $CLICKFIX_API_KEY"Konuşma ve kişi yanıtlarındaki identity_state alanı verified, anonymous ya da self_named değerini alır; webhook olayları contact_external_id, contact_verified, company_uuid ve company_external_id taşır, böylece kendi kaydınızı ek istek atmadan eşleştirirsiniz.
Şirket
Şirket, widget identify çağrısındaki company ile oluşur ya da eşleşir: birinci anahtar company.id (şirketin dış kimliği; yalnız user_hash onu da imzalıyorsa kullanılır, bkz. kimlik doğrulama), ikinci anahtar domain. İmzalı kimlikle bağlanan şirket panelde Doğrulanmış rozeti taşır. API'de şirket GET /v1/public-api/companies?external_id= ile bulunur; şirket kaydı üzerinde müşteri sağlığı için üç sinyal gönderilir: kullanım (PUT /company-usage, 0–100), gelir (PUT /company-revenue) ve ürün olayları (POST /company-events, bir sonraki bölüm). Şirket her üçünde company_uuid, external_id ya da domain ile seçilir.
// Adım 4: şirket identify ile oluşur ya da dış kimliğiyle eşleşir (ikinci anahtar: domain).
// company.id yalnız user_hash onu da imzalıyorsa bağlanır (user_id + "\n" + company.id).
// @ts-check
ClickFix("boot", {
widgetId: "WIDGET_ID",
user: {
user_id: "1001",
user_hash: "SUNUCUDA_HESAPLANAN", // user_id + "\n" + "F-77" üzerinden
company: { id: "F-77", name: "Acme A.Ş.", domain: "acme.com.tr" },
},
});// Adım 4: şirket. Şirket widget identify (company.id) ile oluşur; API ile
// bulunur ve müşteri sağlığı sinyalleri (kullanım, gelir, olay) gönderilir.
import { createClient } from "@getclickfix/node";
const client = createClient({
baseURL: process.env.CLICKFIX_BASE_URL!,
apiKey: process.env.CLICKFIX_API_KEY!, // companies:read, health:write
});
const found = await client.request(
"/v1/public-api/companies",
"get",
undefined,
{
query: { external_id: "F-77" },
},
);
// 0-100 arası kullanım sinyali; 30 gün boyunca sağlık puanına katılır.
const usage = await client.request(
"/v1/public-api/company-usage",
"put",
{ external_id: "F-77", score: 82 },
// İşlemi tanımlayan sabit değer: kendi ölçüm kaydınızın kimliği (örnekte zaman damgası)
{ idempotencyKey: `usage-F-77-${Date.now()}` },
);
console.log(JSON.stringify({ found: found.data, usage: usage.data }));package main
import (
"context"
"encoding/json"
"fmt"
"os"
"time"
clickfix "github.com/ClickSolveMainTR/clickfix-sdks/go"
)
// Adım 4: şirketi bul ve kullanım sinyali gönder (health:write).
func company(ctx context.Context) error {
client, err := clickfix.New(os.Getenv("CLICKFIX_BASE_URL"), os.Getenv("CLICKFIX_API_KEY"))
if err != nil {
return err
}
ext := "F-77"
found, err := client.GetV1PublicApiCompaniesWithResponse(ctx, &clickfix.GetV1PublicApiCompaniesParams{ExternalId: &ext})
if err != nil {
return err
}
usage, err := client.PutV1PublicApiCompanyUsageWithResponse(ctx,
// İşlemi tanımlayan sabit değer: kendi ölçüm kaydınızın kimliği (örnekte zaman damgası)
&clickfix.PutV1PublicApiCompanyUsageParams{IdempotencyKey: fmt.Sprintf("usage-F-77-%d", time.Now().UnixNano())},
clickfix.PutV1PublicApiCompanyUsageJSONRequestBody{ExternalId: &ext, Score: 82})
if err != nil {
return err
}
if usage.StatusCode() != 200 {
return fmt.Errorf("clickfix: HTTP %d", usage.StatusCode())
}
return json.NewEncoder(os.Stdout).Encode(map[string]int{"found": found.StatusCode(), "usage": usage.StatusCode()})
}<?php
// Adım 4: şirket. Şirket widget identify (company.id) ile oluşur; API ile
// bulunur ve müşteri sağlığı sinyalleri (kullanım, gelir, olay) gönderilir.
require __DIR__.'/vendor/autoload.php';
use ClickFix\Client;
$client = new Client(
getenv('CLICKFIX_BASE_URL'),
getenv('CLICKFIX_API_KEY'), // companies:read, health:write
);
$found = $client->companies()->findByExternalId('F-77');
// 0-100 arası kullanım sinyali; 30 gün boyunca sağlık puanına katılır.
$usage = $client->companies()->setUsage(
['external_id' => 'F-77', 'score' => 82],
// İşlemi tanımlayan sabit değer: kendi ölçüm kaydınızın kimliği (örnekte zaman damgası)
idempotencyKey: 'usage-F-77-'.(int) (microtime(true) * 1000),
);
echo json_encode(['found' => $found, 'usage' => $usage]), PHP_EOL;# Adım 4: şirket kullanım sinyali (0-100, health:write); şirket external_id ile bulunur.
curl -sS --fail-with-body -X PUT "$CLICKFIX_BASE_URL/v1/public-api/company-usage" \
-H "Authorization: Bearer $CLICKFIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: usage-F-77-$(date +%s%N)" \
-d '{ "external_id": "F-77", "score": 82 }'Son güncelleme
Kimlik doğrulama: user_hash ve firma imzası
Giriş yapmış kullanıcıyı ve firmasını widget'a kanıtlı biçimde tanıtın: user_hash sunucuda hesaplanır, firma kimliği imzaya girer; widget, Node.js, Go, PHP ve curl örnekleri.
Özel alanlar
Özel alanı bir kez tanımlayın, aynı anahtarı API'de custom_fields ve widget'ta setAttributes ile gönderin; tip doğrulama, liste alanları ve widget erişimi.