# Token yenileme

> Refresh token ile yeni bir token çifti üretir.

- **İstek:** `POST https://ext-api.netgsm.com.tr/auth/v3/token/refresh`
- **Canlı ortam:** `https://ext-api.netgsm.com.tr/auth/v3`
- **Sandbox:** `https://ext-sandbox.netgsm.com.tr/auth/v3`
- **Kimlik doğrulama:** gerekmez
- **HTML sayfası:** https://api-docs.netgsm.com.tr/auth/refresh-token/
- **OpenAPI tanımı:** https://api-docs.netgsm.com.tr/openapi/auth-v3.yaml (operationId: `refreshToken`)

## Açıklama

Refresh token ile yeni bir token çifti üretir. Kullanıcı adı ve şifre yeniden istenmez.

- Yenilemeden sonra önceki access token geçersiz olur; oturum başına tek geçerli access
  token vardır.
- `refresh_token` değeri aynı kalabilir; yine de her zaman yanıttaki `access_token` ve
  `refresh_token` değerlerini saklamalısınız.
- Token'ın kapsamı yenilemede değişmez.
- Oturum sonlandırıldıysa refresh token da geçersizdir (`401` `invalid_refresh_token`).

**Limit:** IP başına dakikada 60 istek.

## İstek

### Gövde (`application/json`, zorunlu)

- `refresh_token` (string, uuid, zorunlu): Token alma ya da son yenileme yanıtındaki refresh token. UUID değilse `401` `invalid_refresh_token` döner. Örnek: `a170696c-8c1f-4eb5-81bd-391e29fbebc4`.

Örnek gövde:

```json
{
  "refresh_token": "a170696c-8c1f-4eb5-81bd-391e29fbebc4"
}
```

### Gövde (`application/x-www-form-urlencoded`, zorunlu)

- `refresh_token` (string, uuid, zorunlu): Token alma ya da son yenileme yanıtındaki refresh token. UUID değilse `401` `invalid_refresh_token` döner. Örnek: `a170696c-8c1f-4eb5-81bd-391e29fbebc4`.

Örnek gövde (şemadan üretildi):

```json
{
  "refresh_token": "a170696c-8c1f-4eb5-81bd-391e29fbebc4"
}
```

## Örnek istek

```bash
curl -X POST 'https://ext-api.netgsm.com.tr/auth/v3/token/refresh' \
  -H 'Content-Type: application/json' \
  -d '{
  "refresh_token": "a170696c-8c1f-4eb5-81bd-391e29fbebc4"
}'
```

## Yanıtlar

### 200 — Token verildi.

Başlıklar:

- `Cache-Control` (string): Her zaman `no-store`.
- `Pragma` (string): Her zaman `no-cache`.
- `RateLimit-Limit` (integer): Penceredeki istek hakkı.
- `RateLimit-Remaining` (integer): Penceredeki kalan hak.
- `RateLimit-Reset` (integer): Pencerenin sıfırlanmasına kalan saniye.
- `RateLimit-Policy` (string): Limit politikası; `30;w=60` 60 saniyede 30 istek demektir.

Gövde (`application/json`):

- `access_token` (string, zorunlu): JWT. Korunan uçlarda `Authorization: Bearer <access_token>` olarak gönderilir. Örnek: `eyJhbGciOiJIUzI1NiJ9...`.
- `token_type` (string, zorunlu): Her zaman `Bearer`. Değerler: `Bearer`.
- `expires_in` (integer, zorunlu): Access token'ın geçerlilik süresi (saniye). Örnek: `86400`.
- `refresh_token` (string, uuid, zorunlu): Token yenilemek için kullanılır. Örnek: `a170696c-8c1f-4eb5-81bd-391e29fbebc4`.
- `scope` (string, zorunlu): Token'ın verilen kapsamları, boşlukla ayrılmış. İstenenden farklı olabilir (bkz. Scope). Örnek: `sms`.
- `user_id` (integer, int64, zorunlu): Hesap kimliği. Örnek: `100001`.
- `sub_user_id` (integer, int64, zorunlu): Alt kullanıcı kimliği; ana hesapla girişte `0`. Örnek: `0`.

Örnek:

```json
{
  "access_token": "eyJhbGciOiJIUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "a170696c-8c1f-4eb5-81bd-391e29fbebc4",
  "scope": "sms",
  "user_id": 100001,
  "sub_user_id": 0
}
```

### 400 — invalid_request. İstek işlenemedi.

Gövde (`application/problem+json`):

- `type` (string, zorunlu): Hata tipinin URI tanımlayıcısı. Örnek: `urn:problem-type:identity:invalid-credentials`.
- `title` (string, zorunlu): Hata tipinin kısa özeti. Örnek: `Kimlik doğrulanamadı`.
- `status` (integer, zorunlu): HTTP durum kodu. Örnek: `401`.
- `detail` (string, zorunlu): Son kullanıcıya gösterilebilir açıklama (Türkçe). Örnek: `Kullanıcı adı veya şifre hatalı.`.
- `instance` (string, zorunlu): İstek yolu. Örnek: `/auth/v3/token`.
- `code` (string, zorunlu): Değerler: `invalid_request`.
- `request_id` (string, zorunlu): Destek talebinde iletilecek istek kimliği; `X-Thread-Id` yanıt başlığıyla aynıdır. Örnek: `c7e54ee8-b831-427b-a5a5-af6b66cabbd0`.
- `error` (string, isteğe bağlı): OAuth 2.0 hata kodu (RFC 6749 §5.2 / RFC 6750 §3.1), OAuth istemci kütüphaneleri için. Değerler: `invalid_grant`, `invalid_token`, `invalid_scope`, `access_denied`, `invalid_request`, `temporarily_unavailable`, `server_error`.
- `error_description` (string, isteğe bağlı): OAuth 2.0 hata açıklaması (İngilizce).
- `errors` (object, isteğe bağlı): Yalnızca `422`. Alan adı → mesaj listesi.
- `errors.<anahtar>` (array<string>, isteğe bağlı)
- `denied_scopes` (array<string>, isteğe bağlı): Yalnızca `service_not_activated` ve `sub_user_not_permitted`. Token verilmesini engelleyen kapsamlar.
- `retry_after` (integer, isteğe bağlı): Yalnızca `429`. Tekrar denemeden önce beklenecek süre (saniye).

Örnek (şemadan üretildi):

```json
{
  "type": "urn:problem-type:identity:invalid-credentials",
  "title": "Kimlik doğrulanamadı",
  "status": 401,
  "detail": "Kullanıcı adı veya şifre hatalı.",
  "instance": "/auth/v3/token",
  "code": "invalid_request",
  "request_id": "c7e54ee8-b831-427b-a5a5-af6b66cabbd0",
  "error": "invalid_grant",
  "error_description": "string",
  "errors": {},
  "denied_scopes": [
    "string"
  ],
  "retry_after": 0
}
```

### 401 — invalid_refresh_token. Refresh token geçersiz, UUID değil, süresi dolmuş ya da oturum sonlandırılmış. Kullanıcının yeniden giriş yapması (`POST /token`) gerekir.

Başlıklar:

- `WWW-Authenticate` (string): `Bearer`.

Gövde (`application/problem+json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `invalid_refresh_token`.

Örnek:

```json
{
  "type": "urn:problem-type:identity:invalid-refresh-token",
  "title": "Refresh token geçersiz",
  "status": 401,
  "detail": "Oturum süresi dolmuş veya sonlandırılmış. Lütfen yeniden giriş yapın.",
  "instance": "/auth/v3/token/refresh",
  "code": "invalid_refresh_token",
  "error": "invalid_grant",
  "request_id": "c7e54ee8-b831-427b-a5a5-af6b66cabbd0"
}
```

### 403 — Hesap kontrolleri yenilemede de yapılır; token alındıktan sonra değişen bir durum (örneğin IP izni ya da hesabın aktifliği) yenilemeyi reddeder. `code` token almadaki hesap kodlarından biridir.

| Kod | Ne zaman |
|---|---|
| `login_not_permitted` | Bu hesapla giriş yapılamıyor. |
| `api_access_denied` | Hesabın API erişimi yok. |
| `ip_not_allowed` | Bu IP adresinden erişim izni yok. |
| `country_not_allowed` | Hesabın yurt dışından erişim izni yok. |
| `account_inactive` | Hesap aktif değil. |
| `service_not_activated` | Token'ın kapsamındaki hizmet artık hesapta aktif değil; `denied_scopes` ilgili kapsamları listeler. |
| `sub_user_not_permitted` | Alt kullanıcının token'ın kapsamındaki hizmete yetkisi artık yok; `denied_scopes` ilgili kapsamları listeler. |

Gövde (`application/problem+json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `login_not_permitted`, `api_access_denied`, `ip_not_allowed`, `country_not_allowed`, `account_inactive`, `service_not_activated`, `sub_user_not_permitted`.

Örnek:

```json
{
  "type": "urn:problem-type:identity:ip-not-allowed",
  "title": "IP adresine izin yok",
  "status": 403,
  "detail": "Bu IP adresinden erişim izni bulunmuyor.",
  "instance": "/auth/v3/token/refresh",
  "code": "ip_not_allowed",
  "error": "access_denied",
  "request_id": "c7e54ee8-b831-427b-a5a5-af6b66cabbd0"
}
```

### 422 — validation_failed. Girdi eksik ya da hatalı; `errors` her alan için mesajları listeler. Alanlar query string'de gönderildiğinde de bu hata döner.

Gövde (`application/problem+json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `validation_failed`.

Örnek:

```json
{
  "type": "urn:problem-type:identity:validation-failed",
  "title": "Doğrulama hatası",
  "status": 422,
  "detail": "Girilen bilgiler eksik veya hatalı.",
  "instance": "/auth/v3/token",
  "code": "validation_failed",
  "error": "invalid_request",
  "errors": {
    "username": [
      "Kullanıcı adı alanı zorunludur."
    ],
    "password": [
      "Şifre alanı zorunludur."
    ]
  },
  "request_id": "c7e54ee8-b831-427b-a5a5-af6b66cabbd0"
}
```

### 429 — rate_limited. IP başına dakikada 60 istek aşıldı.

Başlıklar:

- `Retry-After` (integer): Tekrar denemeden önce beklenecek süre (saniye).

Gövde (`application/problem+json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `rate_limited`.

Örnek:

```json
{
  "type": "urn:problem-type:identity:rate-limited",
  "title": "İstek limiti aşıldı",
  "status": 429,
  "detail": "Çok fazla istek gönderildi. Lütfen daha sonra tekrar deneyin.",
  "instance": "/auth/v3/token/refresh",
  "code": "rate_limited",
  "error": "temporarily_unavailable",
  "retry_after": 42,
  "request_id": "c7e54ee8-b831-427b-a5a5-af6b66cabbd0"
}
```

### 502 — service_misconfigured. Sunucu tarafı yapılandırma hatası; kimlik doğrulama servisi isteği şu an işleyemiyor.

Gövde (`application/problem+json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `service_misconfigured`.

Örnek (şemadan üretildi):

```json
{
  "type": "urn:problem-type:identity:invalid-credentials",
  "title": "Kimlik doğrulanamadı",
  "status": 401,
  "detail": "Kullanıcı adı veya şifre hatalı.",
  "instance": "/auth/v3/token",
  "code": "service_misconfigured",
  "request_id": "c7e54ee8-b831-427b-a5a5-af6b66cabbd0",
  "error": "invalid_grant",
  "error_description": "string",
  "errors": {},
  "denied_scopes": [
    "string"
  ],
  "retry_after": 0
}
```

### 503 — service_unavailable. Kimlik doğrulama altyapısına şu an ulaşılamıyor; isteği biraz sonra tekrar gönderebilirsiniz. Servis geçici olarak istek almayı durdurduysa `Retry-After` beklenecek süreyi verir.

Başlıklar:

- `Retry-After` (integer): Tekrar denemeden önce beklenecek süre (saniye).

Gövde (`application/problem+json`): alanlar 400 yanıtıyla aynı; farklı olanlar:

- `code` (string, zorunlu): Değerler: `service_unavailable`.

Örnek (şemadan üretildi):

```json
{
  "type": "urn:problem-type:identity:invalid-credentials",
  "title": "Kimlik doğrulanamadı",
  "status": 401,
  "detail": "Kullanıcı adı veya şifre hatalı.",
  "instance": "/auth/v3/token",
  "code": "service_unavailable",
  "request_id": "c7e54ee8-b831-427b-a5a5-af6b66cabbd0",
  "error": "invalid_grant",
  "error_description": "string",
  "errors": {},
  "denied_scopes": [
    "string"
  ],
  "retry_after": 0
}
```
