# Lisans Transferi

https://dev.wisecp.com/tr/lisans-transferi

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.

feeobject 3 alanDevir ücreti.

typestring`percentage` 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 JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/services/506/license-transfers', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$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);
```

```php
// 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.

feeobject 3 alanDevir ücreti.

typestring`percentage` 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[] 7 alanİ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 JavaScript PHP (HTTP) PHP (Dahili)

```bash
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}'
```

```javascript
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();
```

```php
$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);
```

```php
// 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 201 422

```json
{
  "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": "john@example.com",
        "verified": false,
        "verified_at": null,
        "sent_at": "2026-06-21 12:00:00",
        "last_resent_at": null,
        "resend_count": 0
      },
      {
        "party": "transferee",
        "email": "jane@example.com",
        "verified": false,
        "verified_at": null,
        "sent_at": "2026-06-21 12:00:00",
        "last_resent_at": null,
        "resend_count": 0
      }
    ]
  }
}
```

```json
{
  "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.

feeobject 3 alanDevir ücreti.

typestring`percentage` 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[] 7 alanİ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 JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
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();
```

```php
$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);
```

```php
// 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 JavaScript PHP (HTTP) PHP (Dahili)

```bash
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}'
```

```javascript
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();
```

```php
$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);
```

```php
// 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 JavaScript PHP (HTTP) PHP (Dahili)

```bash
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"}'
```

```javascript
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();
```

```php
$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);
```

```php
// 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 JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X POST 'https://panel.ornek.com/api/v1/admin/services/506/license-transfers/7/remind-invoice' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
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();
```

```php
$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);
```

```php
// 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.

## İlgili Makaleler

- [Sahiplik Transferi](https://dev.wisecp.com/tr/sahiplik-transferi)
- [Hizmet Uçları](https://dev.wisecp.com/tr/hizmet-uclari)
