Payment Orchestrator
Subscription
Planlar

Planlar

Plan, bir ürünü müşterinin abone olabileceği bir şeye dönüştürür: bir fiyat, bir para birimi, opsiyonel bir deneme süresi ve motora her faturanın ne zaman üretileceğini söyleyen bir billing kuralı. Başarısızlık senaryosu da planın sorumluluğundadır — başarısız çekimin kaç kez yeniden deneneceği (maxDunningAttempts), hangi günlerde deneneceği (dunningScheduleDays) ve tahsilat kovalanırken müşterinin erişimi ne kadar koruyacağı (gracePeriodDays).

price minor-unit (kuruş) integer'dır: "price": 49900 = ₺499,00.

Endpoint'ler

Hepsi Bearer ile doğrulanır (at_live_…); listeler cursor pagination kullanır (pageSize, pageToken; productId / includeArchived ile filtre).

MethodPathNe yapar
POST/api/v1/subscriptions/plansPlan oluşturur
GET/api/v1/subscriptions/plansListeler (productId, includeArchived filtreleri)
GET/api/v1/subscriptions/plans/:idTek planı getirir
PATCH/api/v1/subscriptions/plans/:idGünceller
DELETE/api/v1/subscriptions/plans/:idArşivler (soft delete)
GET/api/v1/subscriptions/plans/:id/translationsÇevirileri listeler
PATCH/api/v1/subscriptions/plans/:id/translations/:localeÇeviri oluşturur veya günceller

Plan oluşturma

curl -X POST https://api-gateway.lunixi.com/api/v1/subscriptions/plans \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "prd_4b2e88",
    "code": "pro-monthly",
    "name": "Pro Aylık",
    "price": 49900,
    "currency": "TRY",
    "trialPeriodDays": 7,
    "billing": {
      "frequency": "MONTHLY",
      "interval": 1,
      "byMonthDay": [15],
      "timezone": "Europe/Istanbul",
      "lastDayOfMonthFix": true
    },
    "maxDunningAttempts": 3,
    "dunningScheduleDays": [1, 3, 7],
    "gracePeriodDays": 7
  }'

Alanlar

AlanTipNot
productIdstring, zorunluBu planın fiyatlandırdığı ürün.
codestring, zorunluSizin sabit kimliğiniz (örn. pro-monthly), merchant başına benzersiz.
namestring, zorunluMüşteriye görünen ad (temel locale).
descriptionstringMüşteriye görünen açıklama.
priceinteger, zorunluMinor unit. 49900 = ₺499,00.
currencystring, zorunluISO kodu, örn. TRY.
trialPeriodDaysinteger ≥ 0Ücretsiz deneme süresi; abonelik trial'da başlar ve otomatik dönüşür. 0/gönderilmezse deneme yok.
billingobject, zorunluBilling kuralı — aşağıda.
maxDunningAttemptsinteger 0–10Başarısız çekimden sonra faturadan vazgeçilmeden önce kaç deneme yapılacağı.
dunningScheduleDaysinteger[]Denemelerin çalışacağı, başarısızlıktan sonraki günler — [1, 3, 7] 1., 3. ve 7. günde dener.
gracePeriodDaysinteger ≥ 0Dunning sürerken aboneliğin erişimi ne kadar koruyacağı.
metadataobjectSerbest key/value deposu.

Billing kuralı

billing nesnesi bir tekrarlama kuralıdır — RRULE ile aynı yapı taşları:

AlanTipAnlamı
frequencyDAILY | WEEKLY | MONTHLY | YEARLY, zorunluTemel ritim.
intervalinteger 1–365, zorunluHer N frekans biriminde bir — frequency: MONTHLY, interval: 3 üç ayda bir faturalar.
byMonthDayinteger[]Faturalamayı ayın belirli günlerine sabitler, örn. [15].
byWeekDaystring[]Haftalık ritimler için: ["MO", "WE", "FR"].
timezonestring, zorunluKuralın değerlendirildiği IANA saat dilimi, örn. Europe/Istanbul. "Ayın 15'inde" demek bu dilimde 15'i demektir.
lastDayOfMonthFixboolean, zorunlutrue iken 31'ine sabitlenmiş bir döngü, kısa aylarda ayı atlamak yerine ayın son gününde faturalar.
countinteger ≥ 1Toplam tekrar sayısı; süresiz abonelik için göndermeyin (null).

Hazır tarifler:

{ "frequency": "MONTHLY", "interval": 1,  "timezone": "Europe/Istanbul", "lastDayOfMonthFix": true }          // klasik aylık
{ "frequency": "MONTHLY", "interval": 3,  "byMonthDay": [1], "timezone": "Europe/Istanbul", "lastDayOfMonthFix": true }  // üç ayda bir, ayın 1'inde
{ "frequency": "WEEKLY",  "interval": 1,  "byWeekDay": ["MO"], "timezone": "Europe/Istanbul", "lastDayOfMonthFix": false } // her pazartesi
{ "frequency": "YEARLY",  "interval": 1,  "timezone": "Europe/Istanbul", "lastDayOfMonthFix": true, "count": 3 }          // 3 yıllık çekim, sonra biter

Güncelleme & arşivleme

PATCH /api/v1/subscriptions/plans/:id; name, description, price, trialPeriodDays, billing, dunning alanları ve metadata'yı (artı audit için reason) günceller. Bir fiyat güncellemesinin mevcut abonelere ulaşıp ulaşmayacağı ve ne zaman ulaşacağı ürün/abonelik fiyat politikasınca belirlenir (LOCKED / FOLLOW_PLAN, IMMEDIATE / NEXT_PERIOD) — bkz. Ürünler.

DELETE /api/v1/subscriptions/plans/:id planı arşivler: artık abone olunamaz ve public katalogdan çıkar; ancak üzerindeki mevcut abonelikler normal faturalanmaya devam eder.

curl -X DELETE https://api-gateway.lunixi.com/api/v1/subscriptions/plans/pln_9f3a1c \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{ "reason": "pro-monthly-v2 ile değiştirildi" }'

Çeviriler & vitrin metinleri

Plan name / description alanları tıpkı ürünlerdeki gibi yerelleşir — PATCH …/plans/:id/translations/:locale ve { "name": …, "description": … }; locale geçilen her yerde (public catalog, portal) otomatik sunulur.

Pricing sayfanızda planın altındaki pazarlama maddeleri — "500 işlem / ay", "Öncelikli destek" — planın vitrin özellikleridir: sıralı, locale bazlı görüntüleme metinleri; merchant panelinden yönetilir ve Public Catalog API'de planla birlikte döner. Bunlar yalnızca sunumdur; zorlanabilir kotalar Özellikler & entitlement tarafında yaşar.

Yanıt

{
  "id": "pln_9f3a1c",
  "productId": "prd_4b2e88",
  "code": "pro-monthly",
  "name": "Pro Aylık",
  "price": 49900,
  "currency": "TRY",
  "trialPeriodDays": 7,
  "billing": {
    "frequency": "MONTHLY",
    "interval": 1,
    "byMonthDay": [15],
    "timezone": "Europe/Istanbul",
    "lastDayOfMonthFix": true
  },
  "maxDunningAttempts": 3,
  "dunningScheduleDays": [1, 3, 7],
  "gracePeriodDays": 7,
  "isActive": true,
  "createdAt": "2026-07-06T09:31:00Z"
}

Plan değişikliği

Mevcut bir aboneyi başka plana taşımak planın değil aboneliğin işlemidir: POST /api/v1/subscriptions/subscriptions/:id/change-plan, behavior: "IMMEDIATE" (hemen geçir ve mahsuplaş) veya "NEXT_PERIOD" (dönem sınırına planla) ile. Upgrade, downgrade ve ürettikleri event'ler Abonelikler sayfasında anlatılır.

Hatalar

DurumAnlamıNe yapmalı
400Doğrulama hatası (negatif price, 1–365 dışında interval, 10'dan büyük maxDunningAttempts, boş dunningScheduleDays)İşaretlenen alanları düzeltin.
401Eksik veya geçersiz API keyAuthorization: Bearer at_live_… gönderin.
404productId veya plan bulunamadıÖnce ürünü oluşturun; id'yi kontrol edin.
409Mükerrer plan code'uKodlar merchant başına benzersizdir.

Webhook'lar

EventNe zaman
plan.createdPlan oluşturuldu.
plan.updatedAlanlar, fiyat veya çeviriler değişti.
plan.archivedPlan DELETE ile arşivlendi.

Sonraki adımlar

  • Abonelikler — müşteri abone etme, iptal, duraklatma, plan değişikliği
  • Ürünler — fiyat-değişikliği politikası ve katalog çevirileri
  • Pricing & Portal SDK — bu planları kendi pricing sayfanızda gösterin
  • Faturalar — billing kuralının her dönem ürettiği şey