# Değişiklik günlüğü

Storefront API'si URL öneki (`/v1`) ile sürümlenir. v1 içinde her değişiklik eklemelidir: alanlar, endpoint'ler, isteğe bağlı parametreler ve enum değerleri yalnızca eklenir. Aşağıdaki her kayıt yayınlandığı tarihi, neyin değiştiğini ve bu referansın hangi sayfalarının güncellendiğini belirtir. Aynı kayıtlar depo değişiklik günlüğünde de yer alır.

## 2026-10-29

### Eklendi
- `GET /v1/api/commerce/products` ve `GET /v1/api/commerce/products/{id}` üzerinde `variants[].image_id` (uuid veya null) ve `variants[].image` (görsel nesnesi veya null): bir varyantın kendi görseli, ürünün medya öğelerinden biri; bu nedenle `image_id`, detay endpoint'indeki `images` içindeki bir öğeyle eşleşir. Shopify'dan içe aktarılan ürünler bunu `Variant Image` sütunundan alır. Bkz. [Varyant nesnesi](/tr/api/catalog/products#varyant-nesnesi).

## 2026-10-24

### Notlar
- Dokümantasyon düzeltmesi, API'de hiçbir şey değişmedi. Webhook olay kataloğu artık `WebhookDispatcher`'ın sales modülünden beri izin verdiği sekiz abone olunabilir sales olayını belgeliyor: `quote.offered`, `quote.accepted`, `quote.declined`, `quote.expired` (`{id, number, status, origin, total_amount, currency, email, valid_until, signed_at}`) ve `invoice.sent`, `invoice.paid`, `invoice.overdue`, `credit_note.sent` (`{id, number, kind, status, total_amount, paid_amount, open_amount, currency, email, issue_date, due_date}`), her birinin ne zaman gönderildiğiyle birlikte. Bkz. [Webhook'lar](/tr/api/webhooks/index).
- Scope tablosu artık verilebilir her scope'u ve onu denetleyen rotaları listeliyor: `catalog:read` (ve `catalog:write`, `configurator:*` çifti), eski adları `customers:*` olan `contacts:read` / `contacts:write`, `sales:read` / `sales:write` ve verilebilir olup henüz hiçbir `/v1/api` rotasının kullanmadığı scope'lar. Bkz. [Kimlik doğrulama](/tr/api/getting-started/authentication).

## 2026-10-18

### Eklendi
- `GET /v1/api/forms/address-lookup` (scope `forms:read`): `country=NL`, `postal_code`, `house_number` ve isteğe bağlı `addition`, `200 {street, city, postal_code, lat, lon}` döndürür (`data` içine sarılmaz). Hatalar: `404` (`No address found.`), `country`, `postal_code` veya `house_number` üzerinde `422`, `503` (`Address lookup is temporarily unavailable.`). Mağaza başına dakikada 60 istek, sonrasında `429`. Bkz. [Adres arama](/tr/api/forms/forms#get-v1apiformsaddress-lookup).
- Formlarda `address` alan türü. `config` şu biçimdedir: `{country, lookup?, service_area?}`; yanıt `{postal_code, house_number, addition?, street, city, lat?, lon?}` olur ve geçersiz bir değer `answers.{key}` üzerinde `Must be a valid address.` hatasını verir. `service_area` şudur: `{origin: {lat, lon, label?}, radius_km, mode: notice | block, message}`. Bkz. [Alan türleri](/tr/api/forms/index#alan-trleri).
- Saklanan bir başvuruda `meta.address`: hizmet bölgesi olan her `address` alanı için `{distance_km, in_area}`. `mode: "block"` ile adresi kesin olarak bölge dışında olan bir başvuru, `answers.{key}` üzerinde alanın `message` metniyle `422` verir. Bkz. [Adres alanları ve hizmet bölgesi](/tr/api/forms/submissions#adres-alanlar-ve-hizmet-blgesi).
- `choice` alanlarında `options_source`: `{object_type, label, description?, sort?, limit?}`. `GET /v1/api/forms/{key}` her istekte `config.options` değerini koleksiyonun herkese açık görünen kayıtlarından doldurur ve başvuru bunlara göre kontrol edilir. Bkz. [Alan türleri](/tr/api/forms/index#alan-trleri).
- Bir `address` yanıtının parçaları için kırpmadan sonraki uzunluk sınırları: `postal_code` 12 karakter, `house_number` 20, `addition` 10, `street` ve `city` 255'er. Daha uzun bir parça, `@borkol/forms` paketinin `check()` işlevinde de, `answers.{key}` üzerinde `Must be a valid address.` hatasını verir. Bkz. [Alan türleri](/tr/api/forms/index#alan-trleri).
- `@borkol/forms` 0.2.0: `BorkolForm` ve `useBorkolForm` üzerindeki `persistKey` seçeneği ziyaretçinin taslağını 30 güne kadar `localStorage` içinde tutar; `formatAddress`, `normaliseAddress` ve `distanceKm` dışa aktarılır. Bkz. [@borkol/forms paketi](/tr/api/forms/index#borkolforms-paketi).

### Değiştirildi
- Bir formda artık 150 girdi alanı olabilir (önceden 60). `heading` ve `paragraph` sayılmaz. Adımlar 20'de kalır. Bkz. [Tanım: adımlar ve alanlar](/tr/api/forms/index#tanm-admlar-ve-alanlar).

### Notlar
- `address` yeni bir alan türüdür: bileşeni `kind` değerine göre seçen bir renderer'ın bunun için bir bileşene ihtiyacı vardır. Bilinmeyen bir türü, `/v1` içinde her zaman olduğu gibi eklemeli bir değişiklik sayın.
- `GET /v1/api/forms/{key}` yanıtında bir `address` alanının `config.service_area.message` değeri, tanımdaki diğer tüm metinler gibi istenen dilde bir metindir (her zamanki yedek dil kuralıyla). Bkz. [Alan türleri](/tr/api/forms/index#alan-trleri).

## 2026-10-16

### Eklendi
- Modül-devre-dışı hata gövdesinde, hem `403` hem `404` varyantında `code: "module_disabled"` ve `module` (modül anahtarı). `error` değişmez, bu nedenle mevcut kontroller çalışmaya devam eder. Bkz. [Modül etkin değil](/tr/api/getting-started/errors-and-rate-limits#modl-etkin-deil).

## 2026-10-13

### Eklendi
- **Formlar.** Yeni bir `forms` modülü ve bölümü. `GET /v1/api/forms/{key}?locale=` (scope `forms:read`), etkin bir formun yayınlanmış sürümünü `data` içinde döndürür: `{key, version, name, steps, settings: {thank_you: {message, redirect_url}}}`; her metin tek bir dile indirgenir ve mağazanın varsayılan diline geri döner. Adımlar ve alanlar `show_if` kuralları taşır (`equals`, `not_equals`, `contains`, `filled`, `empty`, tek seviye `all` veya `any`); alan türleri `text`, `textarea`, `number`, `email`, `phone`, `date`, `select`, `link`, `choice`, `consent`, `hidden`, `file`, `heading` ve `paragraph`'tır. Bkz. [Formlar](/tr/api/forms/index) ve [Form yükleme](/tr/api/forms/forms).
- `POST /v1/api/forms/{key}/submissions` (scope `forms:write`) yanıtları aynı kurallarla yayınlanmış sürüme göre kontrol eder, gizli alanlara verilen yanıtları atar, başvuruyu saklar ve `201 {"data": {"number", "thank_you": {message, redirect_url}}}` döndürür. Hatalar `answers.{key}` ve `files.{key}` anahtarlı `422` zarfını kullanır; boş bir string veya `null` dışında bir değer taşıyan `honeypot`, `number: null` ile `201` döndürür ve hiçbir şey saklamaz. Bkz. [Başvurular](/tr/api/forms/submissions).
- Form route'larında `X-Borkol-Visitor-Ip` header'ı: form başına saatlik sınır (ziyaretçi başına 1 ile 100, varsayılan 5) `422` ile başarısız olanlar dahil ziyaretçi adresi başına sayılır ve `429 {"message": "Too many submissions. Try again later."}` döndürür. Geçerli bir header yoksa bağlantının adresi kullanılır. Bkz. [Ziyaretçi IP'si ve saatlik sınır](/tr/api/forms/index#ziyareti-ipsi-ve-saatlik-snr).
- `forms:read` ve `forms:write` scope'ları ve `403 {"error": "Module not enabled: forms"}` içinde modül anahtarı olarak `forms`. `forms:write` anahtarlarını sunucunuzda tutun. Bkz. [Kimlik Doğrulama](/tr/api/getting-started/authentication).
- Webhook olayları `form.published` (`{key, version}`) ve `form_submission.created` (`{id, number, form_key, status, locale, name, email, created_at}`, asla yanıtlar değil). Bkz. [Webhook'lar](/tr/api/webhooks/index).
- `POST /v1/api/forms/{key}/uploads` (scope `forms:write`, multipart `field` ve `file`) bir `file` alanı için tek bir dosyayı gizli olarak saklar ve `201 {"data": {"token", "name", "size"}}` döndürür. Tür içeriğe göre (`image`: JPEG, PNG, WebP, HEIC/HEIF; `pdf`: PDF), boyut alanın `max_mb` değerine göre (en fazla 20 MB) kontrol edilir; hatalar `field` veya `file` üzerinde `422`'dir. Form ve ziyaretçi başına saatte 30 yükleme, sonrasında `429 {"message": "Too many uploads. Try again later."}`. Token'lar tek kullanımlıktır, forma ve alana bağlıdır ve 24 saat sonra süresi dolar. Bkz. [Yüklemeler](/tr/api/forms/uploads).
- `POST /v1/api/forms/{key}/submissions` üzerinde `files`: alan anahtarından yükleme token'ları listesine, başvuruyla birlikte talep edilir; bilinmeyen, başka bir forma veya alana ait, kullanılmış ya da süresi dolmuş bir token `files.{key}` üzerinde `422` döndürür (`This upload is invalid or has expired. Upload the file again.`). Bkz. [Başvurular](/tr/api/forms/submissions).
- Formlarda Cloudflare Turnstile: formda Turnstile açıksa ve mağaza iki anahtarı da ayarladıysa `GET /v1/api/forms/{key}` üzerinde `settings.turnstile_site_key`, başvuruda ise saatlik sınırdan sonra ve yanıtlardan önce doğrulanan `turnstile_token`. Başarısız bir kontrol `turnstile` üzerinde `422` döndürür; token'lar tek kullanımlıktır, bu yüzden her `422` sonrasında widget'ı sıfırlayın. Bkz. [Turnstile](/tr/api/forms/index#turnstile) ve [Form yükleme](/tr/api/forms/forms).
- `@borkol/forms` paketi: türler, görünürlük ve yanıt kuralları (`visible`, `check`, `prefill`) ve `upload`, `turnstileToken`, `onServerErrors` ile bir `formError` bileşeni içeren headless bir React render aracı (`@borkol/forms/react`). Bkz. [@borkol/forms paketi](/tr/api/forms/index#borkolforms-paketi).

### Notlar
- Turnstile açık bir form, mağaza iki Turnstile anahtarını da ayarlayana kadar kontrol edilmez: bu durumda `turnstile_site_key` yoktur ve başvurular kontrol olmadan kabul edilir.

## 2026-10-12

### Eklendi
- `tags`, `record_ref_list` veya `record_ref` özelliğinde `filter[{propertyKey}]` ile filtreleme: saklanan listenin içerdiği bir etiket veya kayıt kimliği (bir referans eşitlikle eşleşir). Bkz. [Kayıtlar](/tr/api/objects/records).
- `GET /v1/api/objects/types` içindeki her nesne türünde `settings`: `{publishable, slug?}`; `slug` `{source, prefixes}` biçimindedir ve yalnızca tür kayıtlarına adres veriyorsa bulunur. Her özellik tanımında `localized` (boolean) ve `config` (object veya null). Bkz. [Türler](/tr/api/objects/types).
- Nesne özellikleri için `richtext`, `datetime`, `media`, `media_list`, `link`, `icon`, `token_variant`, `color`, `email`, `phone`, `tags`, `record_ref`, `record_ref_list` özellik türleri ve bir düzey iç içe geçebilen `repeater`; mevcut türlere ek olarak. Özellikler yerelleştirilebilir (number, money, boolean, date, datetime, customer, color, media_list, kayıt referansları, repeater ve sections hariç; `media_list` bunun yerine `alt` ve `caption` değerlerini locale haritası olarak taşır). Bkz. [Nesneler](/tr/api/objects/index).
- Her kayıtta `published_at`, adresi olan bir türün kayıtlarında ise `slugs` (dil etiketinden adrese); mağazada etkin dillerle sınırlıdır. Bkz. [Kayıtlar](/tr/api/objects/records).
- `GET /v1/api/objects/types/{key}/records/by-slug/{slug}?locale=`, yayınlanmış tek bir kaydı bir dildeki adresiyle getirir (`locale` varsayılan olarak mağazanın varsayılan dilidir; etkin değilse `locale` üzerinde `422`, görünür bir eşleşme yoksa `404`). Bkz. [Kayıtlar](/tr/api/objects/records).
- `object_record.published`, `object_record.updated`, `object_record.unpublished` ve `object_record.deleted` webhook olayları; payload `{id, type_key, slugs, published_at}`. Yalnızca gerçek geçişlerde gönderilirler; zamanlanmış bir kaydın zamanı gelmesi bir şey göndermez. Bkz. [Webhook'lar](/tr/api/webhooks/index).
- `GET /v1/api/redirects` artık `tenant:read` ve `objects:read` scope'larını da kabul eder ve kayıt adreslerini ürünleri ve kategorileri yönlendirdiği gibi yönlendirir (bir kayıt adresi değişikliği yalnızca türün o dil için boş olmayan bir adres öneki varsa yönlendirme kaydeder). Bkz. [Yönlendirmeler ve site haritası](/tr/api/getting-started/seo).
- `GET /v1/api/objects/types/{key}/records`, `GET /v1/api/objects/records/{id}` ve by-slug endpoint'inde `include=refs` (veya `include[]=refs`), `record_ref` ve `record_ref_list` değerlerini bir düzey derinliğinde `{id, type_key, values, slugs?, published_at}` olarak açar. Herkese açık görünmeyen hedefler atlanır (referans için `null`, listeden çıkarılır); bilinmeyen `include` token'ları yok sayılır. Bkz. [Kayıtlar](/tr/api/objects/records#include-ile-referanslar).
- `GET /v1/api/objects/types/{key}/records` üzerinde `locale` sorgu parametresi: yerelleştirilmiş `filter[...]`, `sort` ve `q` o dili kullanır. Etkili olması için etkin bir dil etiketi gerekir; başka her değer mağazanın varsayılan diline döner. Bkz. [Kayıtlar](/tr/api/objects/records).
- `GET /v1/api/sitemap` içinde nesne kayıtları: herkese açık görünen her kayıt, dil ve adres için bir tane olmak üzere, boş olmayan adres önekine sahip türlerde `{type: "object_record", object_type, locale, path, lastmod, alternates}` girdileri. Bkz. [Yönlendirmeler ve site haritası](/tr/api/getting-started/seo).
- `GET /v1/api/business` (kapsam `tenant:read`) herkese açık işletme profilini döndürür: ticari ve yasal ad, iletişim bilgileri, adres, sicil ve KDV numaraları, `social_links` (`{platform, url, label}`, 23 platform), varsayılan `locale` ve `content_locales`. Banka, imzalayan, gönderici ve koşul alanları asla açılmaz; profili olmayan bir mağaza `200` ile null değerler döndürür. Bkz. [İşletme profili](/tr/api/getting-started/business).

### Değişti
- **Medya değerleri nesnedir.** Bir `media` değeri (bir özellik veya bir section ya da repeater satırındaki alan) artık `{id, url, alt, width, height, mime_type}` biçimindedir; öğe eksikse veya özelse `null`. Eskiden string olarak medya id'siydi. Bir `media_list` değeri aynı nesnelerin listesidir, her biri bir `caption` taşır; eksik veya özel öğeler listeden çıkarılır. Medya id'sini kendiniz getirmeniz artık gerekmez. Bkz. [Nesneler](/tr/api/objects/index#medya-deerleri).
- **Taslaklar ve zamanlanmış kayıtlar gizlidir.** `settings.publishable: true` olan bir türde taslaklar ve gelecekte `published_at` değeri olan kayıtlar kayıt listesinden çıkarılır; `GET /v1/api/objects/records/{id}` ve slug ile getirmede `404` döndürür. `filter[status]` public olarak kabul edilmez (`filter` üzerinde `422`). Yayınlanabilir olmayan türler değişmez. Bkz. [Kayıtlar](/tr/api/objects/records) ve [Yayınlama ve görünürlük](/tr/api/objects/index#yaynlama-ve-grnrlk).
- **Yerelleştirilmiş değerler etkin dillere indirgenir.** Yerelleştirilmiş bir özellik veya alan, yalnızca mağazada etkin dilleri içeren, dil etiketinden değere bir harita döndürür. Boş olarak saklanmış bir `sections` değeri `[]` olarak döner; artık var olmayan bir türün section'ları çıkarılır. Bkz. [Nesneler](/tr/api/objects/index#yerelletirilmi-deerler).
- **`GET /v1/api/redirects` ve `GET /v1/api/sitemap` platform tarafından sunulur.** Aynı yollar, aynı yanıtlar. Artık catalog modülünü gerektirmezler (artık `403 Module not enabled: catalog` yok), `catalog:read`, `commerce:read`, `tenant:read` veya `objects:read` scope'larından herhangi birini kabul ederler ve site haritası yalnızca etkin modüllerin girdilerini listeler (catalog modülü olmayan bir mağaza boş bir liste alır). Referans sayfası Katalog'dan Başlarken bölümüne taşındı. Bkz. [Yönlendirmeler ve site haritası](/tr/api/getting-started/seo).
- **Yerelleştirilmiş filtre, sıralama ve arama `locale` değerini izler.** Yerelleştirilmiş bir özelliğe göre filtreleme veya sıralama ve yerelleştirilmiş bir metin özelliğinde `q`, artık ham saklanan harita yerine istenen dildeki değeri (`locale` yoksa mağazanın varsayılan dilini) okur. Bkz. [Kayıtlar](/tr/api/objects/records).
- **Varsayılan dili olmayan çeviriler saklanır.** Zorunlu olmayan ve mağazanın varsayılan dili için girdisi bulunmayan çevrilebilir bir özellik veya alan, örneğin varsayılan `nl` iken `{"en": "Dusk"}`, atılmak yerine yazıldığı gibi saklanır; yalnızca tüm girdileri boş olan bir map boş sayılır. Zorunlu olan hâlâ `422` döner. `richtext` izin listesine ayrıca yalnızca `src` ve `alt` ile `img` eklendi (`https://` veya kök göreli `/` kaynaklar; diğer her `img` kaldırılır). Bkz. [Objects](/tr/api/objects/index#yerelletirilmi-deerler).

### Notlar
- Kayıt şekline `published_at` (her zaman) ve `slugs` (adresi olan türler) eklendi. Bilinmeyen alanları, `/v1` içinde her zaman olduğu gibi, eklemeli kabul edin.

## 2026-10-11

### Eklendi
- `GET /v1/api/commerce/products` ve `GET /v1/api/commerce/products/{id}` ürün nesnesinde `capability` (`standard` veya `made_to_measure`) ve `capability_active` (boolean). `capability`, ürünün sepete nasıl ekleneceğini söyler; `capability_active`, ürünü satan modül (`standard` için commerce, `made_to_measure` için configurator) devre dışı olduğu sürece `false` olur. Bkz. [Ürünler](/tr/api/catalog/products).
- Ürün nesnesinde (`piece`, `kg`, `g`, `l`, `m`, `m2`, `m3`, `hour`) ve her sipariş satırında `unit` (`lines[].unit`, sipariş anında ürünün birimi). Bkz. [Ürünler](/tr/api/catalog/products) ve [Siparişler](/tr/api/orders-and-quotes/orders).
- `compare_at_amount`, `barcode`, `weight_grams`, `requires_shipping`, `track_stock`, `returnable`, `lead_time_days`, `tags` ve `social_image` ürün alanları ile `barcode` ve `weight_grams` varyant alanları. Bkz. [Ürünler](/tr/api/catalog/products).
- `GET /v1/api/redirects?path=`, slug'ı değişen bir ürün veya kategori yolu için `{data: {from_path, to_path, status}}` döndürür (yoksa 404) ve `GET /v1/api/sitemap`, tüm aktif ürün ve kategori yollarını `{data: [{type, path, lastmod}]}` olarak listeler. Her ikisi de `catalog:read` veya `commerce:read` ve catalog modülü gerektirir. Bkz. [Yönlendirmeler ve site haritası](/tr/api/catalog/seo).
- Sepete eklemenin bir satırı reddettiği 422 yanıtında (`POST /v1/api/commerce/carts/{id}/lines`), değişmeyen `message` ve `errors` alanlarının yanında en üst düzeyde bir `code`: `CAPABILITY_INACTIVE`, `INVALID_CONFIGURATION` veya `NOT_PURCHASABLE`. Bkz. [Sepet satırları](/tr/api/carts-and-checkout/cart-lines) ve [Hatalar ve Rate Limit'ler](/tr/api/getting-started/errors-and-rate-limits).
- Checkout veya kabul edilen bir teklif üzerinden verilen her sipariş satırında `attributes.returnable` ve `attributes.lead_time_days`; made-to-measure bir satır asla iade edilemez. Bkz. [Siparişler](/tr/api/orders-and-quotes/orders).

### Değişti
- **Geriye dönük uyumsuz:** `type` ürün nesnesinden kaldırıldı. Bunun yerine `capability` ile birlikte `requires_shipping` ve `track_stock` kullanın: eski `simple` ve `variable` ürünler `standard`; `configurable` ürünler `made_to_measure` (ve iade edilemez); `digital`, `license` ve `subscription` ürünler `requires_shipping: false` ve `track_stock: false` ile `standard` olur. Bkz. [Ürünler](/tr/api/catalog/products).
- **Geriye dönük uyumsuz:** adetler ondalıklıdır. Sepet, sipariş ve teklif satırlarındaki `quantity`, stok durumundaki `available`, checkout ve teklif kabulündeki `out_of_stock[].requested` ile `.available`, ve `stock.adjusted` webhook'undaki `quantity` ondalıklı olabilen JSON sayılarıdır (`0.75`, `12`). `POST /v1/api/commerce/carts/{id}/lines` ve `PATCH .../lines/{lineId}` üzerindeki `quantity` en fazla üç ondalık basamak kabul eder; `unit` değeri `piece` olan bir ürün hâlâ yalnızca tam sayı alır (`quantity` üzerinde 422). Bkz. [Sepet satırları](/tr/api/carts-and-checkout/cart-lines), [Sepetler](/tr/api/carts-and-checkout/carts), [Siparişler](/tr/api/orders-and-quotes/orders), [Stok durumu](/tr/api/stock/availability) ve [Webhook'lar](/tr/api/webhooks/index).
- **Geriye dönük uyumsuz:** configurator endpoint'leri (`GET /v1/api/commerce/configurator/products/{id}/schema`, `POST .../quote`) configurator modülüne bağlıdır: modül yoksa `403 {"error":"Module not enabled: configurator"}` döndürürler (önceden `catalog`). `capability` değeri `made_to_measure` olmayan bir ürün için 404 döndürürler. Bkz. [Yapılandırma şeması](/tr/api/configurator/schema), [Fiyat teklifi](/tr/api/configurator/quote) ve [Konfigüratör nasıl çalışır](/tr/api/configurator/index).
- Configurator boyutları tam sayı olmalıdır; ondalıklı bir değer önceden kırpılıyordu, artık reddedilir. Quote endpoint'i, en üst düzeyde `code` olmadan düz doğrulama zarfında `dimensions.{key}` üzerinde 422 (`{Label} must be a whole number.`) döndürür; sepete ekleme aynı hatayı `code` `INVALID_CONFIGURATION` ile döndürür. Bkz. [Fiyat teklifi](/tr/api/configurator/quote) ve [Sepet satırları](/tr/api/carts-and-checkout/cart-lines).
- **Geriye dönük uyumsuz:** sepet ve sipariş satırlarındaki yapılandırma anlık görüntüsünde `components[].qty` kesin bir ondalık string'dir (`"2.16"`), önceden integer'dı. Bkz. [Sepetler](/tr/api/carts-and-checkout/carts) ve [Siparişler](/tr/api/orders-and-quotes/orders).
- **Geriye dönük uyumsuz:** `POST /v1/api/commerce/carts/{id}/quote-request` sales modülüne aittir ve mağazada sales devre dışıysa `404 {"error":"Module not enabled: sales"}` döndürür. Teklif tetikleyicileri yalnızca sales etkin ve teklif talepleri açıkken devreye girer; aksi halde `requires_quote` her zaman false olur ve checkout hiçbir zaman `QUOTE_REQUIRED` ile reddetmez. Bkz. [Teklif talepleri](/tr/api/orders-and-quotes/quote-requests), [Checkout](/tr/api/carts-and-checkout/checkout) ve [Hatalar ve Rate Limit'ler](/tr/api/getting-started/errors-and-rate-limits).
- `purchasability` sales modülü tarafından belirlenir ve satıcı hiçbir şey ayarlamadıysa `direct` olur; sales devre dışı olsa bile raporlanır. `quote` ürün sepete eklenebilir: sepet `product_purchasability` nedeniyle `requires_quote: true` bildirir, checkout `409 {"code": "QUOTE_REQUIRED", "reasons": [...]}` ile reddeder ve sepet bunun yerine teklif talebinden geçer. Bir kişi grubunun her zaman teklif ayarı artık bir sales ayarıdır; `customer_group` nedeni değişmedi. Bkz. [Ürünler](/tr/api/catalog/products) ve [Teklif talepleri](/tr/api/orders-and-quotes/quote-requests).
- `stock_status`, `track_stock: false` olan bir ürün ve tüm varyantları için, stok satırları olsa bile, ürün nesnesinde ve `GET /v1/api/stock/availability` ile `GET /v1/api/stock/products/{productId}` üzerinde `untracked` olur (`tracked: false`). Bkz. [Ürünler](/tr/api/catalog/products) ve [Stok durumu](/tr/api/stock/availability).
- Checkout, sepette ürünü `requires_shipping: true` olan bir satır varsa `shipping_method_id` ister (önceden: `simple`, `variable` veya `configurable` tipinde bir ürün). Bkz. [Checkout](/tr/api/carts-and-checkout/checkout) ve [Kargo yöntemleri](/tr/api/carts-and-checkout/shipping-methods).
- Sepetten oluşturulan teklif satırları, adet olarak satılan bir ürün için `unit` `pcs`, aksi halde ürünün birimini taşır (önceden `null`). Bkz. [Teklif talepleri](/tr/api/orders-and-quotes/quote-requests) ve [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).
- Sipariş modunda bir teklifi kabul etmek, stoğu her ürünün line handler'ı üzerinden teklif edilen fiyattan rezerve eder; böylece made-to-measure bir satır bileşenlerini düşer. Yalnızca gerçek bir yetersizlik `OUT_OF_STOCK` ile reddedilir; ürünü artık satılamayan bir satır stok hareketi olmadan dönüştürülür. Bkz. [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).

### Kullanımdan kaldırıldı
- `POST /v1/api/sales/quotes/by-token/{token}/accept` ve `POST /v1/api/commerce/quotes/by-token/{token}/accept` üzerindeki `QUOTE_NOT_ORDERABLE` (422) artık döndürülmez: kesirli satır miktarlarına sahip bir teklif, bu miktarlarla bir siparişe dönüştürülür. Kodu tolere etmeye devam edin ama artık görmeyi beklemeyin. Bkz. [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).

### Notlar
- `/v1` yüzeyi, herhangi bir üretim tüketicisi ona bağımlı olmadan önce yeniden yapılandırıldı; bu nedenle yukarıdaki geriye dönük uyumsuz değişiklikler yeni bir URL sürümü yerine `/v1` içinde yayınlanıyor. Bu sürümden itibaren `/v1` içindeki değişiklikler yeniden yalnızca eklemelidir.
- Belgeleme düzeltmeleri, API'de hiçbir şey değişmedi: ürün ve kategori endpoint'leri `catalog:read` veya `commerce:read` kabul eder ve catalog modülüne bağlıdır (referans `commerce:read` ve `commerce` diyordu); sipariş nesnesindeki `invoice_id` ve teklif talebi yanıtının tamamı (`origin`, `intro`, `terms`, `acceptance_mode`, `pdf_url`, `signed_at`, `signed_pdf_url` ve satır alanları `kind`, `unit`, `description`, `tax_rate`, `unit_price`) artık belgelenmiştir. Bkz. [Ürünler](/tr/api/catalog/products), [Kategoriler](/tr/api/catalog/categories), [Siparişler](/tr/api/orders-and-quotes/orders) ve [Teklif talepleri](/tr/api/orders-and-quotes/quote-requests).

## 2026-09-17

### Eklendi
- `POST /v1/api/commerce/carts/{id}/checkout`, `GET /v1/api/commerce/orders/{id}` ve `GET /v1/api/commerce/my/orders` tarafından döndürülen sipariş nesnesinde `discount_total` (money) ve `discount_breakdown` (array veya null). `discount_total.amount`, ödeme sırasında uygulanan ürün indirimidir (indirim yoksa `0`); `discount_breakdown` uygulanan her indirim için bir `{discount_id, name, code, kind, amount}` kaydı listeler ve indirim yoksa `null` olur. Her ikisi de eklemelidir; mevcut hiçbir alan değişmedi. Bkz. [Siparişler](/tr/api/orders-and-quotes/orders) ve [Ödeme](/tr/api/carts-and-checkout/checkout).
- `POST /v1/api/commerce/quotes/by-token/{token}/accept` üzerindeki `OUT_OF_STOCK` reddinde `message` (yalnızca sipariş modu). 409 gövdesi artık `{"code": "OUT_OF_STOCK", "message": "Insufficient stock.", "out_of_stock": [...]}` şeklindedir; `out_of_stock` satırları değişmedi. Eklemelidir ve zarf artık endpoint'teki diğer tüm retlerle (`code` + `message`) aynı biçimdedir. Bkz. [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).

### Değişti
- `POST /v1/api/commerce/carts/{id}/claim` artık müşterinin sahip olduğu **her** diğer `active` sepeti sahiplenilen sepete birleştiriyor, yalnızca bulunan ilkini değil. Birleştirilen her sepet eskisi gibi `merged` durumuna geçer ve stok rezervasyonlarını serbest bırakır; yalnızca geride sahipsiz bir aktif sepet kalmaz. Bkz. [Sepet sahiplenme](/tr/api/carts-and-checkout/claim) ve [Storefront rehberi](/tr/api/storefront-guide/index).
- Sahiplenme birleştirmesi kimliği de taşır: sahiplenilen sepet, ayarlıysa kendi `email` ve `metadata` değerlerini korur, aksi halde birleştirilen sepetin değerini alır; böylece giriş yapılmadan önce yakalanan bir misafir e-postası artık kaybolmaz. Sepet zarfına alan eklenmedi veya tipi değiştirilmedi. Bkz. [Sepet sahiplenme](/tr/api/carts-and-checkout/claim).

### Notlar
- `POST /v1/api/commerce/carts/{id}/lines`: aynı anda gönderilen iki özdeş ekleme (aynı ürün, varyant ve yapılandırma) eskiden kaybeden isteğin 500 ile başarısız olmasına yol açıyordu. Kaybeden istek artık miktarını kazanan satıra katlar ve eskisiyle aynı 201 zarfını döndürür; `max_quantity_per_line` sınırı korunur. Bkz. [Sepet satırları](/tr/api/carts-and-checkout/cart-lines).
- `X-Customer-Token` işleme artık belgelenen "bir müşteriye çözümlenmeli, aksi halde 401" kuralıyla tutarlıdır: `expires_at` süresi geçmiş veya platformun oturum penceresinden eski bir token artık çözümlenmez, dolayısıyla müşteriye bağlı bir sepeti sahiplenemez veya ödemeye taşıyamaz. Yeni bir token için tekrar giriş yapın. Bkz. [Sepet sahiplenme](/tr/api/carts-and-checkout/claim) ve [Ödeme](/tr/api/carts-and-checkout/checkout).
- `POST /v1/api/customers/forgot-password` bilinen ve bilinmeyen adresler için hâlâ aynı gövdeyle 202 döndürür; artık her iki yolda da aynı miktarda kuyruk işi yapar, böylece yanıt süresi bir hesabın var olup olmadığını ele vermez. Bkz. [Parolalar](/tr/api/customers/passwords).
- Bir `bogo` indirimi artık kazanılan adedini sepet başına bir kez değil, her hak ediş için bir kez verir: indirimli birim sayısı `get_quantity × floor(uygun satın alma adedi ÷ minimum satın alma adedi)` olup en ucuz kazanılan satırın adediyle sınırlıdır. Sepetteki `discounts[].amount` ve siparişin `discount_total` değeri buna göre büyür; hiçbir alan veya enum değeri değişmedi. Bkz. [Sepet indirimleri](/tr/api/carts-and-checkout/discounts).
- `configurable` tipindeki ürünler yalnızca konfigüratör motoruyla fiyatlanır; tip değişikliğinden kalan müşteri grubu ve kademe fiyat satırları artık böyle bir ürünün `price`, `quantity_tiers` veya sepet satırı fiyatında görünmez. Basit ürünler etkilenmez. Bkz. [Ürünler](/tr/api/catalog/products).
- `POST /v1/api/commerce/quotes/by-token/{token}/accept`: sipariş oluşturulurken ortaya çıkan `QUOTE_NOT_OFFERED` reddi (aynı teklifin başka bir kabulüyle yarış durumu) artık `Quote cannot be accepted in its current status (...)` yerine belgelenmiş `Quote is not awaiting a response (status: ...)` mesajını taşır. Kod ve durum değişmedi. Bkz. [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).

## 2026-09-04

### Değişti
- `requires` kuralı yayınlanan diğer seçimlerle karşılanamayan bir konfigüratör seçimi, artık yayınlanıp quote sırasında reddedilmek yerine `GET /v1/api/commerce/configurator/products/{id}/schema` yanıtından çıkarılıyor. Filtreleme yayıldığı için şemanın sunduğu her seçim seçilebilir ve fiyatlandırılabilir. Bkz. [Yapılandırma şeması](/tr/api/configurator/schema) ve [Konfigüratör nasıl çalışır](/tr/api/configurator/index).
- `POST /v1/api/commerce/configurator/products/{id}/quote` aynı kullanılabilirlik kuralını uygular: şemanın artık yayımlamadığı bir seçimi seçmek mevcut genel `choices` mesajıyla başarısız olur ve `choices.{choiceId}` mesajları artık yalnızca hâlâ kullanılabilir olan seçimlerin adını verir, böylece pasife alınmış bir seçim hiçbir hata mesajında açığa çıkmaz. Bkz. [Fiyat teklifi](/tr/api/configurator/quote).
- Kullanılabilir olmayan bir seçime koşullanmış fiyat matrisi, kısaltılmış bir `conditions` dizisiyle listelenmek yerine artık `price_matrices` içinden çıkarılıyor. Böyle bir matris hiçbir zaman uygun hâle gelemeyeceği için motor, ona geri düşmek yerine yapılandırmayı `not_priceable` olarak değerlendirir. Bkz. [Yapılandırma şeması](/tr/api/configurator/schema).

### Notlar
- Her iki konfigüratör endpoint'i için dokümantasyon düzeltmesi: bu endpoint'ler `catalog:read` **veya** `commerce:read` scope'unu taşıyan bir API anahtarını kabul eder (2026-08-25'ten beri değişmedi) ve modül kapıları catalog modülüdür, dolayısıyla 403 gövdesi `{"error":"Module not enabled: catalog"}` şeklindedir. Referans her ikisi için de `commerce:read` ve `commerce` diyordu. API'de hiçbir şey değişmedi. Bkz. [Fiyat teklifi](/tr/api/configurator/quote), [Yapılandırma şeması](/tr/api/configurator/schema) ve [Konfigüratör nasıl çalışır](/tr/api/configurator/index).

## 2026-08-26

### Eklendi
- Customer endpoint'leri artık `/v1/api/contacts/*` üzerinde de sunuluyor; önceki `/v1/api/customers/*` path'leri, aynı request ve response şekilleriyle kalıcı bir alias olarak kalıyor. Yeni API-key scope'ları `contacts:read` ve `contacts:write` kullanılabilir; mevcut `customers:read` / `customers:write` anahtarları değişmeden çalışmaya devam eder. Bkz. [Kişi hesapları](/tr/api/customers/index).
- Kişi profili (`GET/PATCH /v1/api/contacts/me`, ayrıca `.../customers/me`) artık `kind` (`person` veya `company`), `company_name`, `registration_number`, `vat_id`, `external_id` ve `display_name` alanlarını içeriyor. Bu alanlar storefront API üzerinden salt okunurdur. `email` artık satıcı tarafından oluşturulan herhangi bir kişi için `null` olabilir; storefront kaydı bunu hâlâ gerektirir. Bkz. [Profil](/tr/api/customers/profile).
- Adres `type` alanı, `shipping` ve `billing` yanında yeni bir değer olan `work`'ü kabul ediyor. Bkz. [Adresler](/tr/api/customers/addresses).
- Sipariş ve satıcı teklifi nesnelerinde `contact_id`: `customer_id` ile aynı değer, bundan sonraki kanonik ad altında. `customer_id` değişmedi ve kalıyor. Token ile erişilen teklif nesnesinde ikisi de bulunmaz. Bkz. [Siparişler](/tr/api/orders-and-quotes/orders) ve [Checkout](/tr/api/carts-and-checkout/checkout).
- Teklif token endpoint'leri artık `/v1/api/sales/quotes/by-token/{token}` (`GET`, `/accept`, `/decline`) üzerinde de sunuluyor. `/v1/api/commerce/quotes/by-token/*` aynı şekilde ve kalıcı olarak çalışmaya devam ediyor; her iki yol da `sales:read`/`sales:write` **veya** `commerce:read`/`commerce:write` taşıyan bir anahtarı kabul eder. Bkz. [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).
- `GET /v1/api/{sales,commerce}/quotes/by-token/{token}`, `origin`, `intro`, `terms`, `scope_items[]`, `acceptance_mode`, `pdf_url`, `signed_at` ve `signed_pdf_url` döner; `lines[]` içindeki her giriş `kind`, `unit`, `description` ve `tax_rate` kazanır. Bkz. [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).
- `POST /v1/api/{sales,commerce}/quotes/by-token/{token}/accept`, isteğe bağlı bir `signature` body parametresi kabul eder — mağazanın `acceptance_mode`'u `signature` olduğunda zorunlu, en fazla 2 MB'lık bir PNG veri URL'si — ve `signed_pdf_url` döner. Yeni hata kodları: `SIGNATURE_REQUIRED` (422), `SIGNATURE_INVALID` (422), `QUOTE_NOT_ORDERABLE` (422), `ALREADY_CONVERTED` (409) ve `QUOTE_EXPIRED` (410). Bkz. [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).
- Yeni scope'lar `sales:read` ve `sales:write`, teklif token endpoint'lerinde `commerce:read`/`commerce:write`'ın kabul edildiği her yerde kabul edilir. Bkz. [Kimlik doğrulama](/tr/api/getting-started/authentication).
- Bir teklifin `status`'u artık `draft` olabilir: satıcının yazdığı teklifler gönderilmeden önce var olur. Bir draft'ın numarası yoktur ve token ile hiçbir zaman erişilemez.

### Değişti
- Customer endpoint'leri artık bir modülün etkin olmasını gerektirmiyor; 403 `Module not enabled: customers` yanıtı artık oluşamaz. Bkz. [Müşteri hesapları](/tr/api/customers/index) ve [Hatalar ve rate limit'ler](/tr/api/getting-started/errors-and-rate-limits).
- Teklif satırı `quantity` alanı (satıcı teklifleri ve token ile erişilen teklif nesnesi) artık `integer` yerine `number` olarak belgelenir: ürün satırları hâlâ her zaman tam sayı bildirir, ancak hizmet ve malzeme satırları artık kesirli bir miktar taşıyabilir (saat, metre). Daha önce tam sayı olan her değer tam olarak aynı şekilde serileştirilmeye devam eder. Bkz. [Teklif talepleri](/tr/api/orders-and-quotes/quote-requests) ve [Teklif token'ları](/tr/api/orders-and-quotes/quote-tokens).
- Teklif token endpoint'lerinde accept ve decline, çağıranın IP'siyle anahtarlanarak dakikada 30 istek ile sınırlandırıldı. Bkz. [Hatalar ve rate limit'ler](/tr/api/getting-started/errors-and-rate-limits).

### Notlar
- Teklif token endpoint'lerinde `lines[].quantity` her zaman bir JSON sayısıydı ve hâlâ öyle; artık kesirli olabilir (iki ondalık). Hiçbir alan kaldırılmadı, yeniden adlandırılmadı veya türü değiştirilmedi.

## 2026-08-25

### Değişti
- Genel katalog rotaları (`/v1/api/commerce/products`, `/v1/api/commerce/categories`, `/v1/api/commerce/configurator/*`) artık `catalog:read` **veya** `commerce:read` scope'unu taşıyan bir API anahtarını kabul eder. Mevcut anahtarlar değişmeden çalışmaya devam eder. Bkz. [Kimlik doğrulama](/tr/api/getting-started/authentication).
- Catalog modülü etkin mağazalar için yeni `catalog:read` ve `catalog:write` API anahtarı scope'ları kullanılabilir. Diğer tüm modüllerin scope adları değişmedi.

### Notlar
- Bu sürümde hiçbir istek parametresi, yanıt alanı, durum değeri veya hata zarfı değişmedi.
