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

# Authorization Code Akışı

> Kullanıcıyı yetkilendirme sayfasına yönlendirin, dönen code'u access token ile değişin.

Authorization Code akışı iki HTTP adımından oluşur: kullanıcının tarayıcısında yetkilendirme, sunucunuzda token değişimi.

## Adım 1 — Kullanıcıyı yetkilendirmeye yönlendirin

Kullanıcıyı aşağıdaki URL'e yönlendirin. URL parametrelerini uygun şekilde doldurun ve `scope` değerini **boşluk** ile ayırın.

```
https://dev.flextell.ai/oauth/authorize
  ?response_type=code
  &client_id=SIZIN_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
  &scope=customers%3Aread%20appointments%3Aread
  &state=RASTGELE_STRING
```

### Query parametreleri

<ParamField query="response_type" type="string" required>
  Her zaman `code` değerini gönderin.
</ParamField>

<ParamField query="client_id" type="string" required>
  OAuth uygulamanızın `client_id` değeri.
</ParamField>

<ParamField query="redirect_uri" type="string" required>
  Uygulamanızda kayıtlı `redirect_uri` değerlerinden biriyle birebir eşleşmelidir. URL-encode edilmiş olarak gönderin.
</ParamField>

<ParamField query="scope" type="string" required>
  Talep ettiğiniz scope'lar, **boşluk** ile ayrılmış. Uygulamanız oluşturulurken seçtiğiniz scope'ların alt kümesi olmalıdır.
</ParamField>

<ParamField query="state" type="string" required>
  CSRF koruması için rastgele üretilmiş bir değer. Callback'te aynı değeri alıp karşılaştırmalısınız.
</ParamField>

### Kullanıcı deneyimi

Kullanıcı daha önce Flextell'e giriş yapmamışsa bir login ekranı görür, sonra uygulamanızın talep ettiği izinleri gösteren bir onay ekranı görür. Onay verdiğinde Flextell onu `redirect_uri`'ye yönlendirir:

```
https://app.example.com/callback?code=def50200abcdef&state=RASTGELE_STRING
```

Kullanıcı reddederse:

```
https://app.example.com/callback?error=access_denied&state=RASTGELE_STRING
```

<Warning>
  Callback'te önce `state` değerinin gönderdiğiniz değerle eşleşip eşleşmediğini kontrol edin. Eşleşmiyorsa isteği reddedin.
</Warning>

## Adım 2 — code'u access token ile değişin

Sunucunuzdan token endpoint'ine bir `POST` atın. Bu istek **yalnızca backend'den** yapılmalıdır — `client_secret` tarayıcıda ifşa edilmemelidir.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://dev.flextell.ai/oauth/token \
    --header "Content-Type: application/x-www-form-urlencoded" \
    --data "grant_type=authorization_code" \
    --data "code=AUTHORIZATION_CODE" \
    --data "client_id=SIZIN_CLIENT_ID" \
    --data "client_secret=SIZIN_CLIENT_SECRET" \
    --data "redirect_uri=https://app.example.com/callback"
  ```

  ```http HTTP theme={null}
  POST /oauth/token HTTP/1.1
  Host: dev.flextell.ai
  Content-Type: application/x-www-form-urlencoded

  grant_type=authorization_code
  &code=AUTHORIZATION_CODE
  &client_id=SIZIN_CLIENT_ID
  &client_secret=SIZIN_CLIENT_SECRET
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
  ```

  ```js Node.js theme={null}
  const params = new URLSearchParams({
    grant_type: "authorization_code",
    code: "AUTHORIZATION_CODE",
    client_id: process.env.FLEXTELL_CLIENT_ID,
    client_secret: process.env.FLEXTELL_CLIENT_SECRET,
    redirect_uri: "https://app.example.com/callback",
  });

  const res = await fetch("https://dev.flextell.ai/oauth/token", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: params,
  });

  const tokens = await res.json();
  ```
</CodeGroup>

### Başarılı yanıt

```json theme={null}
{
  "token_type": "Bearer",
  "expires_in": 1296000,
  "access_token": "eyJ0eXAiOiJKV1Q...",
  "refresh_token": "def502004d5c..."
}
```

<ResponseField name="token_type" type="string">
  Her zaman `"Bearer"`.
</ResponseField>

<ResponseField name="expires_in" type="integer">
  Access token'ın geçerlilik süresi, saniye cinsinden (`1296000` = 15 gün).
</ResponseField>

<ResponseField name="access_token" type="string">
  API isteklerinde `Authorization: Bearer <token>` olarak gönderin.
</ResponseField>

<ResponseField name="refresh_token" type="string">
  30 gün içinde access token yenilemek için kullanın. Detay: [Token Yenileme](/authentication/refresh-tokens).
</ResponseField>

<ResponseField name="id_token" type="string">
  **Yalnızca `openid` scope'u talep edildiyse** döner. Kullanıcının kimliğini kanıtlayan RS256 imzalı JWT. Detay: [OpenID Connect](/authentication/openid-connect).
</ResponseField>

<Note>
  Yetkilendirme sırasında `scope=openid ...` ekleyerek OIDC akışını başlatabilirsiniz; yanıtta ekstra bir `id_token` alırsınız. Kullanıcı bilgisi için `profile`, `email`, `phone` scope'larını da ekleyebilirsiniz. Tüm detaylar: [OpenID Connect](/authentication/openid-connect).
</Note>

### Hata yanıtları

| HTTP | `error`                  | Sebep                                                                                       |
| ---- | ------------------------ | ------------------------------------------------------------------------------------------- |
| 400  | `invalid_request`        | Zorunlu parametre eksik veya geçersiz biçimde.                                              |
| 400  | `invalid_grant`          | `code` daha önce kullanılmış, süresi dolmuş veya farklı bir `redirect_uri` ile gönderilmiş. |
| 401  | `invalid_client`         | `client_id` veya `client_secret` hatalı.                                                    |
| 400  | `unsupported_grant_type` | `grant_type` değeri desteklenmiyor.                                                         |

```json theme={null}
{
  "error": "invalid_grant",
  "error_description": "The authorization code has expired",
  "message": "The authorization code has expired"
}
```

## PKCE (tek sayfa / mobil uygulamalar)

`client_secret` saklayamayan istemciler (SPA, native mobile) için **PKCE** (Proof Key for Code Exchange) kullanılmalıdır. Yetkilendirme URL'ine `code_challenge` + `code_challenge_method=S256` ekler, token değişiminde `client_secret` yerine `code_verifier` gönderirsiniz.

```bash theme={null}
curl --request POST \
  --url https://dev.flextell.ai/oauth/token \
  --data "grant_type=authorization_code" \
  --data "code=..." \
  --data "client_id=SIZIN_CLIENT_ID" \
  --data "code_verifier=ORIJINAL_VERIFIER" \
  --data "redirect_uri=https://app.example.com/callback"
```

Tam akış, örnek kodlar ve güvenlik kontrol listesi için: [PKCE Akışı](/authentication/pkce).

## Access token'ı kullanma

Token'ı aldıktan sonra her API isteğinde `Authorization` header'ı ile gönderin. Multi-tenant endpoint'lerde ayrıca `X-Tenant` header'ı da gerekir:

```bash theme={null}
curl --request GET \
  --url https://dev.flextell.ai/api/v1/customers \
  --header "Authorization: Bearer eyJ0eXAi..." \
  --header "X-Tenant: 12"
```

Detaylar için [İstek Header'ları](/requests/headers) sayfasına bakın.
