PushizoDocs
Mesajlaşma & kampanyalar

Data Feeds

Data Feeds, mesaj gönderilirken her alıcı için harici bir JSON uç noktasından veri çeker ve şablonda {{ feed.<ad>.alan }} olarak kullanılmasını sağlar (sadakat puanı, stok, sepet, hava durumu…). Karar kaydı:…

Data Feeds, mesaj gönderilirken her alıcı için harici bir JSON uç noktasından veri çeker ve şablonda {{ feed.<ad>.alan }} olarak kullanılmasını sağlar (sadakat puanı, stok, sepet, hava durumu…). Karar kaydı: docs/adr/0028-data-feeds-dynamic-content-ai.md.

Feed tanımlama

Dashboard → Mesajlar → Dinamik İçerik → Data Feeds → Yeni feed veya public API:

curl -X POST https://api.pushizo.example/v1/apps/$APP_ID/data-feeds \
  -H "Authorization: Bearer $API_KEY" -H "content-type: application/json" \
  -d '{
    "name": "profil",
    "url_template": "https://api.ornek.com/u/{{ user.external_id }}?sehir={{ user.tags.sehir }}",
    "secret_headers": { "Authorization": "Bearer <servis-anahtarı>" },
    "cache_ttl_seconds": 300,
    "timeout_ms": 1500
  }'
```text

| Alan | Açıklama |
|------|----------|
| `name` | Liquid adı: küçük harf, rakam, alt çizgi (`feed.profil`). App içinde benzersiz. |
| `url_template` | Liquid ile `user.*`, `subscription.*`, `custom_data.*` kullanılabilir; değerler URL kodlanır. |
| `method` | `GET` (varsayılan) veya `POST`. |
| `body_template` | Yalnızca POST: JSON şablonu; değişkenler JSON dize kaçışlıdır. |
| `headers` | Gizli olmayan başlıklar (yanıtta görünür). |
| `secret_headers` | Gizli başlıklar: zarf şifrelemeyle saklanır, bir daha gösterilmez (yalnızca adları). Güncellemede verilmezse korunur, `null` tümünü kaldırır. |
| `cache_ttl_seconds` | 0–86400; önbellek anahtarı feed + çözümlenmiş URL (+gövde). Feed düzenlenince önbellek geçersizleşir. |
| `timeout_ms` | 100–2000 (üst sınır 2 sn). |

## Güvenlik (SSRF)
- Yalnızca `https://` ve herkese açık adresler: `localhost`, `.local/.internal`, özel/ayrılmış IP'ler (10/8, 172.16/12,
  192.168/16, 127/8, 169.254.169.254 metadata, IPv6 yerel…) ve URL içinde kullanıcı adı/parola reddedilir.
- Ad, istek anında DNS ile çözülür; özel bir adrese çözülürse istek yapılmaz ve bağlantı doğrulanan IP'ye
  sabitlenir (DNS rebinding koruması). Yönlendirmeler izlenmez.
- Yanıt en fazla 256 KB ve **JSON** (nesne veya dizi) olmalıdır.
- Yerel geliştirmede `WEBHOOK_ALLOW_INSECURE_TARGETS=true` http/yerel adreslere izin verir (üretimde açılamaz).

## Şablonda kullanım ve yedek içerik
Feed çekilemezse (zaman aşımı, HTTP hatası, JSON olmayan yanıt, devre açık) **gönderim durmaz**; feed değeri boş kalır.
Bu yüzden her feed kullanımına yedek verin:

```liquid
{% if feed.profil %}{{ feed.profil.puan }} puanın var!{% else %}Puanlarını keşfet!{% endif %}
```text

Yalnızca şablonda referans verilen feed'ler çekilir (`feed.profil` → yalnızca `profil`). Aynı gönderim içinde aynı
çözümlenmiş URL bir kez istenir.

## Devre kesici
Bir feed art arda 5 kez hata verirse devre 30 sn açılır ve bu sürede istek yapılmaz. Süre dolunca tek deneme
yapılır: başarılıysa devre kapanır, hatalıysa yeniden açılır. Durum tüm worker örnekleri arasında Redis'te paylaşılır.

## Deneme (test et)
Dashboard'da **Dene** veya `POST /v1/apps/{appId}/data-feeds/{feedId}/test` `{"external_id": "…"}`: örnek
kullanıcının değerleriyle önbelleği atlayarak çeker; durum, HTTP kodu, süre, çözümlenmiş URL ve JSON önizlemesi döner.

## İzleme
- Metrikler: `data_feed_fetch_total{status="ok|cached|timeout|error|circuit_open|blocked"}`,
  `data_feed_fetch_duration_seconds`.
- Worker logu "data feed çekilemedi; varsayılan içerikle devam" uyarısı feed kimliği, durum ve kısa hata içerir;
  URL ve başlıklar loglanmaz.

Bu sayfada