# Yönlendirmeler ve site haritası

Bu iki endpoint, merchant bir şeyi yeniden adlandırdığında storefront'un arama sıralamasını korumasına yardımcı olur. Bunlar tek bir modüle değil platforma aittir: içeriğe adres veren her modül bunlara katkıda bulunur. Katalog içeriği sabit biçimli yollar kullanır: bir ürün `/products/{slug}`, bir kategori `/categories/{slug}` adresinde bulunur. İçerik kayıtları (Objects), türün o dil için adres önekinde artı kaydın slug'ında bulunur, örneğin `/hizmetler/mutfak-montaji`. Storefront'unuz farklı URL'ler kullanıyorsa bu yolları kendi route'larınıza eşleyin.

Katalog ürünler ve kategoriler için, Objects ise yayınlanmış her kayıt adresi için bir site haritası girdisi katar ([GET /v1/api/sitemap](#get-v1apisitemap) bölümüne bakın). Merchant bir ürünün, kategorinin veya kaydın slug'ını değiştirdiğinde Borkol, eski yoldan yenisine kalıcı bir yönlendirme kaydeder; bir kayıt için bu yalnızca türün o dil için boş olmayan bir adres öneki varsa olur. Zincirler birleştirilir: `a` adını `b` ve ardından `b` adını `c` olarak değiştirmek, hem `/products/a` hem de `/products/b` yollarını doğrudan `/products/c` adresine yönlendirir. Yeniden canlı hale gelen bir yol (eski slug'ı yeni bir ürün alır) yönlendirmeyi bırakır.

Her iki endpoint de `Authorization: Bearer {api_key}` olarak gönderilen, `catalog:read`, `commerce:read`, `tenant:read` veya `objects:read` scope'larından herhangi birine sahip bir tenant API anahtarı alır. Catalog modülünü gerektirmezler: yalnızca Objects kullanan bir mağaza da bunları çağırabilir. Dakikada 120 istek olan ortak tenant rate limit'i geçerlidir.

## GET /v1/api/redirects

Tek bir storefront yolu için yönlendirmeyi arar. Storefront'unuzdaki bir ürün, kategori veya kayıt isteği aksi halde 404 döndürecekse bu endpoint'i çağırın ve ziyaretçiyi dönen `status` koduyla yönlendirin.

Arama, sondaki bir eğik çizgiyi kaldırır (`/products/old-chair/`, `/products/old-chair` ile eşleşir; kök yol `/` olduğu gibi bırakılır) ve büyük/küçük harfe duyarlıdır. Yalnızca birebir aynı yollar eşleşir: query string'ler yolun parçası değildir.

### Query parametreleri

| Ad | Tür | Zorunlu | Açıklama |
| --- | --- | --- | --- |
| path | string | Evet | Aranacak storefront yolu, örneğin `/products/old-chair` veya `/hizmetler/eski-slug`. En fazla 512 karakter. |

```bash title="Request"
curl "https://api.borkol.com/v1/api/redirects?path=%2Fproducts%2Fold-chair" \
  -H "Authorization: Bearer {api_key}" \
  -H "Accept: application/json"
```

```javascript title="Request (JS)"
const res = await fetch(
  "https://api.borkol.com/v1/api/redirects?" +
    new URLSearchParams({ path: "/products/old-chair" }),
  {
    headers: {
      Authorization: `Bearer ${apiKey}`,
      Accept: "application/json",
    },
  }
);
if (res.status === 404) {
  // No redirect: render your own not-found page.
} else {
  const { data } = await res.json();
  // Redirect the visitor to data.to_path with data.status.
}
```

```json title="Response"
{
  "data": {
    "from_path": "/products/old-chair",
    "to_path": "/products/oak-dining-chair",
    "status": 301
  }
}
```

### Yanıt alanları

| Ad | Tür | Zorunlu | Açıklama |
| --- | --- | --- | --- |
| from_path | string | her zaman | Kayıtlı eski yol (sonda eğik çizgi olmadan). |
| to_path | string | her zaman | Ziyaretçinin gönderileceği yol. Yönlendirmeler ürünün, kategorinin veya kaydın durumundan bağımsız olarak kaydedilir ve arşivleme ya da yayından kaldırma bir yönlendirmeyi kaldırmaz; bu nedenle `to_path` yolunun kendisi kullanılamıyor olabilir, yönlendirmeden önce kontrol edin. |
| status | integer | her zaman | Yönlendirmede kullanılacak HTTP durumu. Şu anda her zaman `301` (kalıcı). |

### Hatalar

| Durum | Body | Neden |
| --- | --- | --- |
| 401 | `{"message":"Unauthenticated."}` | API anahtarı eksik veya geçersiz. |
| 403 | `{"message":"Invalid ability provided."}` | Anahtar `catalog:read`, `commerce:read`, `tenant:read` veya `objects:read` scope'larından hiçbirine sahip değil. |
| 403 | `{"message":"Tenant suspended.","code":"tenant_suspended"}` | Tenant hesabı askıya alınmış. |
| 404 | `{"message":"..."}` | Bu yol için yönlendirme yok. |
| 422 | `{"message":"...","errors":{"path":["..."]}}` | `path` eksik, string değil veya 512 karakterden uzun. |
| 429 | `{"message":"Too Many Attempts."}` | Dakikada 120 istek olan rate limit aşıldı. |

## GET /v1/api/sitemap

Mağaza için etkin modüllerin tüm canlı yollarını `sitemap.xml` olarak işlenmeye hazır şekilde listeler. Devre dışı bir modül hiçbir şey katmaz; bu yüzden catalog modülü olmayan bir mağaza ürün veya kategori girdisi almaz (yanıt hata değil, boş bir `data` dizisidir). Catalog modülü durumu `active` olan tüm ürünleri ve etkin tüm kategorileri katar; önce ürünler, ardından kategoriler gelir; her grup slug'a göre sıralanır. Objects modülü, o dil için boş olmayan bir adres önekine sahip nesne türlerinde, herkese açık görünen her kayıt, dil ve adres için bir girdi katar; öneki olmayan türlerin herkese açık sayfası yoktur ve taslaklar ile zamanlanmış kayıtlar gibi dışarıda bırakılır. Yanıt sayfalanmaz.

### Parametreler

Yok.

```bash title="Request"
curl "https://api.borkol.com/v1/api/sitemap" \
  -H "Authorization: Bearer {api_key}" \
  -H "Accept: application/json"
```

```json title="Response"
{
  "data": [
    {
      "type": "product",
      "path": "/products/oak-dining-chair",
      "lastmod": "2026-10-11T09:14:33+00:00"
    },
    {
      "type": "category",
      "path": "/categories/chairs",
      "lastmod": "2026-10-02T15:20:11+00:00"
    },
    {
      "type": "object_record",
      "object_type": "service",
      "locale": "nl",
      "path": "/diensten/keukenmontage",
      "lastmod": "2026-10-09T12:41:07+00:00",
      "alternates": {
        "en": "/services/kitchen-fitting",
        "nl": "/diensten/keukenmontage"
      }
    }
  ]
}
```

### Yanıt alanları

`data` içindeki her öğe:

| Ad | Tür | Zorunlu | Açıklama |
| --- | --- | --- | --- |
| type | string | her zaman | `product`, `category` veya `object_record`. |
| path | string | her zaman | Storefront yolu: `/products/{slug}`, `/categories/{slug}` veya bir kayıt için türün o dildeki adres öneki artı kaydın adresi, örneğin `/services/kitchen-fitting`. |
| lastmod | string (ISO 8601) veya null | her zaman | Ürünün, kategorinin veya kaydın son güncellenme zamanı. |
| object_type | string | yalnızca `object_record` | Kaydın nesne türünün anahtarı. |
| locale | string | yalnızca `object_record` | Bu girdinin adresinin dili. |
| alternates | object | yalnızca `object_record` | Kaydın herkese açık bir adresi olan her etkin dil için dil etiketi - yol eşlemesi (bu girdinin kendisi dahil). `hreflang` bağlantıları için kullanın. |

### Hatalar

| Durum | Body | Neden |
| --- | --- | --- |
| 401 | `{"message":"Unauthenticated."}` | API anahtarı eksik veya geçersiz. |
| 403 | `{"message":"Invalid ability provided."}` | Anahtar `catalog:read`, `commerce:read`, `tenant:read` veya `objects:read` scope'larından hiçbirine sahip değil. |
| 403 | `{"message":"Tenant suspended.","code":"tenant_suspended"}` | Tenant hesabı askıya alınmış. |
| 429 | `{"message":"Too Many Attempts."}` | Dakikada 120 istek olan rate limit aşıldı. |
