Lisans Transferi

1.6k görüntülenme Markdown

Bir hizmetin lisansını başka bir müşteriye devreden altı uç: başlatma, onay takibi, hatırlatma ve iptal.

Genel Bakış

Lisans devri, bir hizmetin lisansını başka bir müşteriye geçirir. Bu altı uç devir kaydını yönetir: başlatır, izler, hatırlatır ve gerekirse iptal eder.

Akış tek adımda bitmez. Başlatma yalnız kaydı açar; devreden ve devralan e-posta ile onaylar, ücret varsa faturası ödenir, ancak ondan sonra lisans el değiştirir. Devrin şu an neyi beklediğini detaydaki onay durumundan okursunuz.

Bu hizmet sahipliği devri değildir. Bir hizmetin sahibini değiştirmek ayrı bir sistemdir ve kendi uçları vardır.

Referans

Devirleri Listeleme

get/api/v1/admin/services/{id}/license-transfers
Services/GetServiceLicenseTransfers admin

Hizmetin devir geçmişini döndürür, en yenisi başta.

Dönen alanlar data[] — 17
idintDevrin kimliği.
service_idintDevredilen hizmetin kimliği.
product_idintÜrünün kimliği.
transferor_idintDevreden müşterinin kimliği.
transferee_idintDevralan müşterinin kimliği.
statusstringDevrin durumu. Doğrulama beklenirken, tamamlandığında ve iptal edildiğinde farklı değerler alır.
feeobjectDevir ücreti.
typestringpercentage yüzde, fixed sabit tutar.
amountfloatÜcretin değeri.
currency_idintPara birimi kimliği.
invoice_idintÜcret faturasının kimliği. Fatura üretilmediyse sıfır.
invoice_recipientstringFaturanın kime kesildiği: devreden ya da devralan.
notify_partiesboolTarafların bilgilendirilip bilgilendirilmediği.
notesstringYönetici notu.
expires_atstringDevrin geçerliliğini yitireceği zaman. O zamana kadar iki taraf da onaylamazsa devir düşer.
initiated_atstringBaşlatılma zamanı.
completed_atstring | nullTamamlanma zamanı.
cancelled_atstring | nullİptal zamanı.
cancel_reasonstring | nullİptal gerekçesi.
created_atstringKaydın oluşturulma zamanı.
Hatalar 2
not_found404Hizmet bulunamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.ornek.com/api/v1/admin/services/506/license-transfers', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/services/506/license-transfers');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Liste onay durumunu TASIMAZ; onu gormek icin tek devrin detayini okuyun.
$transfers = Api::Services()->GetServiceLicenseTransfers(['id' => 506])['data'];

Devir Başlatma

post/api/v1/admin/services/{id}/license-transfers
Services/CreateServiceLicenseTransfer admin 201

Yeni bir devir açar, iki tarafa da doğrulama gönderir ve ücret varsa faturasını üretir.

Gövde 3
transferee_idintzorunluLisansı devralacak müşterinin kimliği.
notesstringYönetici notu.
notify_partiesboolTarafları bilgilendirir. Varsayılan açık.
Dönen alanlar data — 18
idintDevrin kimliği.
service_idintDevredilen hizmetin kimliği.
product_idintÜrünün kimliği.
transferor_idintDevreden müşterinin kimliği.
transferee_idintDevralan müşterinin kimliği.
statusstringDevrin durumu. Doğrulama beklenirken, tamamlandığında ve iptal edildiğinde farklı değerler alır.
feeobjectDevir ücreti.
typestringpercentage yüzde, fixed sabit tutar.
amountfloatÜcretin değeri.
currency_idintPara birimi kimliği.
invoice_idintÜcret faturasının kimliği. Fatura üretilmediyse sıfır.
invoice_recipientstringFaturanın kime kesildiği: devreden ya da devralan.
notify_partiesboolTarafların bilgilendirilip bilgilendirilmediği.
notesstringYönetici notu.
expires_atstringDevrin geçerliliğini yitireceği zaman. O zamana kadar iki taraf da onaylamazsa devir düşer.
initiated_atstringBaşlatılma zamanı.
completed_atstring | nullTamamlanma zamanı.
cancelled_atstring | nullİptal zamanı.
cancel_reasonstring | nullİptal gerekçesi.
created_atstringKaydın oluşturulma zamanı.
verificationsobject[]İki tarafın onay durumu.
partystringHangi taraf: transferor devreden, transferee devralan.
emailstringDoğrulamanın gönderildiği adres.
verifiedboolBu taraf onayladı mı.
verified_atstring | nullOnay zamanı.
sent_atstringİlk gönderim zamanı.
last_resent_atstring | nullSon yeniden gönderim zamanı.
resend_countintKaç kez yeniden gönderildiği.
Hatalar 4
not_found404Hizmet bulunamadı.
transferee_required422Devralan müşteri verilmedi.
transfer_not_allowed422Devir başlatılamıyor. Lisans devri eklentisi kurulu olmayabilir, üründe devir kapalı olabilir, hizmette zaten açık bir devir olabilir ya da hizmet uygunluk şartlarını taşımıyor olabilir.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X POST 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"transferee_id":88,"notes":"sold","notify_parties":true}'
const res = await fetch('https://panel.ornek.com/api/v1/admin/services/506/license-transfers', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    transferee_id: 88,
    notes: 'sold',
    notify_parties: true,
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/services/506/license-transfers');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'transferee_id' => 88,
        'notes'         => 'sold',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Baslatmak devri TAMAMLAMAZ: iki taraf da e-postayla onaylayana kadar lisans yerinde kalir.
$transfer = Api::Services()->CreateServiceLicenseTransfer([
    'id'            => 506,
    'transferee_id' => 88,
])['data'];

$waiting = array_filter($transfer['verifications'], fn (array $v): bool => !$v['verified']);
Yanıt
{
  "data": {
    "id": 7,
    "service_id": 506,
    "transferor_id": 50,
    "transferee_id": 88,
    "status": "pending_verification",
    "fee": { "type": "percentage", "amount": 5.0, "currency_id": 840 },
    "invoice_id": 0,
    "invoice_recipient": "transferee",
    "expires_at": "2026-06-28 12:00:00",
    "verifications": [
      {
        "party": "transferor",
        "email": "[email protected]",
        "verified": false,
        "verified_at": null,
        "sent_at": "2026-06-21 12:00:00",
        "last_resent_at": null,
        "resend_count": 0
      },
      {
        "party": "transferee",
        "email": "[email protected]",
        "verified": false,
        "verified_at": null,
        "sent_at": "2026-06-21 12:00:00",
        "last_resent_at": null,
        "resend_count": 0
      }
    ]
  }
}
{
  "error": {
    "code": "transfer_not_allowed",
    "message": "License transfer is not enabled for this product."
  }
}

Devir Detayı

get/api/v1/admin/services/{id}/license-transfers/{tid}
Services/GetServiceLicenseTransfer admin onaylar dahil

Tek bir devri, iki tarafın onay durumuyla birlikte döndürür.

Dönen alanlar data — 18
idintDevrin kimliği.
service_idintDevredilen hizmetin kimliği.
product_idintÜrünün kimliği.
transferor_idintDevreden müşterinin kimliği.
transferee_idintDevralan müşterinin kimliği.
statusstringDevrin durumu. Doğrulama beklenirken, tamamlandığında ve iptal edildiğinde farklı değerler alır.
feeobjectDevir ücreti.
typestringpercentage yüzde, fixed sabit tutar.
amountfloatÜcretin değeri.
currency_idintPara birimi kimliği.
invoice_idintÜcret faturasının kimliği. Fatura üretilmediyse sıfır.
invoice_recipientstringFaturanın kime kesildiği: devreden ya da devralan.
notify_partiesboolTarafların bilgilendirilip bilgilendirilmediği.
notesstringYönetici notu.
expires_atstringDevrin geçerliliğini yitireceği zaman. O zamana kadar iki taraf da onaylamazsa devir düşer.
initiated_atstringBaşlatılma zamanı.
completed_atstring | nullTamamlanma zamanı.
cancelled_atstring | nullİptal zamanı.
cancel_reasonstring | nullİptal gerekçesi.
created_atstringKaydın oluşturulma zamanı.
verificationsobject[]İki tarafın onay durumu.
partystringHangi taraf: transferor devreden, transferee devralan.
emailstringDoğrulamanın gönderildiği adres.
verifiedboolBu taraf onayladı mı.
verified_atstring | nullOnay zamanı.
sent_atstringİlk gönderim zamanı.
last_resent_atstring | nullSon yeniden gönderim zamanı.
resend_countintKaç kez yeniden gönderildiği.
Hatalar 2
not_found404Hizmet ya da devir bulunamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Devrin neyi bekledigini burada gorursunuz: onay mi, odeme mi.
$transfer = Api::Services()->GetServiceLicenseTransfer(['id' => 506, 'tid' => 7])['data'];

$allConfirmed = !array_filter($transfer['verifications'], fn (array $v): bool => !$v['verified']);
$feeUnpaid    = $transfer['invoice_id'] > 0;

Devri İptal Etme

delete/api/v1/admin/services/{id}/license-transfers/{tid}
Services/CancelServiceLicenseTransfer admin fatura da iptal olur

Süren bir devri durdurur ve bağlı ödenmemiş ücret faturasını iptal eder.

Gövde 1
notify_partiesboolTarafları bilgilendirir. Varsayılan açık.
Dönen alanlar data — 2
cancelledboolİptal başarılı mı.
idintDevrin kimliği.
Hatalar 4
not_found404Hizmet ya da devir bulunamadı.
not_active422Devir iptal edilebilir durumda değil. Tamamlanmış ya da zaten iptal edilmiş olabilir.
cancel_failed500Devir iptal edilemedi.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"notify_parties":true}'
const res = await fetch('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ notify_parties: true }),
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['notify_parties' => true]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Tamamlanmis bir devir iptal EDILEMEZ: sahiplik geri almak icin ters yonde yeni devir gerekir.
$response = Api::Services()->CancelServiceLicenseTransfer(['id' => 506, 'tid' => 7]);

Doğrulamayı Yeniden Gönderme

post/api/v1/admin/services/{id}/license-transfers/{tid}/resend
Services/ResendServiceLicenseTransferVerification admin

Onay bekleyen tarafa doğrulama e-postasını yeniden gönderir.

Gövde 1
partystringHedef taraf: transferor, transferee ya da ikisi birden. Varsayılan ikisi birden.
Dönen alanlar data — 2
resentarrayGerçekten gönderim yapılan taraflar. Onaylamış taraf listede olmaz.
idintDevrin kimliği.
Hatalar 4
not_found404Hizmet ya da devir bulunamadı.
invalid_party422Taraf üç değerden biri değil.
resend_failed422Gönderilecek doğrulama yok. İki taraf da onaylamış ya da devir doğrulama aşamasında değil.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X POST 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7/resend' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"party":"both"}'
const res = await fetch('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7/resend', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ party: 'both' }),
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7/resend');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['party' => 'both']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Iki tarafi da istemek zararsizdir: onaylamis olan atlanir, donen liste kime gittigini soyler.
$response = Api::Services()->ResendServiceLicenseTransferVerification([
    'id'    => 506,
    'tid'   => 7,
    'party' => 'both',
]);

$sentTo = $response['data']['resent'];

Ücret Faturasını Hatırlatma

post/api/v1/admin/services/{id}/license-transfers/{tid}/remind-invoice
Services/RemindServiceLicenseTransferInvoice admin

Devir ücreti faturası için hatırlatma gönderir. Müşteriye ulaşamazsa hiçbir şey kaydetmez ve durum kodu yine 200 olur.

Gövde —
——Gövde gerekmez, boş gönderin. Hizmeti ve devri adres belirler; alıcı da devrin fatura alıcısı alanının gösterdiği taraftır, başka bir yere yönlendirecek alan yok.
Dönen alanlar data — 5
remindedboolHatırlatma müşteri tarafına ulaştıysa true: fatura sahibi, ek iletişim adresi ya da alt kullanıcı, gönderildi ya da kuyrukta. Yalnız personele giden kopya sayılmaz.
idintDevrin kimliği.
invoice_idintHatırlatılan faturanın kimliği.
reasonstringYalnız reminded false iken: disabled, blocked, opted_out, client_side_off, send_failed ya da no_recipients.
messagestringYalnız reminded false iken: reason'ın İngilizce açıklaması.
Hatalar 3
not_found404Hizmet ya da devir bulunamadı.
invoice_not_generated422Bu devir için ücret faturası üretilmemiş. Ücretsiz devirlerde fatura hiç oluşmaz.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X POST 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7/remind-invoice' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7/remind-invoice', {
  method: 'POST',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7/remind-invoice');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Hatirlatma faturanin MUHATABINA gider; muhatap devreden de olabilir devralan da.
$transfer = Api::Services()->GetServiceLicenseTransfer(['id' => 506, 'tid' => 7])['data'];

if ($transfer['invoice_id'] > 0) {
    Api::Services()->RemindServiceLicenseTransferInvoice(['id' => 506, 'tid' => 7]);
}

Tuzaklar

Başlatmak devri tamamlamaz

Başlatma isteği 201 döndürse bile lisans hâlâ eski sahibindedir. Devrin yürümesi için iki tarafın da e-postayla onaylaması ve ücret varsa faturasının ödenmesi gerekir. Yanıttaki onay listesi kimin beklendiğini söyler.

Devrin bir son kullanma tarihi var

Kayıt bir geçerlilik süresi taşır. O tarihe kadar onaylar tamamlanmazsa devir kendiliğinden düşer ve lisans hiç el değiştirmez. Uzun süre bekleyen bir devirde iptal etmeden önce süresine bakın; zaten düşmüş olabilir.

Başlatma dört ayrı sebeple reddedilebilir

transfer_not_allowed tek bir kural değil, dört ayrı koşulu birden temsil eder: lisans devri eklentisi kurulu olmayabilir, üründe devir kapalı olabilir, hizmette zaten açık bir devir olabilir ya da hizmet uygunluk şartlarını taşımıyor olabilir. Hangi sebep olduğunu mesaj söyler; kodu tek başına okumak yanıltır.

Sahiplik devriyle karıştırmayın

Buradaki devir lisansı taşır ve kendi doğrulama ve ücret akışı vardır. Bir hizmetin sahibini değiştirmek, yani faturasını başka müşteriye kesmeye başlamak, bambaşka bir sistemdir ve kendi uçlarında yaşar.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.