Chargeless Webhook'larını Almak: events/v1
Bu rehber, Chargeless webhook'larını kendi sistemlerinde (yardım masası, CRM, sipariş sistemi ya da veri ambarı) karşılayan işletme mühendisleri için hazırlanmıştır. Her olayın ne anlama geldiğini, gövdesinde neler bulunduğunu, nasıl doğrulanacağını ve yeniden denemeler, yinelenen teslimatlar ve sıralama konusunda nelerle karşılaşacağınızı anlatır.
Sözleşme, Chargeless'ın size sağladığı dosyalardan oluşur. Bu rehberle dosyalar arasında fark varsa dosyalar esas alınır.
| Dosya | İçeriği |
|---|---|
schemas/events/v1/handoff.json |
Tüm olayların ortak zarfı ve başlıkları; handoff.requested, action.failed, ticket.handed_to_team, ticket.message_received, ping |
schemas/events/v1/action-outcome.json |
action.executed, refund.reversed |
schemas/events/v1/customer-request.json |
customer_request.decided |
schemas/events/v1/ticket-status.json |
ticket.status_changed |
schemas/events/v1/payment-alert.json |
payment_alert.opened, payment_alert.resolved |
schemas/events/examples/ |
Her olay için geçerli bir örnek |
CHANGELOG.md |
Sözleşmede yapılan tüm değişiklikler |
Her şema, $id değeri https://schemas.supportroute.dev/events/v1/<name> olan bir JSON Schema
draft 2020-12 belgesidir. Başlık adlarında ve şema kimliklerinde geçen "SupportRoute",
Chargeless'ın önceki çalışma adıdır; istek ve yanıtlarda (wire format) bu ad değişmeden kalır.
1. Webhook'lar Nedir, Ne Değildir
- Bildirimdir, asla soru değildir. Chargeless hiçbir zaman yanıtınızı beklemez. 2xx yanıtı Chargeless'a yalnızca teslimatın ulaştığını bildirir, başka bir anlam taşımaz. Verdiğiniz hiçbir yanıt bir şeyi onaylamaz, reddetmez, yeniden denemez ya da geri almaz.
- İki olay grubu.
- Devir olayları (
handoff.requested,action.failed,ticket.handed_to_team) ekibinizin işi devralması gerektiğini bildirir. Yalnızca devir hedefiniz webhook'u içerdiği sürece gönderilir (Ayarlar → Genel → Devirlerin Gideceği Yer: Yalnızca webhook ya da Ekip kuyruğu ve webhook). Bu ayar webhook'u içerdiği sürece üç olayın her birini en az bir etkin uç nokta almalıdır: panel, olaylardan birini alıcısız bırakacak bir değişikliği kabul etmez. - Bildirimler (
action.executed,refund.reversed,customer_request.decided,ticket.status_changed,payment_alert.opened,payment_alert.resolved) olanları kayıt altına alır. Her uç noktada ayrı ayrı seçilir (opt-in) ve devir hedefiniz ne olursa olsun, yalnızca ekip kuyruğu seçili olsa bile gönderilir.
- Devir olayları (
- Gövdede neler bulunur. Devir olayları, ekibinizin müşteriye yanıt verebilmesi için gereken bilgileri taşır: talep sahibinin adresi ve adı ile yazışmadaki en son mesajlar (en fazla 20). Bu olayları kişisel veri olarak işleyin. Bildirimler yalnızca kimlik, kod, tutar ve zaman damgası içerir; adres, ad ya da mesaj içermez. Hiçbir olayda kart numarası, güvenlik kodu ya da gizli anahtar bulunmaz; mesaj metinlerindeki kart numaraları maskelenir.
- Esas kayıt paneldir. Webhook'lar en az bir kez teslim edilir ve gecikebilir (bölüm 5).
Mutabakat için
cases.readyetkisi olan bir API anahtarıylaCasesService.ListActionsveListCasesprosedürlerini çağırın ya da vakayı veya talebi numarasıyla panelde açın.
2. Uç Nokta Kurulumu
Panelde: Ayarlar → Entegrasyonlar → Webhook'lar → Webhook Uç Noktası Ekle (handoff.manage
yetkisi ve doğrulama uygulamanızdan bir kod gerekir).
- Uç nokta URL'si: 443 numaralı portta herkese açık bir
httpsadresi. Chargeless özel ve dahili adresleri reddeder, bağlanırken adresi yeniden denetler ve yönlendirmeleri hiçbir zaman izlemez. Yanıtı doğrudan bu URL'den verin. - Etiket: uç noktaya kendinizin verdiği ad.
- Aldığı Olaylar: her uç nokta için ayrı ayrı seçilir. Yeni bir olay türü mevcut bir uç noktaya hiçbir zaman kendiliğinden eklenmez; almaya hazır olduğunuzda o türe abone olun.
- Bir çalışma alanında en fazla 10 uç nokta olabilir. Her olay, ona abone olan tüm etkin uç noktalara, her birine ayrı bir teslimat olarak gider.
- Uç noktanın imza anahtarı (
srwh_…) yalnızca bir kez, uç noktayı oluşturduğunuzda gösterilir. Anahtarı gizli anahtar yöneticinizde (secret manager) saklayın. - Deneme Olayı Gönder, abonelikleri ne olursa olsun yalnızca o uç noktaya bir
pinggönderir (uç nokta başına saatte en fazla 10). Ping hiçbir zaman yeniden denenmez.
Eski bir çalışma alanındaki tek devir webhook'undan oluşturulan bir uç noktanın teslimatları, anahtarı bir kez yenileyene (rotate) kadar o çalışma alanının devir imza anahtarıyla imzalanır.
3. İstek
Her teslimat, JSON gövdeli bir HTTP POST isteğidir; Content-Type: application/json ve
aşağıdaki başlıkları taşır:
| Başlık | Değer |
|---|---|
X-SupportRoute-Event |
Olay türü; gövdedeki type ile aynıdır |
X-SupportRoute-Delivery |
Teslimat kimliği: her olay ve uç nokta için bir tane; aynı teslimatın tüm yeniden denemelerinde aynıdır |
X-SupportRoute-Timestamp |
Bu denemenin imzalandığı an, Unix saniyesi olarak (her denemede yenilenir) |
X-SupportRoute-Signature |
v1= ön eki ve ardından {timestamp}.{body} metninin küçük harfli onaltılık (hex) HMAC-SHA256 özeti |
X-SupportRoute-Signature-Previous |
Aynı imza, önceki anahtarla; yalnızca anahtar yenilendikten sonraki 7 gün boyunca |
User-Agent |
SupportRoute-Handoff/1 (ödeme alarmlarında: SupportRoute-Alerts/1) |
Gövde, tüm olaylarda aynı olan zarftır (envelope):
{
"id": "019a4f20-3c00-7d21-8e33-4f5a6b7c8d01",
"type": "ticket.status_changed",
"tenant_id": "0199a1b0-0000-7000-8000-000000000001",
"created_at": "2026-11-04T10:12:05Z",
"data": { "...": "depends on type" }
}id: olayın kimliği. Tüm yeniden denemelerde ve olayı alan tüm uç noktalarda aynıdır. Yinelenen teslimatları bu değerle ayıklayın.type: olay türü. Yönlendirmeyi başlığa göre değil, gövdedekitypedeğerine göre yapın.tenant_id: çalışma alanınız.created_at: olayın oluşturulduğu an (RFC 3339, UTC). Her olayındatanesnesinde, olayın konusu olan gelişmenin kendi zamanı bulunur (changed_at,executed_at,decided_at,opened_at…); sıralamayı bu zamana göre yapın.data: olaya özgü nesne (bölüm 7).
4. İmzayı Doğrulama
Her teslimatı okumadan önce doğrulayın:
- JSON olarak ayrıştırmadan ya da yeniden kodlamadan önce ham gövdeyi bayt olarak okuyun.
X-SupportRoute-Timestampile sizin saatiniz arasındaki fark 5 dakikayı aşıyorsa teslimatı reddedin.v1=+ hex(HMAC-SHA256(anahtar = UTF-8 baytları olaraksrwh_…anahtarınız, mesaj ={timestamp}.{raw body})) değerini hesaplayın.- Bu değer, sabit zamanlı (constant-time) karşılaştırmada
X-SupportRoute-Signatureya daX-SupportRoute-Signature-Previousile eşleşiyorsa teslimatı kabul edin.
Anahtar yenilemeyi güvenli kılan, iki başlığı birden kontrol etmenizdir: eski anahtarı
kullandığınız sürece imzanız -Previous başlığıyla, yenisini devreye aldığınızda ise ana başlıkla
eşleşir.
Node:
import crypto from 'node:crypto';
function verify(rawBody, headers, secret) {
const ts = headers['x-supportroute-timestamp'];
if (!/^\d+$/.test(ts ?? '') || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = 'v1=' + crypto.createHmac('sha256', secret).update(`${ts}.`).update(rawBody).digest('hex');
return [headers['x-supportroute-signature'], headers['x-supportroute-signature-previous']].some(
(sig) => typeof sig === 'string' && sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)));
}Go:
func verify(h http.Header, rawBody []byte, secret string, now time.Time) bool {
ts := h.Get("X-SupportRoute-Timestamp")
sec, err := strconv.ParseInt(ts, 10, 64)
if err != nil || now.Sub(time.Unix(sec, 0)).Abs() > 5*time.Minute {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(ts + "."))
mac.Write(rawBody)
expected := []byte("v1=" + hex.EncodeToString(mac.Sum(nil)))
for _, sig := range []string{h.Get("X-SupportRoute-Signature"), h.Get("X-SupportRoute-Signature-Previous")} {
if sig != "" && hmac.Equal([]byte(sig), expected) {
return true
}
}
return false
}Python:
import hashlib, hmac, time
def verify(raw_body: bytes, headers, secret: str) -> bool:
ts = headers.get("X-SupportRoute-Timestamp", "")
if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
return False
expected = "v1=" + hmac.new(secret.encode(), ts.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
return any(sig and hmac.compare_digest(sig, expected)
for sig in (headers.get("X-SupportRoute-Signature"), headers.get("X-SupportRoute-Signature-Previous")))Anahtarı yenileme. Uç noktadaki Anahtarı Döndür düğmesi yeni anahtarı bir kez gösterir. Sonraki 7 gün boyunca her teslimat iki anahtarla birden imzalanır; böylece yeni anahtarı kendi takviminize göre devreye alabilirsiniz. Yeni anahtarı devreye aldıktan sonra Öncekini Emekliye Ayır ile bu geçiş süresini erken bitirebilirsiniz.
5. Yanıt, Yeniden Denemeler, Yinelenen Teslimatlar ve Sıralama
Yanıtınızı yavaş işlere başlamadan, 5 saniye içinde herhangi bir 2xx koduyla verin: gövdeyi kaydedin, yanıt verin, ardından işleyin. Yanıt gövdesi dikkate alınmaz. (Bir deneme ödeme alarmlarında en fazla 5 saniye, test olayında 10, diğer tüm olaylarda 15 saniye bekler; dolayısıyla 5 saniye her teslimat için yeterlidir.)
| Yanıtınız | Chargeless ne yapar |
|---|---|
| 2xx | Teslim edildi. Bir daha asla gönderilmez |
| Zaman aşımı, bağlantı hatası, 408, 429 ya da 5xx | Giderek uzayan aralıklarla yeniden denenir |
| Diğer tüm durum kodları (400, 401, 403, 404, 410, 3xx…) | Kesin sonuç: başarısız olarak kaydedilir, bir daha asla gönderilmez |
İlk yeniden deneme 30 saniye sonra yapılır; bekleme süresi her seferinde iki katına çıkar ve iki deneme arasında en fazla 4 saat olur:
| Deneme | İlk denemeden yaklaşık ne kadar sonra |
|---|---|
| 2 | 30 sn |
| 3–6 | 1,5 dk, 3,5 dk, 7,5 dk, 15,5 dk |
| 7–10 | 31 dk, 1 sa, 2 sa, 4 sa 15 dk |
| 11, 12 | 8 sa 15 dk, 12 sa 15 dk: devir olayları ve bildirimler için son deneme |
| 13–15 | 16, 20, 24 sa: yalnızca ödeme alarmlarında; son deneme ilkinden yaklaşık bir gün sonra yapılır |
Son denemeden sonra teslimat başarısız olarak kaydedilir ve panelin bildirimlerinde teslimatı başarısız olan uç nokta belirtilir. Ping hiçbir zaman yeniden denenmez.
Yinelenen teslimatlar. Teslimat en az bir kez yapılır: gövdeyi işledikten sonra sizin
tarafınızda zaman aşımı olursa aynı olay yeniden gelir. İşlediğiniz id değerlerini saklayın (bir
hafta yeterlidir) ve daha önce gördüğünüz bir olayı atlayın.
Sıralama. Ne olay türleri arasında ne de aynı türün içinde bir sıra garanti edilir: yeniden
denenen bir action.executed, aynı işlemin refund.reversed olayından sonra gelebilir; bir
talebin iki durum değişikliği de herhangi bir sırayla gelebilir. Bir olayı yalnızca zamanı
(changed_at, executed_at, decided_at, opened_at, resolved_at) o talep, işlem ya da alarm
için elinizdeki kayıttan daha yeniyse uygulayın.
Eksik olaylar. Bir olay hiç gelmeyebilir:
- Kısıtlama (throttling). Uç nokta başına en fazla 250 bildirim (
action.executed,refund.reversed,customer_request.decided,ticket.status_changed) ve en fazla 25 ödeme alarmı bekleyebilir. Sınır aşıldıktan sonra kaydedilen olay başarısız olarak işaretlenir ve hiç gönderilmez; panelin bildirimlerinde ilgili uç nokta belirtilir. Devir olayları hiçbir zaman kısıtlanmaz. - Vazgeçilen teslimatlar. 24 saat sonra hâlâ bekleyen bir bildirimden ya da 25 saat sonra hâlâ bekleyen bir ödeme alarmından vazgeçilir.
- Kesin yanıtlar. 408 ve 429 dışındaki her 4xx yanıtı o teslimatı sonlandırır.
İşlemlerin ve vakaların mutabakatını CasesService.ListActions ve ListCases ile yapın. Bir
payment_alert.resolved olayı, payment_alert.opened olayı olmadan gelebilir: bu durumda onu
alarmın tamamı olarak değerlendirin.
Bir uç noktayı devre dışı bıraktığınızda ya da sildiğinizde bekleyen teslimatları durur. Bu
durumda devir olayları ve bildirimler, o anda kendi türüne abone olan uç noktalar için aynı gövde
ve id ile yeniden kaydedilir. Ödeme alarmları ise gönderilmeden bırakılır.
6. V1 Kapsamındaki Değişiklikler
Chargeless, yeni bir sürüm çıkarmadan v1'e olay türleri, enum değerleri ve isteğe bağlı özellikler
ekler ve her eklemeyi CHANGELOG.md dosyasında listeler. Bir özelliği kaldırmak, yeniden
adlandırmak, türünü değiştirmek ya da zorunlu hale getirmek ise yeni bir sürüm (events/v2)
gerektirir ve önceden duyurulur.
Bu nedenle alıcınız:
- bilmediği bir olay türünü yok sayar ve 2xx ile yanıtlar;
- bilmediği bir özelliği yok sayar;
- bilmediği bir enum değerini belirtilmemiş sayar: bilinmeyen bir talep kanalını "herhangi bir kanal", bilinmeyen bir neden kodunu "neden yok", bilinmeyen bir durumu "değişti" olarak yorumlar;
- gövdede yeni bir şey var diye asla 4xx döndürmez. Bu yanıt kesindir ve olay kaybolur.
Şemalar kapalıdır (additionalProperties: false). Bu kısıt Chargeless için bağlayıcıdır:
Chargeless şemada bulunmayan bir özelliği ya da değeri asla göndermez. Gövdeleri bu şemalarla
doğruluyorsanız sözleşmedeki güncel dosyaları kullanın; doğrulama başarısız olursa teslimatı
reddetmek yerine hatayı günlüğe kaydedin.
7. Olaylar
| Tür | Grup | Ne zaman gönderilir | Şema |
|---|---|---|---|
handoff.requested |
devir | Bir vaka ekibinize devredildi: politika, yanıt denetimi (gate) ya da otomasyon işi bir kişinin devralmasına karar verdi | handoff |
action.failed |
devir | Onaylanan bir iade ya da iptal gerçekleştirilemedi | handoff |
ticket.handed_to_team |
devir | Bir talep, kendisine ait bir işlem olmadan otomasyondan ekibinize geçti | handoff |
action.executed |
bildirim | Bir iade ya da iptal ödeme sağlayıcısında başarıyla gerçekleşti | action-outcome |
refund.reversed |
bildirim | Başarıyla gerçekleşmiş bir iade, sağlayıcı tarafından sonradan başarısız sayıldı | action-outcome |
customer_request.decided |
bildirim | Kendi formunuzdan gelen bir talep karara bağlandı | customer-request |
ticket.status_changed |
bildirim | Bir talebin durumu değişti (değiştiren kim olursa olsun) | ticket-status |
payment_alert.opened |
bildirim | Bir ödeme izleyicisi alarm açtı | payment-alert |
payment_alert.resolved |
bildirim | Bir ödeme alarmı çözüldü | payment-alert |
ping |
test | Deneme Olayı Gönder'i kullandınız | handoff |
ticket.message_received |
— | Tanımlıdır ve panelde listelenir, ancak henüz gönderilmez | handoff |
Tüm tutarlar en küçük para birimi cinsinden (USD için sent, JPY için yen) { "amount_minor": <integer>, "currency": "<ISO 4217>" }
biçimindedir; asla ondalıklı sayı (float) değildir. Alan, sağlayıcıya ait bir kimlik olduğunu
belirtmedikçe tüm kimlikler UUID'dir.
handoff.requested ve action.failed
data, işlemi ve onunla ilgili her şeyi açıklar:
action:id,type(refund,cancel_subscription,handoff,dispute_accept,dispute_submit_evidence),status,target_id(kayıt defterindeki ödeme, abonelik ya da itiraz; ya da null),amount(ya da null),reason_code,failure(action.failedolayında başarısızlığın nedeni; asla kart verisi içermez),requested_by,created_at.case: vaka (id,type,status,customer_id,transaction_id,subscription_id, zaman damgaları) ya da null. Vakanıntypedeğerichat_refund,chat_cancellation,fraud_alert,dispute,ticketya dastaff_action(bir ekip üyesinin panelden yaptığı iade ya da iptal) olabilir.decision:outcome(allow,deny,handoff), sıralı gerekçelerreasons(code, İngilizcetextve kendi kurallarınız içinrule_id), değerlendirme izitrace, uygulanan güvenlik sınırlarılimits_appliedvepolicy_version(v7).timeline: vakanın geçmişi, en eskiden en yeniye.ticket_id,ticketvethread_excerpt: devrin ilgili olduğu talep ve yardım masanızın bu talebi yanıtlamak için ihtiyaç duyduğu bilgiler (aşağıda); talebe bağlı olmayan bir devirde (erken dolandırıcılık uyarısı, itiraz) null ve boştur.
Devri data.action.id ile tanımlayın (anahtar olarak bunu kullanın). Ekibin devralmasına bir
işlem yol açtıysa, talep için o işlemin handoff.requested ya da action.failed olayı gönderilir;
bunun yanında asla bir ticket.handed_to_team gönderilmez.
ticket.handed_to_team
{
"id": "0199a3d0-1c2e-7f10-8a55-3b9e6d2c4f05",
"type": "ticket.handed_to_team",
"tenant_id": "0199a1b0-0000-7000-8000-000000000001",
"created_at": "2026-09-25T13:41:07Z",
"data": {
"ticket_id": "0199a3f1-0b00-7a01-9b22-1c3d4e5f6a74",
"reason": "customer_requested",
"thread_excerpt": [
{ "author": "customer", "text": "My subscription renewed but I cancelled it last month.", "at": "2026-09-25T13:39:12Z" },
{ "author": "agent_llm", "text": "I can see the renewal on your account. Could you tell me when you cancelled?", "at": "2026-09-25T13:39:20Z" },
{ "author": "customer", "text": "I'd like someone from your team to look at this, please.", "at": "2026-09-25T13:41:02Z" }
],
"ticket": {
"number": 57,
"subject": "Renewal after cancellation",
"channel": "widget_message",
"requester_email": "[email protected]",
"requester_name": "Sam Rivera",
"requester_verified": true,
"identity_method": "email_otp"
}
}
}reason: sabit bir koddur, asla serbest metin değildir. Olası değerlerden bazıları:customer_requested,out_of_scope,unable_to_resolve,needs_identity,sender_unverified(göndereni doğrulanamayan bir e-posta; müşteriye hiçbir şey gönderilmedi),automation_stalled(otomasyon müşterinin mesajını bir saat boyunca yanıtsız bıraktı),automation_failed, yanıt bütçelerine ait*_budget_exhaustedvedaily_automation_cap_exhausted,request_disownedveidentity_not_on_file(form talepleri, aşağıda) ve kendi ödeme sisteminiz ya da yardım masanızla ilgiliprovider_unavailable,target_not_found,ownership_not_established,ambiguous_customer,ambiguous_target,helpdesk_taken_over. Bu liste zamanla genişler; bilinmeyen bir koduunspecifiedolarak yorumlayın.thread_excerpt: en son mesajlar (en fazla 20), en eskiden en yeniye; her birindeauthor(customer, otomasyon içinagent_llm,staff,system),text(kart numaraları maskelenmiş, 4.000 karakterde kesilmiş) veatbulunur. Dahili notlar hiçbir zaman eklenmez.ticket:number(panelde göründüğü haliyle),subject,channel(email,widget_message,web_form,chat_handoff,helpdesk,merchant_form),requester_email(yanıtların gideceği adres ya da null),requester_name(talep sahibinin yazdığı haliyle, doğrulanmamış),requester_verifiedveidentity_method(none,signed_token,email_otp,email_link). Hesap ayrıntılarını yalnızca doğrulanmış bir adrese yazın.helpdesktaleplerinde ayrıcaexternal_refbulunur: bağlayıcı, talebin yardım masanızdaki kimliği ve bağlantısı.
Her talep için bir kez gönderilir; devralmayla aynı veritabanı işleminde (transaction) kaydedilir.
action.executed ve refund.reversed
{
"id": "019a3410-2b00-7c11-8d22-3e4f5a6b7c01",
"type": "action.executed",
"tenant_id": "0199a1b0-0000-7000-8000-000000000001",
"created_at": "2026-10-30T09:14:07Z",
"data": {
"action_id": "019a3410-1f00-7a01-9b22-1c3d4e5f6a90",
"action_type": "refund",
"source": "merchant_user",
"status": "executed",
"amount": { "amount_minor": 2499, "currency": "EUR" },
"connection_id": "0199a1b0-0000-8000-8000-000000000001",
"target": { "type": "transaction", "id": "019a33f0-7a10-7b3e-9d41-5f2a8c6e1b02", "provider_id": "ch_3QxZ8aLkdIwHu7ix0abcDEF1", "public_ref": "PAY-7K3F9QS" },
"provider_operation_id": "re_3QxZ8aLkdIwHu7ix0ghiJKL2",
"case": { "id": "019a33fe-0000-7c0d-8e0f-101112131417", "number": 482 },
"ticket_id": "019a33fd-ff02-7a01-9b22-1c3d4e5f6a73",
"policy_version": "v7",
"manual_override": false,
"actor_user_id": "0199b2c0-4d5e-7f60-8a71-92a3b4c5d6e7",
"executed_at": "2026-10-30T09:14:06Z",
"revised_from_failed": false
}
}- Kaynağı ne olursa olsun, her işlem ve tür için en fazla bir kez gönderilir: widget sohbeti
(
chat), otomasyonun bir talebe verdiği yanıt (ticket), bir ekip üyesi (merchant_user,actor_user_idile birlikte), erken dolandırıcılık uyarısı ve itiraz iş akışları (fraud_alert,dispute) ve API üzerinden arka uç sisteminiz (system). amountödemenin kendi para birimindedir ve asla dönüştürülmez; iptallerde ve itiraz işlemlerinde null olur.target.provider_id(Stripe'tach_…,sub_…ya dadp_…; kendi sisteminizde sizin referansınız) yalnızca kendi ödeme bağlantısı içinde benzersizdir:connection_idile birlikte anahtar olarak kullanın.target.public_ref, ödemenin ya da aboneliğin kısa referansıdır ("PAY-…", "SUB-…"; ADR 0042); çalışma alanınızda benzersizdir ve müşterilerinizin gördüğü referans budur; itirazlarda null olur.events/v1/handoffaynı değerleriaction.target_public_ref,case.transaction_public_refvecase.subscription_public_refalanlarında taşır. Bu alanlar 2026-11-08'de v1'e eklendi: gövdeleri şemanın bir kopyasıyla doğruluyorsanız kopyanızı güncelleyin (nesneler bilinmeyen özelliklere izin vermez).- Hiçbir politika çalışmadıysa
policy_versionnull olur; bir ekip üyesi politika dışı onayla işlem yaptıysamanual_overridetrue olur. revised_from_failed(action.executedolayında): işlem önce başarısız olarak kaydedilmiş, ardından sağlayıcıda gerçekleşen başarı bu kaydı düzeltmiştir. Bu işleminaction.failedolayına göre bir adım attıysanız, yaptığınızı gözden geçirin.refund.reversedaynı alanları ve ek olarakreversed_atalanını taşır; işlemexecuteddurumunda kalır. Geri alma (reversal) bir kişinin ilgilenmesini gerektiriyorsa, devir hedefinize bağlı olarak birhandoff.requestedda gelebilir: o olay ekibinizden harekete geçmesini ister, bu olay ise yalnızca durumu kayda geçirir.
customer_request.decided
Kendi formunuzun RequestIntakeService.SubmitCustomerRequest ile gönderdiği bir talep karara
bağlandığında gönderilir: bir kez talep ulaştığında, bir kez de müşteri talebi talep sayfasında
onayladığında.
{
"id": "019a3b14-2b00-7c11-8d22-3e4f5a6b7c12",
"type": "customer_request.decided",
"tenant_id": "0199a1b0-0000-7000-8000-000000000001",
"created_at": "2026-11-01T09:31:40Z",
"data": {
"request_id": "order-1001-refund",
"ticket": { "id": "019a3b10-1f00-7a01-9b22-1c3d4e5f6a01", "number": 231 },
"action_id": "019a3b14-1f00-7a01-9b22-1c3d4e5f6a03",
"action_type": "refund",
"decision": "after_confirmation",
"outcome": "pending",
"reason_code": null,
"decided_at": "2026-11-01T09:31:39Z"
}
}request_id: talebe sizin verdiğiniz kimlik, gönderdiğiniz şekliyle.decision:firstya daafter_confirmation.outcome: olay oluşturulduğu anda talebin durumu:executed,pending(onaylandı ve sağlayıcıya iletiliyor; başarılı olduğundaaction.executedolayı gelir),denied,handoffya daidentity_required(adresin sahibinin talep sayfasında onay vermesi bekleniyor).reason_code: kararı belirleyen gerekçe;executedvependingiçin null.
Müşterinin sahiplenmediği ("This wasn't me") ya da kayıtlarda kimseye ait olmayan bir adresten
onaylanan bir talep yeniden karara bağlanmaz: talep ekibinize geçer ve bunu ticket.handed_to_team
olayı bildirir (request_disowned, identity_not_on_file).
ticket.status_changed
Değişikliği kim yaparsa yapsın, her talebin her durum değişikliğinde gönderilir: ekibinizden bir üye, çözülmüş bir talebe yeniden yazan müşteri ya da Chargeless'ın kendisi.
{
"id": "019a4f20-3c00-7d21-8e33-4f5a6b7c8d01",
"type": "ticket.status_changed",
"tenant_id": "0199a1b0-0000-7000-8000-000000000001",
"created_at": "2026-11-04T10:12:05Z",
"data": {
"ticket": { "id": "019a4f1e-2b00-7c11-8d22-3e4f5a6b7c10", "number": 412 },
"channel": "merchant_form",
"handling": "automation",
"from": "new",
"to": "solved",
"actor": { "kind": "system", "user_id": null },
"reason": "request_finished",
"changed_at": "2026-11-04T10:12:04Z"
}
}from,to:new,open,waiting_on_customer,on_hold,solved,closed.handling: değişiklikten sonra talebi kimin yürüttüğü:automation,team(paneldeki ekibiniz) ya daexternal(kendi sisteminiz; talep Chargeless'ta salt okunur bir kayıt olarak durur).actor.kind:staff(değişikliği yapan üyeactor.user_idiçinde),customer(müşterinin yanıtı çözülmüş bir talebi yeniden açtı) ya dasystem.reason(yalnızca sistemin yaptığı değişikliklerde; diğerlerinde null):Neden Değişiklik request_finishedOtomasyon talebi sonuçlandırdı (bir işlem gerçekleşti ya da kesin olarak reddedildi) ve müşteriye bildirdi: solveddurumuna geçercustomer_quietOtomasyon yanıt verdi, müşteri ise çalışma alanının bekleme süresi (varsayılan 72 saat) içinde geri yazmadı: solveddurumuna geçersolved_quietTalep, çalışma alanının kapanma süresi (varsayılan 7 gün) boyunca çözüldü durumunda kaldı: closeddurumuna geçerteam_entryTalep ekibinizin kuyruğuna geldi: newdurumuna geçerprovider_outcome_changedTalep çözüldükten ya da kapatıldıktan sonra ödeme sağlayıcısı, talebin vakasındaki bir sonucu değiştirdi: talep yeniden açılır closeddurumundaki bir talep de böyle bir sağlayıcı değişikliğiyle yeniden açılabilir; Chargeless hiçbir talebi silmez.
Bir talebin birden fazla değişikliği art arda gelebilir (örneğin team_entry ve hemen ardından
bir üyenin solved değişikliği): bunları changed_at değerine göre sıralayın.
payment_alert.opened ve payment_alert.resolved
Bir ödeme izleyicisi (Ödeme Analizi → alarmlar) bir alarm açtığında ya da çözdüğünde gönderilir. Gövde yalnızca kendi ödeme denemelerinize ait toplu sayıları içerir: müşteri, kart ya da tutar bilgisi yoktur.
alert_id: bir alarmın iki olayında da aynıdır; anahtar olarak bunu kullanın.monitor:auth_rate_drop,failure_category_spike,fraud_warning_rate,dispute_rate,network_programme.status(open,resolved),sensitivity,scope(kart ülkesi, kart markası ya da hata kategorisi; daraltılmamışsa her biri null),connection(id,label; yalnızca gösterim amaçlı).currentvebaselinedönemleri (period,from,to, deneme sayısı,numerator,denominator, baz puan cinsindenrate_bp), uygulanan eşikthresholdvechange_bp,multiple_milli,z_milli.network_programme(yalnızca bu izleyicide): program (visa_vamp_merchant,mastercard_ecm,mastercard_hecmya dacustom), kart ağı, kademe (approaching,projected,breached), ay ve sayılar.resolution(resolvedolayında):recovered,monitor_disabled,escalated,programme_exited,limit_removed.panel_url: Ödeme Analizi sayfası (panele giriş yapmanız gerekir).
Açık bir alarmın sonraki değerlendirmeleri gönderilmez. Çözülen bir alarmın olayı, açılış olayı olmadan da gelebilir.
ping
{
"id": "019a2f4c-7d10-7a3e-9c41-5e6f708192a3",
"type": "ping",
"tenant_id": "0199a1b0-0000-7000-8000-000000000001",
"created_at": "2026-10-28T10:15:00Z",
"data": { "endpoint_id": "019a2f40-1b2c-7d3e-8f40-516273849506" }
}Diğer tüm olaylar gibi imzalanır. Abone olmadan önce URL'nizi, TLS yapılandırmanızı ve imza doğrulama kodunuzu denemek için kullanın.
8. Abone Olmadan Önce Kontrol Listesi
- URL, 443 numaralı portta herkese açık bir
httpsadresidir ve yönlendirme olmadan doğrudan yanıt verir. - İşleyici ham gövdeyi okur ve imzayı, 5 dakikalık zaman damgası aralığıyla, iki imza başlığına karşı da doğrular.
- 5 saniye içinde 2xx döndürür, işlemeyi sonra yapar.
- Daha önce işlediği bir
iddeğerini atlar. - Olayları geliş sırasına göre değil, olayın kendi zamanına göre sıralar.
- Bilinmeyen bir türe, özelliğe ya da değere 2xx ile yanıt verir ve şema doğrulaması nedeniyle hiçbir teslimatı reddetmez.
- Devir olayları kişisel veri olarak saklanır: talep sahibinin adresini, adını ve mesajlarını taşırlar.
- Deneme Olayı Gönder ile gönderilen ping, işleyiciniz tarafından kabul edilir.
- Panelin bildirimlerinde başarısız teslimatları takip eden biri vardır; böyle bir bildirim
göründüğünde
ListActionsile mutabakat yaparsınız.