> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Kampanyayı uçtan uca gönderin: taslak, hedef kitle, dry-run, başlatma, analiz

> Bir kampanyayı taslaktan başlatmaya ve ölçümeye taşıyın — hedef kitleyi seçin, alıcıları önizleyin, uçuş öncesi dry-run'ı çalıştırın, blast veya drip olarak başlatın ve istatistikleri, holdout lift'ini ve ROI'yi okuyun.

# Kampanyayı uçtan uca gönderin

Bu rehber, kampanya yaşam döngüsünün tamamında API üzerinden ilerler: taslak oluşturma, hedef kitle bağlama, kişiselleştirmeyi önizleme, uçuş öncesi dry-run'ı çalıştırma, başlatma ve sonucu ölçme. Bir kez izlediğinizde aynı sıra her kanalda çalışır — SMS, WhatsApp, e-posta, RCS, ses, push.

SDK kullanıcıları aşağıdaki yaşam döngüsünün tamamını cURL olmadan yürütebilir: her adım, curl bloğunun yanında bir [Node SDK](https://docs.orbit.devotel.io/sdks/node.md) sekmesi taşır — varsa tipli `orbit.campaigns.*` yardımcısı, yoksa API yüzeyindeki her uç noktayı kapsayan genel `orbit.request(method, path, body)` kaçış yolu.

İstek ve yanıt şemaları için [campaigns API referansına](https://docs.orbit.devotel.io/api-reference/endpoints/campaigns.md) bakın. Bu sayfa iş akışını kapsar; varyantları [A/B testi rehberi](https://docs.orbit.devotel.io/guides/campaign-ab-testing.md), teslim edilebilirlik ve uyumluluk ayrıntılarını ise [en iyi uygulamalar](https://docs.orbit.devotel.io/guides/best-practices.md) ve [opt-out listeleri](https://docs.orbit.devotel.io/guides/opt-out-lists.md) kapsar — aşağıda tekrarlanmak yerine bağlantılanır.

## 1. Ön koşullar

* **`campaigns:write` scope'una sahip bir API anahtarı.** Aşağıdaki tüm okumalar (hedef kitle önizleme, dry-run, istatistikler) `campaigns:read` de kabul eder, ancak başlatma eylemleri write gerektirir. Anahtarları panoda Settings → API keys altında oluşturun veya düzenleyin.
* **Node SDK (isteğe bağlı).** cURL yerine SDK sekmelerini tercih ediyorsanız `npm install @devotel-orbit/node`.
* **Kanalınız için gönderim kimliği.** SMS/MMS için doğru kayıtlara sahip bir numara veya gönderici havuzu (ABD A2P için [10DLC](https://docs.orbit.devotel.io/guides/10dlc-registration.md) gerekir); WhatsApp için bağlı bir WABA; e-posta için doğrulanmış bir gönderici alan adı.
* **Onaylı bir hedef kitle kaynağı.** Bir kişi listesi, canlı bir segment, alıcı adreslerinden oluşan bir CSV, harici bir CRM kitlesi (HubSpot listesi / Salesforce raporu) veya elle seçilmiş bir dizi kişi kimliği. Hedef kitleler opt-in olmuş alıcılardan gelmelidir — suppression ve abonelikten çıkma işleme, göndericiye bırakılmayıp gönderim anında zorunlu olarak uygulanır.

## 2. Taslak kampanyayı oluşturun

Kampanyayı bir kanal, bir hedef kitle ve bir `message_template` ile oluşturun. Şablon, oluşturma anında isteğe bağlıdır — şablonsuz bir taslak başlatılamaz — ancak baştan vermek taslağı eksiksiz tutar.

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns" \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Retail promo — summer sale",
    "type": "blast",
    "channel": "sms",
    "audience_type": "list",
    "audience_id": "list_summerVIPs",
    "message_template": "Hi {{first_name}}, early access to our summer sale starts now: 25% off through Sunday. Reply STOP to opt out.",
    "send_time_optimization": "fixed"
  }'
```

```typescript Node.js (TypeScript) theme={null}
import { Orbit } from "@devotel-orbit/node";

const orbit = new Orbit({ apiKey: process.env.ORBIT_API_KEY });

const campaign = await orbit.campaigns.create({
  name: "Retail promo — summer sale",
  channel: "sms",
  message_template:
    "Hi {{first_name}}, early access to our summer sale starts now: 25% off through Sunday. Reply STOP to opt out.",
});
```

Tipli yardımcı, çekirdek `name` / `channel` / `message_template` üçlüsünü alır. curl sekmesinde gösterilen tam gövdeyi (`type`, `audience_type`, `send_time_optimization`, …) geçmek için SDK'nin `orbit.request("POST", "/campaigns", body)` kaçış yolu her alanı kabul eder. Her iki biçim de API anahtarınızda `campaigns:write` scope'u gerektirir.

Oluşturma anındaki anahtar alanlar:

| Alan | Notlar |
| - | - |
| `type` | `blast` (tek zamanlanmış gönderim), `drip` (çok adımlı dizi), `journey` (olay güdümlü) veya `ad`. |
| `audience_type` | `all`, `list`, `segment`, `csv` veya `manual` (elle seçilmiş kişi kimlikleri). |
| `audience_id` | `audience_type` `list` veya `segment` iken zorunludur. |
| `audience_source` | Gönderim anında list/segment ikilisini geçersiz kılan isteğe bağlı CRM tanımlayıcısı (`hubspot_list`, `salesforce_report`, …). |
| `message_template` | En fazla 100.000 karakter; e-posta gövdeleri rahatça sığar. Kişiselleştirme token'ları `{{token}}` biçimini kullanır. |
| `subject` | Yalnızca e-postaya özgü konu satırı. E-posta dışı kanallarda yok sayılır. |
| `send_time_optimization` | `fixed` (tek parti zamanı) veya `recipient-optimal` (kişi başına en iyi zaman, bkz. adım 6). |
| `throttle_rate` | Mesaj/saniye cinsinden gönderim tavanı, 0–1000. Yok/0 = platformun varsayılan hızlandırması. |
| `scheduled_at` | Başlatma için ISO zaman damgası; sonradan düzenlenebilir. Gelecekte olmalıdır. |
| `recurrence` | Yinelenen kampanyalar için isteğe bağlı takvim. |
| `credit_cap_usd_cents` | Sert harcama tavanı; ulaşıldığında kampanya otomatik duraklar. |

Yanıt, kampanyayı `draft` durumunda döndürür. Adım 6 açıkça başlatana kadar hiçbir şey gönderilmez.

## 3. Hedef kitleyi bağlayın ve doğrulayın

Üç hedef kitle biçimi yaygındır; tümü aynı şekilde önizlenir.

**Liste veya segment.** Bir `audience_id` ile `audience_type: "list" | "segment"` geçin, ya da bir CRM `audience_source` tanımlayıcısı kullanın. Segmentler gönderim anında canlı değerlendirilir; bu yüzden büyüyen bir segment çalışmaya devam eder.

**CSV alıcıları.** Tek seferlik bir liste için adresleri doğrudan kampanyanın `variables.csv_recipients` dizisine POST edin (telefon kanalları için E.164). Kampanya bunları saklar ve çözümleyici, alıcı uydurmak yerine teslim edilemez girdileri işaretler.

**Elle seçim.** `variables.manual_contact_ids` ile `audience_type: "manual"`, belirli kişi kimliklerini hedefler — listeyle aynı uygunluk hesabı.

Başlatmadan önce hedef kitlenin neye çözüldüğünü her zaman sayın. `POST /api/v1/campaigns/audience/preview`, kampanyanın taşıdığı hedef kitle biçiminin aynısını kabul eder ve `matching_count` ile 10 kişilik bir örnek döndürür:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/audience/preview" \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audience_type": "list",
    "audience_id": "list_summerVIPs",
    "channel": "sms"
  }'
```

```typescript Node.js (TypeScript) theme={null}
import { Orbit } from "@devotel-orbit/node";

const orbit = new Orbit({ apiKey: process.env.ORBIT_API_KEY });

// No typed helper wraps this endpoint — the SDK index
// ([/sdks](/sdks#node)) routes uncovered endpoints through
// the generic `request()` escape hatch.
const preview = await orbit.request("POST", "/campaigns/audience/preview", {
  audience_type: "list",
  audience_id: "list_summerVIPs",
  channel: "sms",
});
```

`channel` geçerseniz yanıt ayrıca bir net projeksiyon döndürür: brüt eşleşmeler eksi suppression listesi satırları, eksi kanal düzeyi opt-out'lar, eksi o kanal için teslim edilebilir adresi olmayan kişiler (örneğin e-posta kampanyası için kayıtlı e-postası olmayanlar). Danışma niteliğindeki `frequency_capped` tahmini, frekans sınırının yaklaşık kaç gönderimi tutacağını gösterir. Önizleme, kriter başına beş dakika önbelleklenir; bu yüzden aynı çekmecenin yeniden çizimi ucuzdur.

`matching_count` 0 dönerse, ilerlemeden önce hedef kitleyi düzeltin — dry-run (adım 5) boş hedef kitleleri yüksek sesle raporlar, ancak yineleme yeri önizlemedir.

## 4. Kişiselleştirme ve yerel ayar

Şablonlar, kişi alanlarından ve kampanya `variables`'ından alıcı başına çözülen `{{token}}` yer tutucuları kullanır — `{{first_name}}` yaygın durumdur. Çözülemeyen token'lar gönderim anında boş dizgeye düşer ve önizleme uç noktası, token'ın kişi başına hangilerinin çözüldüğünü söyler; böylece hatalı yazılmış bir `{{frist_name}}` başlatmadan önce yakalanır.

Kayıtlı bir şablonu başka bir yerel ayara çevirmek için `POST /api/v1/campaigns/templates/translate` kullanın; bu, token'ları ve opt-out talimatını koruyarak şablon gövdesini hedef dil için yeniden yazar. Akılda tutulacak garantiler:

* Token'lar çeviri boyunca olduğu gibi korunur.
* Tek opt-out talimatı tam olarak bir kez kalır (operatör gerekliliği).

Yerelleştirilmiş gövdeyi kampanyada varyant şablonlar olarak saklayın, ya da hedef kitleyi dile göre segmentleyip yerel ayar başına bir kampanya yürütün. Her iki yolda da dry-run (sonraki adım) nihai şablonu doğrular.

## 5. Uçuş öncesi: dry-run çalıştırın

Başlatmadan önce dry-run'ı POST edin. Yalnızca okur — hiçbir durumu değiştirmez, cüzdana dokunmaz, hiçbir işi kuyruğa koymaz — isterseniz sihirbazdaki her tuş vuruşunda çağırın.

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/cmp_abc123/dry-run" \
  -H "X-API-Key: $ORBIT_API_KEY"
```

```typescript Node.js (TypeScript) theme={null}
import { Orbit } from "@devotel-orbit/node";

const orbit = new Orbit({ apiKey: process.env.ORBIT_API_KEY });

const report = await orbit.request(
  "POST",
  `/campaigns/${"cmp_abc123"}/dry-run`,
);
// Same escape hatch as the audience preview above — no body needed.
```

Rapor sekiz kovayı bir araya getirir:

* `audience.total_in_audience` — brüt eşleşen sayısı.
* `audience.suppressed` / `opted_out` / `unreachable` — net projeksiyon kohortları (suppression listesi, kanal başına opt-out'lar, kanal adresinin eksikliği).
* `audience.held_out` — `variables.campaign_holdout_percent` ayarlıysa artırılışklık kontrol kohortuna ayrılan alıcılar; teslimden hariçtir.
* `audience.deliverable` — başlatmanın deneyeceği tam net sayı.
* `cost.unit_price_cents` / `cost.total_cents` — gönderim yolunun kullandığı çözümleyicinin üzerinden fiyatlanır; böylece sayı, yuvarlama payıyla cüzdan düşüşüyle eşleşir.
* `cost.balance_cents` / `cost.sufficient` — cüzdan kontrolü; yeşil bir dry-run, yeşil bir başlatma bakiye kapısı anlamına gelir.
* `quiet_hours.skipped_estimate` ve `quiet_hours.window` — alıcı yerel saatine göre quiet hours'tan öngörülen atlama oranı ve değerlendirilen çözümlenmiş pencere.
* `channel_waterfall` — birincil kanal ve kanallar arası yedek biçimi; böylece göndermeye basmadan önce RCS → SMS (veya kurduğunuz zincir her neyse) doğrulanabilir.
* `warnings[]` — engellemeyen sorunlar (kanal için kayıtlı sağlayıcı yok, quiet hours pencereyi tamamen kapatıyor, …) sert hatalardan ayrı çizilir.

İki isteğe bağlı uçuş öncesi kapı:

* **Onaylar.** Organizasyonunuz amir onayı gerektiriyorsa başlatma (`POST /campaigns/:id/send`) göndermek yerine bekleyen onay durumu döndürür; onaycı kuyruğu `GET /campaigns/approvals/pending`, organizasyon varsayılanları `GET/PUT /campaigns/approvals/settings` altındadır.
* **Sağlayıcı hazır oluşu.** Dry-run, liste hijyenini ve sağlayıcı kaydını uyarıları üzerinden örtük olarak denetler — yapılandırılmış sağlayıcısı olmayan bir kanal, gönderimde hata vermek yerine orada görünür.

`warnings: []` ve `cost.sufficient: true` döndüren sağlıklı bir dry-run, başlatmayı temizler.

## 6. Başlatın ve gönderim biçimini seçin

`POST /api/v1/campaigns/cmp_abc123/send` ile başlatın (gelecek bir parti için `scheduled_at`). Seçilecek dört gönderim biçimi:

**Blast.** Tek zamanda tek parti. `type: "blast"`. En yalın biçim — teslim edilebilir hedef kitlenin tamamı `throttle_rate` hızlandırmasıyla tek geçişte çıkar.

**Drip dizisi.** Bir `steps` dizisiyle (en fazla 50 adım) `type: "drip"`. Her adımın kendi kanalı, gecikmesi ve isteğe bağlı okuma koşulu koruması vardır. Kampanyadaki `message_template`, adım-0 karşılama mesajıdır. Drip ilerlemesi `GET /campaigns/:id/drip-analytics` altında görünür.

**Journey.** `type: "journey"` — `GET /campaigns/:id/journey-analytics` ile düğüm başına analiz ve `GET /campaigns/:id/journey/node-analytics` ile düğüm kırılımları sunan olay güdümlü kayıt. Journey simülasyon uç noktası (`POST /campaigns/journeys/simulate`), blast dry-run'ının hedef kitleler için yaptığını yapar: grafı başlatmadan önce kuru koşar. [Kampanya yolculuk kurucu rehberi](https://docs.orbit.devotel.io/guides/campaign-journey-builder.md) görsel tuvali, graf doğrulama kapılarını, simülatörü ve dönüşüm hedefi bağlamayı uçtan uca anlatır.

**Kanal yedek merdiveni.** Çok kanallı kampanyalar için `channels` dizisi sıralı bir zincirdir (azami derinlik zorunlu, yinelenen kanal yok). Son olmayan her girdi bir `fallback_on` tetikleyicisi taşır — `failed`, `no_delivery` veya `no_engagement` — ayrıca bir `fallback_after_seconds` penceresi. Son girdi uçtur ve yedek alanı taşımaz. Zincir varsa, üst düzey `channel` ilk girdiye eşit olmalıdır. Birleşik [yedek zincirleri rehberi](https://docs.orbit.devotel.io/guides/fallback-chains.md) bu yüzeyi mesaj başına `cascade_policy` ve Verify profil zincirleriyle karşılaştırır ve ikisi için de çalışılmış örnekler yürütür.

Biçim ne olursa olsun, bu hız kontrolü uygulanır:

* **Throttle.** `throttle_rate` (mesaj/sn) gönderim hızını sınırlar — platform varsayılanı 50 msg/sn; açık bir 0 da varsayılan demektir.
* **Akıllı gönderim.** `send_time_optimization: "recipient-optimal"`, her alıcıyı etkileşim profillerinden sonraki en iyi zaman penceresine planlar ve teslimi sonraki 24 saate yayar. Önce `POST /campaigns/:id/preview-smart-send` ile önizleyin; örnek için kişi başına önerilen zamanları ve bir `next_best_channel` ipucu döndürür. Zamanlamanın kendisinin işe yarayıp yararmadığını ölçmek için `variables.smart_send_holdout_pct` ile alıcı başına hold-out kohortuna opting-in yapın — bkz. adım 7.
* **Kanal önizleme.** Kampanyanın kanalı hâlâ açıksa, `POST /messages/route-preview` ile bir alıcı örneği üzerinde doğrulayın — akıllı yönlendiricinin önerisi, yedek zinciri, mesaj başına maliyet ve etkileşim puanı; hiçbir şey gönderilmez. Zinciri gönderim için devreye almak isterseniz (böylece uç bir hata ilk kanalda durmak yerine basamaklar) aynı isteğe `cascade_policy` geçin — mesaj başına politika biçimini [akıllı gönderim yedek zincirleri rehberi](https://docs.orbit.devotel.io/guides/smart-send-fallback-chains.md) kapsar. [Akıllı rota önizleme rehberi](https://docs.orbit.devotel.io/guides/smart-route-preview.md) uç noktayı ve gönderim hattı desenini anlatır.
* **Gönderim penceresi.** `send_window: { start_local_hour, end_local_hour }`, yerel saati pencerenin dışına düşen alıcıları erteler — quiet hours'tan farklı olarak (olumsuz bir filtre) alıcı başına olumlu bir penceredir.

## 7. İzleyin ve ölçün

**Canlı istatistikler.** `GET /campaigns/:id/stats`, sent, delivered, failed, opened, clicked, replied toplamlarını döndürür. SDK'den bu, `orbit.request("GET", \`/campaigns/\${id}/stats\`)`çağrısıdır — tipli kaynak`send`'de durduğundan yine kaçış yolu. Daha ince kırılım için drip ve journey kampanyaları sırasıyla `/drip-analytics`, `/journey-analytics`ve`/journey/node-analytics\` sunar. Yeniden denemeler mesajlaşma yeniden deneme politikasını izler — yeniden denenebilir kodlu hatalar, politika tükenene dek yeniden kuyruklanır.

**Çıkış kriterleri.** Dönüşüm hedeflerini çıkış kriteri olarak bildirin (drip'lerde `exit_goals`): bir kişi hedefe ulaştığında (ör. `purchase_completed`), dizinin geri kalanını almak yerine diziden ayrılır. Çıkış kriterlerini kayıt anında doğrulayın; değerlendirici bunları çalışma anında zorunlu kılar.

**Holdout lift'i.** Kampanya bir holdout ayarladıysa (`variables` içinde `campaign_holdout_percent` veya A/B testlerinde `ab_holdout_percent`), `GET /campaigns/:id/holdout-lift` tedavi kohortunun kontrolle karşılaştırır ve Wald güven aralıklı bir dönüşüm oranı deltası döndürür — böylece mesajın hiçbir şey yapmamayı yenip yenmediğini, yalnızca hangi varyantın kazandığını değil görebilirsiniz. Journey'ler aynı veriyi `GET /campaigns/:id/journey/holdout-lift` altında sunar; akıllı gönderim `GET /campaigns/:id/smart-send-holdout-lift` altında.

**Akıllı gönderim hold-out'u (alıcı başına zamanlama).** Yukıdaki kampanya geneli holdout "göndermek hiç yardımcı oldu mu?" sorusunu yanıtlar — kontrol kohortu hiçbir mesaj almaz. Gönderim zamanı optimizasyonunun kendisini yalıtmak için, `recipient-optimal` bir kampanyada `variables.smart_send_holdout_pct` (0–50; 50 üstü değerler kırpılır) ayarlayın. Alıcının bu dilimi, herkes öngörülen en iyi zamanını alırken doğal optimizasyon öncesi takvimi korur; iki kol da kampanyayı almaya devam eder, bu yüzden karşılaştırma zamanlamayı yalıtır. Atama kişi başına deterministiktir (duraklat/sürdür ve yeniden başlatmalarda sabittir) ve kampanya geneli holdout ile ilişkisiz kendi tohumunu kullanır. Ayarsız veya 0, hold-out yok demektir. Sonucu `GET /campaigns/:id/smart-send-holdout-lift` ile okuyun; `configured`, `holdout_pct`, tıklanan dönüşüm sinyali üzerindeki birincil `lift` ve teslim/okundu/yanıtlandı üzerinden puanlanan bir `metrics` kırılımı döndürür — böylece bağlantısız kanallar (düz SMS, çoğu WhatsApp) bile gerçek bir sayı alır. Hold-out yapılandırılmamış bir kampanya, hata yerine 200 ile `configured: false` döndürür.

**ROI / ROAS.** `GET /campaigns/:id/roas`, atfedilen geliri (son dokunuş ve çoklu dokunuş kırılımları), tıklama hunisini ve holdout-artımlı geliri döndürür. `GET /campaigns/:id/roas/touchpoints` dokunuş başına katkıyı gösterir. Harcamayı mutabakatlamak ve ham satırları çekmek için `GET /campaigns/:id/cost` ve `/campaigns/:id/export` kullanın.

**Yinelenen ölçüm.** Zamanlanmış yinelenen kampanyalarda aynı istatistik uç noktaları her oluşum için geçerlidir; `GET /campaigns/stats` kampanyalar arasında toplulaştırır.

## 8. Kampanya webhook'larına abone olun

Bir uç nokta kaydedin (bkz. [webhook genel bakış](https://docs.orbit.devotel.io/webhooks/overview.md)) ve kendi CRM'inizi veya uyarılarınızı sürmek için `campaign.*` olaylarına abone olun:

* `campaign.created` / `campaign.updated` / `campaign.deleted`
* `campaign.started` / `campaign.paused` / `campaign.resumed` / `campaign.cancelled` / `campaign.completed`
* `campaign.drip_step.sent` / `campaign.drip_step.completed` / `campaign.drip.completed`

İmza doğrulama, yeniden denemeler ve dead letter için [dayanıklı webhook tüketicisi rehberi](https://docs.orbit.devotel.io/guides/webhook-consumer.md) tam deseni anlatır.

## 9. Sorun giderme

* **Hedef kitle sıfıra çözülüyor.** Hedef kitle önizlemesini `channel` geçerek yeniden çalıştırın; net projeksiyon, kitleyi hangi kohortun boşalttığını söyler (tümü suppressed, tümü opt-out, ulaşılabilir adres yok). Kampanyayı değil listeyi veya kanal adres kapsamasını düzeltin.
* **Dry-run kırmızı uyarılar gösteriyor.** `warnings[]` girdileri açıktır — "no provider registered", kanalın yapılandırılmış gönderim kimliği yok demektir; "quiet hours fully closed", çözümlenmiş pencerenin her yerel saati reddettiği demektir; "insufficient balance", `cost.sufficient: false` demektir. Uyarıyı temizleyin ve dry-run'ı yeniden çalıştırın.
* **Başlatma 402 veya bekleyen onay biçimi döndürüyor.** Bakiye kontrolü başarısız oldu veya onay iş akışı açık — ya cüzdanı doldurun ya da `POST /campaigns/approvals/:id/approve` bekleyin.
* **Journey kampanyası paused durumuna takıldı.** Bir kampanya, `credit_cap_usd_cents`'e ulaştığında veya bozuk bir drip adım koşulunda otomatik duraklar. `GET /campaigns/:id/stats` inceleyin, engelleyiciyi temizleyin, ardından `POST /campaigns/:id/resume`. Duraklatılmış journey'ler kayıt durumunu korur; sürdürmek, kaldıkları yerden devam eder.
* **Akıllı gönderim teslimleri fazla seyreltiyor.** `recipient-optimal`, gönderimleri bilinçli olarak 24 saate yayar. Tek parti gerekiyorsa `send_time_optimization: "fixed"` ayarlayın ve alıcılar saat dilimlerine yayılıyorsa `send_window` kullanın.

## Çalışılmış örnek: perakende promosyonu, taslaktan analize

Bir VIP listesine yaz indirimi SMS promosyonu; lift sayısının gerçek olması için holdout'lu.

1. **Taslağı oluşturun.**

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns" \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Retail promo — summer sale",
    "type": "blast",
    "channel": "sms",
    "audience_type": "list",
    "audience_id": "list_summerVIPs",
    "message_template": "Hi {{first_name}}, early access to our summer sale: 25% off through Sunday. Reply STOP to opt out.",
    "send_time_optimization": "recipient-optimal",
    "throttle_rate": 100,
    "variables": { "campaign_holdout_percent": 10 },
    "credit_cap_usd_cents": 50000
  }'
```

2. **Hedef kitleyi önizleyin.**

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/audience/preview" \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "audience_type": "list", "audience_id": "list_summerVIPs", "channel": "sms" }'
```

Sağlıklı bir `matching_count`, küçük bir `suppressed` + `opted_out` kohortu ve sıfır `unreachable` bekleyin.

3. **Dry-run çalıştırın.**

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/cmp_abc123/dry-run" \
  -H "X-API-Key: $ORBIT_API_KEY"
```

`audience.deliverable` (%10 holdout düşülmüş), `cost.sufficient: true` ve uyarı olmadığından emin olun.

4. **Akıllı gönderim zamanlarını önizleyin** (isteğe bağlı).

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/cmp_abc123/preview-smart-send" \
  -H "X-API-Key: $ORBIT_API_KEY"
```

5. **Başlatın.**

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/cmp_abc123/send" \
  -H "X-API-Key: $ORBIT_API_KEY"
```

6. **Yaşam döngüsü olaylarına abone olun** (`campaign.started`, `campaign.completed`) ve teslimler biriktikçe istatistikleri okuyun.

7. **Ölçün.** Gönderim tamamlandıktan sonra:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/campaigns/cmp_abc123/holdout-lift" \
  -H "X-API-Key: $ORBIT_API_KEY"
curl "https://api.orbit.devotel.io/api/v1/campaigns/cmp_abc123/roas" \
  -H "X-API-Key: $ORBIT_API_KEY"
```

Aynı sıra [Node SDK](https://docs.orbit.devotel.io/sdks/node.md) ile — create ve send için tipli yardımcı, geri kalanı için `orbit.request()` kaçış yolu:

```typescript theme={null}
import { Orbit } from "@devotel-orbit/node";

const orbit = new Orbit({ apiKey: process.env.ORBIT_API_KEY });

const campaign = await orbit.campaigns.create({
  name: "Retail promo — summer sale",
  channel: "sms",
  message_template:
    "Hi {{first_name}}, early access to our summer sale: 25% off through Sunday. Reply STOP to opt out.",
});
const id = campaign.data.id;

// Attach the audience plus the fields the typed helper doesn't carry
// (holdout percent, spend cap, throttle) via a partial update.
await orbit.request("PUT", `/campaigns/${id}`, {
  audience_type: "list",
  audience_id: "list_summerVIPs",
  type: "blast",
  send_time_optimization: "recipient-optimal",
  throttle_rate: 100,
  variables: { campaign_holdout_percent: 10 },
  credit_cap_usd_cents: 50000,
});

const preview = await orbit.request("POST", "/campaigns/audience/preview", {
  audience_type: "list",
  audience_id: "list_summerVIPs",
  channel: "sms",
});

const dryRun = await orbit.request("POST", `/campaigns/${id}/dry-run`);

// Launch — the typed helper auto-generates an idempotency key.
await orbit.campaigns.send(id);

const lift = await orbit.request("GET", `/campaigns/${id}/holdout-lift`);
const roas = await orbit.request("GET", `/campaigns/${id}/roas`);
```

Holdout-lift yanıtı, promosyon mesajının hiçbir şey yapmayan kontrolü yenip yenmediğini söyler (veya yenmediğini); ROAS raporu geliri dokunuş başına atfeder. Kazananı ya sonraki kampanyaya katlayın ya da şablonu gözden geçirip bu sırayı yeniden çalıştırın.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.