Ingest sözleşmesi (Chrome eklentisi)
TikTok, YouTube, Twitch, Kick, Facebook, Instagram ve Trovo eventlerini ve hediye kataloglarını 14 dilde, tek ortak şemada listeler.
Chrome eklentisi ve StreamEmber launcher her platform × öğe türü × dil için tek bir POST gönderir. Sunucu ham platform yanıtı kabul etmez; ayrıştırma eklentinin işidir. Platformun veri yapısı değişirse eklenti güncellenir, bu sözleşme aynı kalır. Sözleşme değişirse schema sürümü artırılır.
Uç nokta
| Adres | POST https://api.streamember.com/platform-events/ingest.php |
| Başlıklar | Content-Type: application/json, X-Ingest-Token: <config.php'deki sabit UUID> |
| Sıkıştırma | İsteğe bağlı: Content-Encoding: gzip |
| Boyut sınırı | 8 MB (açılmış gövde) |
| Şema | GET ingest.php?schema=1 → JSON Schema (token gerekmez) |
Eklenti host_permissions ile https://api.streamember.com/* adresine erişir; CORS gerekmez. Sunucu yine de OPTIONS isteğine X-Ingest-Token başlığına izin veren bir yanıt döner.
Gövde
{
"schema": "streamember.ingest/1",
"platform": "tiktok",
"item_type": "gift",
"lang": "tr",
"source": {
"agent": "streamember-chrome-extension",
"agent_version": "0.2.0",
"captured_at": "2026-10-07T09:45:36Z",
"platform_lang": "tr-TR",
"streamer_region": "VN",
"page_url": "https://www.tiktok.com/@ornek/live"
},
"items": [
{
"native_id": "5655",
"name": "Gül",
"description": null,
"value": { "amount": 1, "unit": "tiktok_coin" },
"icon": "https://p16-webcast.tiktokcdn.com/img/alisg/webcast-sg/…~tplv-obj.webp",
"flags": { "community": false, "streakable": true },
"attributes": {
"tiktok.gift_type": 1,
"tiktok.gift_sub_type": 0,
"tiktok.gift_label_type": 0,
"tiktok.is_global_gift": true,
"tiktok.is_displayed_on_panel": true
}
}
]
}Alanlar
| Alan | Zorunlu | Tür | Kural |
|---|---|---|---|
schema | ✔ | metin | Tam olarak streamember.ingest/1 |
platform | ✔ | metin | tiktok, youtube, twitch, kick, facebook, instagram, trovo |
item_type | ✔ | metin | Platformun desteklediği tür: TikTok/YouTube/Kick gift, Twitch power_up, Trovo spell |
lang | ✔ | metin | 14 koddan biri, tam olarak (tr, zh-Hant; tr-TR değil). Bu alanda normalleştirme yapılmaz. |
source.agent | ✔ | metin | streamember-chrome-extension, streamember-launcher ya da tikfinity-import |
source.agent_version | ✔ | metin | Anlamsal sürüm, ör. 0.2.0 |
source.captured_at | ✔ | metin | Listenin platformdan alındığı an, ISO 8601 |
source.platform_lang | metin | Platform isteğinde kullanılan dil kodu (tr-TR, zh-Hant-TW) | |
source.streamer_region | metin | Yayıncının ülkesi, ISO 3166-1 alpha-2. Katalogda regions alanına eklenir. | |
source.page_url | metin | Listenin alındığı yayın sayfası (https://) | |
items | ✔ | dizi | 1–5000 öğe |
items[].native_id | ✔ | metin | 1–128 karakter, [A-Za-z0-9_-]; sayı olsa da metin |
items[].name | ✔ | metin | 1–200 karakter, lang dilinde |
items[].description | metin | null | En fazla 1000 karakter | |
items[].value.amount | ✔ | tam sayı | 0 ya da daha büyük |
items[].value.unit | ✔ | metin | tiktok_coin, youtube_jewel, twitch_bit, kick_kick, trovo_mana, trovo_elixir (platforma uygun olan) |
items[].icon | ✔ | metin | Platformun verdiği tam https URL; sunucu olduğu gibi saklar |
items[].flags | nesne | community, streakable (boolean). Eksik bayrak false. | |
items[].attributes | nesne | Anahtar {platform}.{alan}, değer skaler; en fazla 32 anahtar |
Tanımlanmamış alanlar yok sayılır. Aynı gönderimde tekrar eden native_id reddedilir; eklenti listeyi göndermeden önce tekilleştirmelidir.
Platform eşleme rehberi
Deneme kayıtlarından (2026-10-07) çıkarılan eşleme. Sunucu yalnızca sözleşmeye bakar; bu tablo eklenti içindir.
| Alan | TikTok /webcast/gift/list/ → data.gifts[] | YouTube get_panel → giftCollectionViewModel.giftItems[].giftItemViewModel |
|---|---|---|
native_id | id (metne çevrilir) | giftId (ör. football) |
name | name | giftName.content |
value.amount | diamond_count | tokenAmountMicros / 1 000 000 |
icon | image.url_list[0] | unselectedGiftImage.sources içindeki en büyük, // → https:// |
flags.streakable | combo | koleksiyondaki unlockGiftComboExperience |
flags.community | biz_extra içinde anchor_community_level varsa true | false |
attributes | tiktok.gift_type, tiktok.gift_sub_type, tiktok.gift_label_type, tiktok.is_global_gift, tiktok.is_displayed_on_panel | youtube.limited (sınırlı süre rozeti) |
source.streamer_region | data.pages[].region | — |
TikTok listesi aynı hediyeyi birden fazla kez içerebilir (deneme kaydında 677 satır, 673 benzersiz hediye); ilk görülen alınır.
Yanıt
{
"ok": true,
"submission_id": "sub_20261007T114856Z_34e910",
"platform": "tiktok",
"item_type": "gift",
"lang": "tr",
"received": 673,
"created": 3,
"updated": 12,
"unchanged": 658,
"rejected": [
{ "index": 41, "native_id": "99999", "errors": ["value.unit: tiktok için tiktok_coin olmalı"] }
]
}Bütün isteğin reddedilmesine yalnızca zarf hataları yol açar. Öğe düzeyindeki hata sadece o öğeyi reddeder. received = created + updated + unchanged + rejected sayısı.
Hatalar
| HTTP | error | Ne zaman |
|---|---|---|
| 400 | invalid_json | Gövde geçerli JSON değil ya da gzip açılamadı |
| 401 | invalid_token | X-Ingest-Token yok ya da yanlış |
| 405 | method_not_allowed | POST dışı istek (?schema=1 hariç) |
| 413 | payload_too_large | Gövde 8 MB'ı aşıyor |
| 415 | unsupported_media_type | Content-Type JSON değil ya da desteklenmeyen Content-Encoding |
| 422 | invalid_envelope | Zarf alanı geçersiz; ayrıntılar details dizisinde |
| 429 | duplicate_submission | Aynı içerik son 30 dakikada zaten alındı; hiçbir şey yazılmadı. Retry-After saniye cinsinden pencereyi verir. |
| 500 | internal_error | Sunucu tarafı hata (ör. storage/ yazılamıyor) |
Aynı içerik penceresi
Aynı içerik en fazla 30 dakikada bir yazılır (config.php → ingest_duplicate_window_seconds, 0 = kapalı).
- İçerik anahtarı:
platform | item_type | lang | streamer_region | öğeler. Öğelernative_idsırasına göre dizilir; yalnıznative_id,name,value.amountvedescriptionhesaba katılır.captured_at,agentvepage_urlanahtara girmez. - Böylece aynı ülkede ve aynı dilde aynı listeyi gören yüzlerce launcher yalnız bir kez yazar. Farklı ülke, dil ya da değişmiş liste ayrı içeriktir ve hemen kabul edilir.
- İşaret
storage/throttle/<sha1>dosyasında,flockaltında tutulur. Eşzamanlı iki aynı gönderimden yalnız biri geçer, diğeri 429 alır. - Yazım 500 ile biterse işaret geri alınır; bir sonraki gönderim pencereyi beklemez.
- Pencereden eski işaret dosyaları ara sıra (≈ her 200 gönderimde bir) silinir.
İstemci 429'u hata olarak göstermemeli. Launcher aynı lang + streamer_region için kendi tarafında da 30 dakika bekler.
Sunucunun yaptığı
- Token'ı, zarfı ve her öğeyi doğrular.
- Her öğe için:
- Katalogda yoksa oluşturur ve
first_seenatar. - Varsa dilden bağımsız alanları (
value,icon,flags,attributes) son gönderimle günceller; eski değerleristorage/history/altına yazar. - Ad ve açıklamayı
langdilinin dosyasına yazar. last_seen,langsveregionsalanlarını günceller.
- Katalogda yoksa oluşturur ve
- Gönderimi özetiyle
storage/submissions/altına sıkıştırılmış olarak kaydeder. - Hiçbir öğeyi silmez.
tikfinity-importkaynağından gelen gönderim yalnızca eksikleri tamamlar.
Launcher
Launcher, gizli canlı yayın penceresinde sayfanın kendi GET /webcast/gift/list/ yanıtını CDP ile yakalar ve yukarıdaki TikTok eşlemesiyle gönderir:
source.agent:streamember-launcher,agent_version= uygulama sürümü.lang: isteğinwebcast_language/app_languageparametresinden.zh-TW/zh-Hant→zh-Hant,zh*→zh-Hans, diğerleri ilk alt etiket. 14 kod dışında kalırsa gönderilmez.source.platform_lang: ham dil parametresi.source.streamer_region:data.pages[].region.source.page_url: yayın sayfası.- Gövde gzip ile gönderilir. Aynı
lang + regioniçin 30 dakikada en fazla bir istek atılır. Başarısız istek sessizce yok sayılır; yayın izlemeyi etkilemez.
Hediye listesi yalnız TikTok'a giriş yapılmış oturumda istenir. Böylece farklı ülkelerdeki launcher kullanıcıları kendi bölgelerinin listesini toplar.
Eklenti kontrol listesi
- Platform yanıtını eklentide ayrıştır, sunucuya yalnızca bu şemayı gönder.
- Her dil için ayrı istek;
langbizim kodumuz, platformun kodusource.platform_lang. -
native_idher zaman metin; listeyi göndermeden önce tekilleştir. - Biliniyorsa yayıncının ülkesini
source.streamer_regionalanına ekle. - Platform istenen dili uygulamadıysa (ad listesi başka bir dilinkiyle aynıysa) o dili gönderme.
- Yanıttaki
rejectedlistesini kayıt ekranında göster.