Originos

Originos Storefront & Theme Developer API

Bu doküman Originos üzerinde web, mobil uygulama veya özel tema geliştiren frontend ekipleri içindir. Mağaza vitrininin ihtiyaç duyduğu tema config'i, katalog, sepet, checkout, müşteri hesabı, adres, sipariş ve dijital teslimat API'lerinin tamamını kapsar.

1. Hızlı başlangıç

Production API kökü:

https://originos.netkora.com/api/v1

Local API kökü:

http://127.0.0.1:8000/api/v1

Storefront isteklerinde mağazaya ait public API anahtarı gönderilir:

Accept: application/json
Content-Type: application/json
X-Store-Key: pk_live_...

Public storefront key tarayıcı veya mobil uygulamada kullanılabilir. sk_... ile başlayan secret anahtarlar frontend bundle'ına, public repository'ye veya tarayıcı storage'ına kesinlikle konulmamalıdır.

İlk bağlantı testi:

curl 'https://originos.netkora.com/api/v1/storefront/store' \
  -H 'Accept: application/json' \
  -H 'X-Store-Key: YOUR_PUBLIC_STORE_KEY'

JavaScript istemci örneği:

const API_URL = 'https://originos.netkora.com/api/v1'
const STORE_KEY = 'YOUR_PUBLIC_STORE_KEY'

async function originos(path, options = {}) {
  const response = await fetch(`${API_URL}${path}`, {
    ...options,
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Store-Key': STORE_KEY,
      ...options.headers,
    },
  })

  const body = response.status === 204 ? null : await response.json()
  if (!response.ok) {
    throw Object.assign(new Error(body?.message || 'Originos API error'), {
      status: response.status,
      code: body?.code,
      errors: body?.errors,
      requestId: response.headers.get('X-Request-ID'),
    })
  }

  return body
}

2. Temel kurallar

Mağaza izolasyonu

X-Store-Key hangi mağazanın verisinin döneceğini belirler. Bir mağazaya ait ürün slug'ı, sepet token'ı, müşteri token'ı veya sipariş UUID'si başka mağazada kullanılamaz.

Doğrulanmış özel domain kullanılıyorsa mağaza host üzerinden de çözülebilir. Tema entegrasyonunda açık ve taşınabilir davranış için public store key gönderilmesi önerilir.

Kimlik doğrulama katmanları

Katman Header Kullanım
Public storefront X-Store-Key Config, ürün, kategori, kargo, sepet
Customer hesabı Authorization: Bearer {customer_token} Profil, adresler, müşteri siparişleri
Guest sipariş X-Order-Token: {guest_access_token} Yalnız ilgili misafir siparişini görüntüleme
Checkout retry güvenliği Idempotency-Key: {unique-value} Siparişin iki kez oluşmasını engelleme

Customer endpointlerinde hem X-Store-Key hem customer bearer token gönderilmelidir.

Para değerleri

Bütün amount alanları integer minor unit değeridir. Ondalıklı sayı kullanılmaz.

{"amount": 12990, "currency": "TRY"}

Bu değer 129,90 TRY anlamına gelir. Gösterim için para biriminin fraction digit bilgisi kullanılmalıdır:

function formatMoney(money, locale = 'tr-TR') {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency: money.currency,
  }).format(money.amount / 100)
}

Tarih, UUID ve sayfalama

{
  "data": [],
  "links": {
    "first": "...",
    "last": "...",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "per_page": 20,
    "to": 1,
    "total": 1
  }
}

Rate limit

Grup Sınır
Storefront 120 istek/dakika
Register/login 10 istek/dakika
Checkout 10 istek/dakika
Dijital indirme 30 istek/dakika

Limit aşılırsa 429 Too Many Requests döner. İstemci exponential backoff uygulamalı ve checkout için aynı Idempotency-Key değerini korumalıdır.

3. Originos Theme Contract 1.5.0

Hero alanı çoklu slider destekler. hero_slides en fazla 8 öğeden oluşur; her öğe title, subtitle, image, button_label ve button_url alanlarını taşır. hero_slider_autoplay otomatik geçişi, hero_slider_interval ise 3–15 saniye arasındaki geçiş süresini belirler. hero_slides boşsa geriye uyumluluk için hero_title, hero_subtitle, hero_image, hero_button_label ve hero_button_url alanları tek slide olarak kullanılmalıdır.

Her Originos teması aynı config şemasını kullanır. Müşteri tema değiştirdiğinde uyumlu mağaza ayarları korunur, eksik veya geçersiz değerler yeni temanın varsayılanlarıyla tamamlanır. Frontend'in tema bazında farklı config eşlemesi yapması gerekmez.

Tema config'i şu endpointten alınır:

GET /storefront/store

Manifest yapısı:

{
  "schema_version": "1.1.0",
  "assets": {
    "css": "https://cdn.example.com/originos/theme.css",
    "js": null
  },
  "settings": [
    {
      "key": "primary_color",
      "label": "Primary color",
      "group": "colors",
      "type": "color",
      "required": true,
      "default": "#111827"
    }
  ]
}

Runtime değerleri data.theme.settings içindeki key/value objesidir. Tasarım çalışırken manifestteki default yerine öncelikle bu resolved değerler kullanılmalıdır.

Kanonik tema ayarları

Grup Key Tip Varsayılan / seçenekler
colors primary_color color #111827
colors secondary_color color #ffffff
colors accent_color color #10b981
colors background_color color #ffffff
colors text_color color #111827
typography font_family select system; system, inter, manrope, serif
layout border_radius select medium; none, small, medium, large
layout header_style select minimal; minimal, centered, mega
layout footer_style select columns; minimal, columns
catalog product_card_style select bordered; minimal, bordered, elevated
catalog catalog_columns number 4; minimum 2, maksimum 6
catalog show_search boolean true
catalog show_categories boolean true
hero hero_enabled boolean true
hero hero_title text Welcome
hero hero_subtitle text boş metin
hero hero_image image URL null, yalnız HTTP(S)
hero hero_button_label text Shop now
hero hero_button_url URL null, yalnız HTTP(S)
announcement announcement_position select top; top, below_header, above_footer
announcement announcement_style select bar; bar, floating, minimal
homepage homepage_section_order list hero, announcement, featured_products, categories, new_arrivals, promo
homepage homepage_featured_products_enabled boolean true
homepage homepage_featured_products_title text Featured products
homepage homepage_featured_products_limit number 8; minimum 1, maksimum 24
homepage homepage_categories_enabled boolean true
homepage homepage_categories_title text Shop by category
homepage homepage_categories_limit number 8; minimum 1, maksimum 24
homepage homepage_new_arrivals_enabled boolean true
homepage homepage_new_arrivals_title text New arrivals
homepage homepage_new_arrivals_limit number 8; minimum 1, maksimum 24
promo promo_enabled boolean false
promo promo_title text Special offer
promo promo_subtitle text Discover our latest offers.
promo promo_image image URL null, yalnız HTTP(S)
promo promo_button_label text Explore
promo promo_button_url URL null, yalnız HTTP(S)
account account_auth_mode select pages; pages, combined, modal
account account_default_tab select login; login, register
account account_allow_registration boolean true
account account_login_title text Tekrar hoş geldiniz.
account account_register_title text Hesabınızı oluşturun.
account account_show_benefits boolean true
account account_marketing_consent boolean true
engagement wishlist_enabled boolean true
engagement wishlist_drawer_title text Favorilerim
engagement recently_viewed_enabled boolean true
engagement recently_viewed_title text Son baktıklarınız
engagement sale_badge_enabled boolean true
engagement sticky_mobile_buy boolean true
advanced custom_css css boş metin, maksimum 50.000 karakter

Önerilen CSS variable eşlemesi

function applyTheme(settings) {
  const root = document.documentElement

  root.style.setProperty('--color-primary', settings.primary_color)
  root.style.setProperty('--color-secondary', settings.secondary_color)
  root.style.setProperty('--color-accent', settings.accent_color)
  root.style.setProperty('--color-background', settings.background_color)
  root.style.setProperty('--color-text', settings.text_color)

  root.dataset.font = settings.font_family
  root.dataset.radius = settings.border_radius
  root.dataset.header = settings.header_style
  root.dataset.footer = settings.footer_style
  root.dataset.productCard = settings.product_card_style

  let customStyle = document.getElementById('originos-custom-css')
  if (!customStyle) {
    customStyle = document.createElement('style')
    customStyle.id = 'originos-custom-css'
    document.head.appendChild(customStyle)
  }
  customStyle.textContent = settings.custom_css || ''
}

Tema kodu bilinmeyen gelecekteki alanları görmezden gelmeli ve schema_version değerini kontrol etmelidir. Desteklenmeyen major sürüm görülürse güvenli bir varsayılan tasarım gösterilmelidir.

Tema paketi manifesti

Tema Originos kataloğuna eklenirken 38 alanın tamamını tekrar tanımlamak gerekmez. Tema yalnız değiştirmek istediği default değerlerini ve asset URL'lerini verir:

{
  "name": "Originos Modern",
  "slug": "originos-modern",
  "version": "1.1.0",
  "type": "free",
  "is_active": true,
  "is_public": true,
  "manifest": {
    "schema_version": "1.1.0",
    "assets": {
      "css": "https://cdn.example.com/originos-modern/1.1.0/theme.css",
      "js": null
    },
    "settings": [
      {"key": "primary_color", "default": "#2563eb"},
      {"key": "font_family", "default": "inter"},
      {"key": "header_style", "default": "centered"},
      {"key": "product_card_style", "default": "elevated"}
    ]
  }
}

Originos manifesti otomatik olarak tam sözleşmeye genişletir. 1.0.0–1.4.0 manifestler geriye uyumlulukla 1.5.0 sözleşmesine yükseltilir. Bilinmeyen key, farklı tip, farklı select seçenekleri veya desteklenmeyen schema version reddedilir.

4. Endpoint özeti

Tüm yollar https://originos.netkora.com/api/v1 köküne göredir.

Mağaza ve katalog

Metot Endpoint Açıklama
GET /storefront/store Mağaza, core settings ve resolved tema config'i
GET /storefront/products Yayındaki ürünler
GET /storefront/products/{slug} Ürün detayı
GET /storefront/categories Kök kategori ağacı
GET /storefront/categories/{slug} Kategori ve doğrudan ürünleri
GET /storefront/shipping-methods Aktif kargo seçenekleri

Sepet ve checkout

Metot Endpoint Açıklama
POST /storefront/cart Yeni sepet oluşturur
GET /storefront/cart/{token} Sepeti getirir
POST /storefront/cart/{token}/items Varyant ekler veya miktarı değiştirir
PATCH /storefront/cart/{token}/items/{item} Sepet satırı miktarını değiştirir
DELETE /storefront/cart/{token}/items/{item} Sepet satırını siler
POST /storefront/cart/{token}/calculate Kupon, kargo ve vergi dahil server-side hesaplar
POST /storefront/checkout İdempotent sipariş oluşturur

Customer hesabı

Metot Endpoint Açıklama
POST /storefront/customer/auth/register Kayıt ve customer token
POST /storefront/customer/auth/login Login ve customer token
POST /storefront/customer/auth/logout Aktif customer token'ını iptal eder
GET /storefront/customer/me Aktif müşteri profili
GET /storefront/customer/addresses Adres listesi
POST /storefront/customer/addresses Adres oluşturur
GET /storefront/customer/addresses/{address} Adres detayı
PUT/PATCH /storefront/customer/addresses/{address} Adres günceller
DELETE /storefront/customer/addresses/{address} Adres siler
GET /storefront/customer/orders Customer siparişleri
GET /storefront/customer/orders/{order} Customer sipariş detayı
GET /storefront/guest/orders/{order} Guest sipariş detayı
GET /storefront/downloads/{grant}?expires=...&signature=...&token=... Signed dijital dosya indirme

5. Mağaza config'i

GET /storefront/store

Storefront uygulamasının ilk açılışında çağrılması önerilir.

{
  "data": {
    "id": "STORE_UUID",
    "name": "Demo Store",
    "currency": "TRY",
    "locale": "tr",
    "timezone": "Europe/Istanbul",
    "maintenance": false,
    "logo_url": "https://cdn.example.com/logo.png",
    "favicon_url": "https://cdn.example.com/favicon.png",
    "settings": {
      "commerce": {
        "show_prices_with_tax": true,
        "show_out_of_stock": true
      },
      "contact": {
        "support_email": "support@example.com",
        "support_phone": "+905551112233"
      },
      "seo": {
        "title": "Demo Store",
        "description": "Mağaza açıklaması"
      },
      "announcement": {
        "enabled": true,
        "message": "Aynı gün kargo"
      },
      "payments": {
        "default_method": "bank_transfer",
        "bank_transfer": {
          "enabled": true,
          "bank_name": "Örnek Banka",
          "account_holder": "Demo Store A.Ş.",
          "iban": "TR00 0000 0000 0000 0000 0000 00",
          "branch": "Merkez",
          "instructions": "Sipariş numaranızı ödeme açıklamasına yazınız."
        }
      }
    },
    "homepage": {
      "section_order": ["hero", "announcement", "featured_products", "categories", "new_arrivals", "promo"],
      "hero": {"enabled": true, "title": "Welcome", "subtitle": "", "image": null, "button_label": "Shop now", "button_url": null},
      "announcement": {"enabled": true, "message": "Aynı gün kargo", "position": "top", "style": "bar"},
      "featured_products": {"enabled": true, "title": "Featured products", "limit": 8},
      "categories": {"enabled": true, "title": "Shop by category", "limit": 8},
      "new_arrivals": {"enabled": true, "title": "New arrivals", "limit": 8},
      "promo": {"enabled": false, "title": "Special offer", "subtitle": "Discover our latest offers.", "image": null, "button_label": "Explore", "button_url": null},
      "custom_css": ""
    },
    "theme": {
      "id": "THEME_UUID",
      "name": "Originos Starter",
      "slug": "originos-starter",
      "version": "1.1.0",
      "manifest": {
        "schema_version": "1.1.0",
        "assets": {"css": null, "js": null},
        "settings": "38 kanonik setting definition"
      },
      "settings": {
        "primary_color": "#111827",
        "secondary_color": "#ffffff",
        "accent_color": "#10b981",
        "background_color": "#ffffff",
        "text_color": "#111827",
        "font_family": "system",
        "border_radius": "medium",
        "header_style": "minimal",
        "footer_style": "columns",
        "product_card_style": "bordered",
        "catalog_columns": 4,
        "show_search": true,
        "show_categories": true,
        "hero_enabled": true,
        "hero_title": "Welcome",
        "hero_subtitle": "",
        "hero_image": null,
        "hero_button_label": "Shop now",
        "hero_button_url": null,
        "announcement_position": "top",
        "announcement_style": "bar",
        "homepage_section_order": ["hero", "announcement", "featured_products", "categories", "new_arrivals", "promo"],
        "homepage_featured_products_enabled": true,
        "homepage_featured_products_title": "Featured products",
        "homepage_featured_products_limit": 8,
        "homepage_categories_enabled": true,
        "homepage_categories_title": "Shop by category",
        "homepage_categories_limit": 8,
        "homepage_new_arrivals_enabled": true,
        "homepage_new_arrivals_title": "New arrivals",
        "homepage_new_arrivals_limit": 8,
        "promo_enabled": false,
        "promo_title": "Special offer",
        "promo_subtitle": "Discover our latest offers.",
        "promo_image": null,
        "promo_button_label": "Explore",
        "promo_button_url": null,
        "custom_css": ""
      }
    }
  }
}

theme aktif tema yoksa null olabilir. maintenance: true iken vitrin okunabilir; sepet oluşturma/değiştirme, customer register ve checkout STORE_MAINTENANCE ile durdurulur.

6. Ürünler

GET /storefront/products

Query parametreleri:

Parametre Tip Açıklama
search string Ürün adı veya SKU içinde arama
page integer Sayfa
per_page integer Varsayılan 20, maksimum 100
GET /storefront/products?search=kulaklık&page=1&per_page=24

Ürün örneği:

{
  "id": "PRODUCT_UUID",
  "type": "physical",
  "name": "Kablosuz Kulaklık",
  "slug": "kablosuz-kulaklik",
  "short_description": "Kısa açıklama",
  "description": "Uzun ürün açıklaması",
  "brand": "Originos",
  "image_url": "https://cdn.example.com/product.jpg",
  "categories": [
    {"id": "CATEGORY_UUID", "name": "Elektronik", "slug": "elektronik", "image_url": "https://cdn.example.com/category.jpg"}
  ],
  "options": [
    {
      "id": "OPTION_UUID",
      "name": "Renk",
      "values": [
        {"id": "VALUE_UUID", "value": "Siyah"}
      ]
    }
  ],
  "media": [
    {
      "id": "MEDIA_UUID",
      "type": "image",
      "url": "https://cdn.example.com/product.jpg",
      "alt_text": "Siyah kablosuz kulaklık"
    }
  ],
  "variants": [
    {
      "id": "VARIANT_UUID",
      "sku": "KB-SIYAH",
      "title": "Siyah",
      "price": {"amount": 129900, "currency": "TRY"},
      "option_values": ["Siyah"],
      "available": true
    }
  ]
}

Yalnız active, public ve yayın zamanı gelmiş ürünler döner. Ürün tipleri physical, digital veya epin olabilir. Sepete eklerken ürün ID'si değil variants[].id gönderilir. available: false varyantın satın alma butonu kapatılmalıdır.

GET /storefront/products/{slug}

Listeyle aynı ürün şemasını tek data objesi olarak döndürür. SEO/product detail sayfalarında canonical kimlik olarak slug kullanılabilir.

7. Kategoriler

GET /storefront/categories

Aktif kök kategorileri sort_order sırasıyla ve children alanıyla döndürür. Varsayılan per_page=50, maksimum 100.

{
  "data": [
    {
      "id": "CATEGORY_UUID",
      "name": "Elektronik",
      "slug": "elektronik",
      "description": null,
      "image_url": "https://cdn.example.com/category.jpg",
      "sort_order": 10,
      "parent_id": null,
      "children": []
    }
  ]
}

GET /storefront/categories/{slug}

Kategori bilgisi, çocuk kategoriler ve products alanını döndürür. Doğrudan ürünlerde varyantlar, stok durumu, medya ve birincil image_url bulunur.

8. Kargo seçenekleri

GET /storefront/shipping-methods

{
  "data": [
    {
      "id": "SHIPPING_UUID",
      "name": "Standart Kargo",
      "code": "standard",
      "type": "flat",
      "price": {"amount": 4990, "currency": "TRY"}
    }
  ]
}

Checkout ve hesaplama isteklerinde UUID değil code gönderilir. Sepette fiziksel ürün yoksa kargo otomatik olarak 0 olur.

9. Sepet

Sepet token'ı 64 karakterdir, mağazaya özeldir ve varsayılan olarak 7 gün geçerlidir. Tarayıcıda cookie veya local storage içinde saklanabilir. Customer token ile aynı şey değildir.

Sepet oluşturma

POST /storefront/cart

Body gerekmez.

{
  "data": {
    "id": "CART_UUID",
    "token": "64_CHARACTER_CART_TOKEN",
    "status": "active",
    "currency": "TRY",
    "items": [],
    "subtotal": {"amount": 0, "currency": "TRY"},
    "expires_at": "2026-08-17T12:00:00+03:00"
  }
}

Sepeti getirme

GET /storefront/cart/{token}

Varyant ekleme

POST /storefront/cart/{token}/items
{
  "variant_id": "VARIANT_UUID",
  "quantity": 2
}

quantity 1–100 arasındadır. Aynı varyant yeniden gönderildiğinde yeni satır açılmaz; mevcut satır miktarı verilen değerle değiştirilir.

Sepet item örneği:

{
  "id": 42,
  "product_id": "PRODUCT_UUID",
  "variant_id": "VARIANT_UUID",
  "name": "Kablosuz Kulaklık",
  "quantity": 2,
  "unit_price": {"amount": 129900, "currency": "TRY"},
  "line_total": {"amount": 259800, "currency": "TRY"}
}

Miktar güncelleme

PATCH /storefront/cart/{token}/items/{item}
{"quantity": 3}

Buradaki {item} sepet response'undaki integer item id değeridir.

Satır silme

DELETE /storefront/cart/{token}/items/{item}

Başarılı cevap 204 No Content.

Server-side hesaplama

POST /storefront/cart/{token}/calculate
{
  "coupon_code": "WELCOME10",
  "shipping_method_code": "standard",
  "payment_method": "bank_transfer"
}

Her iki alan da opsiyoneldir.

{
  "data": {
    "currency": "TRY",
    "items": [
      {
        "cart_item_id": 42,
        "product_id": "PRODUCT_UUID",
        "variant_id": "VARIANT_UUID",
        "name": "Kablosuz Kulaklık",
        "quantity": 2,
        "unit_price_amount": 129900,
        "subtotal_amount": 259800,
        "discount_amount": 25980,
        "tax_amount": 0,
        "total_amount": 233820
      }
    ],
    "subtotal": {"amount": 259800, "currency": "TRY"},
    "discount": {"amount": 25980, "currency": "TRY", "code": "WELCOME10"},
    "shipping": {"amount": 4990, "currency": "TRY", "method": "standard"},
    "tax": {"amount": 0, "currency": "TRY"},
    "total": {"amount": 238810, "currency": "TRY"}
  }
}

Frontend fiyat, indirim, kargo, vergi veya total üretmemelidir. Gösterilen nihai tutarlar her zaman bu endpointten veya checkout response'undan alınmalıdır.

10. Checkout

POST /storefront/checkout
Idempotency-Key: 0194f25b-6e24-7d12-a843-29f14e9bc542

Guest checkout body:

{
  "cart_token": "64_CHARACTER_CART_TOKEN",
  "email": "buyer@example.com",
  "phone": "+905551112233",
  "billing_address": {
    "first_name": "Ali",
    "last_name": "Yılmaz",
    "country": "TR",
    "city": "İstanbul",
    "address_line_1": "Örnek Mah. No: 1"
  },
  "shipping_address": {
    "first_name": "Ali",
    "last_name": "Yılmaz",
    "country": "TR",
    "city": "İstanbul",
    "address_line_1": "Örnek Mah. No: 1"
  },
  "coupon_code": "WELCOME10",
  "shipping_method_code": "standard"
}

Kurallar:

Guest checkout response'unda guest_access_token yalnız sipariş ilk oluşturulduğunda düz metin olarak döner. Güvenli biçimde saklanmalıdır:

{
  "data": {
    "order_id": "ORDER_UUID",
    "order_number": "100001",
    "status": "pending",
    "payment_status": "pending",
    "fulfillment_status": "unfulfilled",
    "subtotal": {"amount": 259800, "currency": "TRY"},
    "discount": {"amount": 25980, "currency": "TRY", "code": "WELCOME10"},
    "shipping": {"amount": 4990, "currency": "TRY"},
    "tax": {"amount": 0, "currency": "TRY"},
    "total": {"amount": 238810, "currency": "TRY"},
    "items": [],
    "placed_at": "2026-08-10T12:00:00+03:00",
    "created_at": "2026-08-10T12:00:00+03:00",
    "guest_access_token": "ONE_TIME_GUEST_ORDER_TOKEN"
  }
}

Siparişe bank_transfer provider'ı eklenir ve ödeme durumu yönetici tahsilatı onaylayana kadar pending kalır. Tema kart bilgisi veya payment status üretmemeli; banka adı, hesap sahibi, IBAN, şube ve açıklamayı storefront config'ten göstermelidir.

11. Customer kayıt ve login

Kayıt

POST /storefront/customer/auth/register
{
  "first_name": "Ayşe",
  "last_name": "Demir",
  "email": "ayse@example.com",
  "phone": "+905551112233",
  "password": "Secure123",
  "password_confirmation": "Secure123",
  "device_name": "web-storefront"
}

Parola en az 8 karakter, en az bir harf ve bir rakam içermelidir. E-posta benzersizliği mağaza bazındadır.

201 yanıtı:

{
  "data": {
    "token": "1|CUSTOMER_TOKEN",
    "token_type": "Bearer",
    "customer": {
      "id": "CUSTOMER_UUID",
      "first_name": "Ayşe",
      "last_name": "Demir",
      "email": "ayse@example.com",
      "phone": "+905551112233",
      "created_at": "2026-08-10T12:00:00+03:00"
    }
  }
}

Login

POST /storefront/customer/auth/login
{
  "email": "ayse@example.com",
  "password": "Secure123",
  "device_name": "web-storefront"
}

Aynı device_name ile yeniden login olunduğunda önceki aynı adlı token iptal edilir.

Profil

GET /storefront/customer/me
Authorization: Bearer CUSTOMER_TOKEN

Logout

POST /storefront/customer/auth/logout
Authorization: Bearer CUSTOMER_TOKEN

Yalnız aktif token iptal edilir.

12. Customer adresleri

Customer bearer token gerektirir.

Adres şeması:

{
  "type": "both",
  "label": "Ev",
  "first_name": "Ayşe",
  "last_name": "Demir",
  "company": null,
  "phone": "+905551112233",
  "address_line_1": "Örnek Mah. No: 1",
  "address_line_2": "Daire 4",
  "city": "İstanbul",
  "state": "Kadıköy",
  "postal_code": "34710",
  "country": "TR",
  "is_default": true
}

type: billing, shipping veya both. Aynı tipte yeni bir adres is_default: true yapıldığında önceki varsayılan adres otomatik kaldırılır.

İşlem İstek
Liste GET /storefront/customer/addresses
Oluştur POST /storefront/customer/addresses
Detay GET /storefront/customer/addresses/{address}
Tam güncelleme PUT /storefront/customer/addresses/{address}
Kısmi güncelleme PATCH /storefront/customer/addresses/{address}
Sil DELETE /storefront/customer/addresses/{address}

Başka müşterinin adresi güvenlik amacıyla 404 döner.

13. Sipariş görüntüleme

Registered customer siparişleri

GET /storefront/customer/orders?page=1&per_page=20
Authorization: Bearer CUSTOMER_TOKEN
GET /storefront/customer/orders/{order}
Authorization: Bearer CUSTOMER_TOKEN

Customer yalnız kendi siparişlerini görebilir.

Guest sipariş

GET /storefront/guest/orders/{order}
X-Order-Token: GUEST_ACCESS_TOKEN

Guest token yalnız checkout sırasında düz metin döner ve yalnız o sipariş için geçerlidir.

Sipariş durum alanları:

Order detail, ürün satırlarını ve yüklenmişse dijital downloads listesini döndürür. Müşteri response'unda yöneticiye özel payment transaction, fatura adresi ve dahili operasyon alanları gösterilmez.

14. Dijital ürün indirme

Ödeme ve fulfillment tamamlandıktan sonra customer veya guest order detail içindeki downloads[].download_url kullanılır:

{
  "id": "GRANT_UUID",
  "file": {
    "id": "FILE_UUID",
    "name": "E-kitap",
    "original_name": "kitap.pdf",
    "mime_type": "application/pdf",
    "size": 4829102
  },
  "download_url": "https://originos.netkora.com/api/v1/storefront/downloads/...?...",
  "download_count": 0,
  "max_downloads": 5,
  "expires_at": "2026-09-10T12:00:00+03:00"
}

download_url kısa süreli signed URL'dir ve olduğu gibi çağrılmalıdır. Registered customer grant'ında ayrıca customer bearer token gönderilir. Guest grant'ında URL içindeki signature ve token yeterlidir. Başarılı yanıt JSON değil dosya stream'idir.

Frontend URL süresi dolduğunda order detail'i yeniden çağırarak yeni signed URL almalıdır.

15. Hata formatları

Domain hatası:

{
  "message": "Cart has expired.",
  "code": "CART_EXPIRED"
}

Validation hatası:

{
  "message": "The given data was invalid.",
  "errors": {
    "billing_address.city": [
      "The billing address.city field is required."
    ]
  }
}

Önemli storefront hata kodları:

HTTP Kod Frontend davranışı
401 API_KEY_INVALID Yapılandırma hatası; anahtarı kontrol et
401 API_KEY_REVOKED / API_KEY_EXPIRED Yeni public key gerekir
403 API_KEY_ABILITY_DENIED Key ability kapsamı eksik
403 CUSTOMER_ACCESS_FORBIDDEN Customer session'ı temizle, login göster
401 INVALID_CREDENTIALS Login formunda genel hata göster
403 CUSTOMER_AUTH_REQUIRED Guest checkout kapalı; login/register göster
403 GUEST_ORDER_ACCESS_DENIED Guest order token yanlış/eksik
403 SUBSCRIPTION_EXPIRED Satın almayı durdur, mağaza desteği göster
403 STORE_SUSPENDED / STORE_DISABLED Mağaza kullanılamıyor ekranı
503 STORE_MAINTENANCE Bakım sayfası; daha sonra retry
404 STORE_NOT_FOUND Store key/domain yapılandırmasını kontrol et
404 kaynak bulunamadı Mağaza dışı veya yayından kalkmış kaynak
409 IDEMPOTENCY_KEY_REUSED Yeni body için yeni checkout key üret
422 IDEMPOTENCY_KEY_REQUIRED Geçerli key ile isteği tekrar gönder
425 REQUEST_IN_PROGRESS Kısa bekle, aynı key/body ile retry
422 CART_EMPTY Sepete yönlendir
422 CART_EXPIRED Yeni sepet oluştur
422 CURRENCY_MISMATCH Sepeti yeniden oluştur veya ürünü çıkar
422 INSUFFICIENT_STOCK Stok mesajı göster, sepeti yenile
422 EPIN_OUT_OF_STOCK Dijital kod stoğu yok mesajı
422 INVALID_COUPON / COUPON_EXPIRED Kuponu kaldır ve yeniden hesapla
422 COUPON_USAGE_LIMIT_REACHED Kupon kullanım sınırı mesajı
422 COUPON_MINIMUM_NOT_MET Minimum sepet tutarını göster
422 INVALID_SHIPPING_METHOD Kargo listesini yenile
422 PAYMENT_METHOD_UNAVAILABLE Ödeme ayarlarını yenile; etkin yöntem göster
403 DOWNLOAD_FORBIDDEN Doğru customer hesabıyla login iste
403 DOWNLOAD_TOKEN_INVALID Order detail'den yeni URL al
403 DOWNLOAD_EXPIRED / DOWNLOAD_REVOKED İndirme hakkı kullanılamıyor
403 DOWNLOAD_LIMIT_REACHED İndirme limiti doldu
404 DIGITAL_FILE_NOT_FOUND Destek mesajı göster
429 rate limit Backoff ve retry uygula

Her API response'unda X-Request-ID header'ı bulunur. Hata ekranında veya loglarda bu değer saklanmalı; destek taleplerinde paylaşılmalıdır.

16. Önerilen storefront akışı

  1. Uygulama açılışında GET /storefront/store çağır.
  2. Locale, currency, SEO, announcement ve tema config'ini uygula.
  3. GET /storefront/categories ile navigasyonu oluştur.
  4. GET /storefront/products ile kataloğu, slug endpointiyle ürün detayını göster.
  5. İlk sepete eklemede POST /storefront/cart çağır ve token'ı sakla.
  6. Varyantları POST /cart/{token}/items ile ekle.
  7. Checkout ekranında kargo yöntemlerini al ve her değişiklikte /calculate çağır.
  8. Customer login olmuşsa bearer token ekle; değilse guest checkout politikasına göre devam et.
  9. Yeni UUID Idempotency-Key ile checkout çağır.
  10. Guest siparişte dönen guest_access_token değerini güvenli sakla.
  11. Sipariş detayını customer veya guest endpointinden takip et.
  12. Dijital ürünlerde order detail'deki signed download URL'lerini kullan.

17. Frontend güvenlik kontrol listesi

18. CORS

Storefront domain'i production ortamında CORS_ALLOWED_ORIGINS listesine eklenmelidir. İzin verilen request header'ları:

Accept
Authorization
Content-Type
Idempotency-Key
X-Order-Token
X-Request-ID
X-Store-Key

X-Request-ID browser tarafından okunabilir. Cookie credential kullanılmaz; customer auth bearer token ile çalışır.

19. API artifact'leri

OpenAPI dosyası code generation ve şema inceleme; Postman collection ise gerçek akışları sırayla çalıştırmak için kullanılabilir.

20. Tema teslim kriterleri

Bir tema Originos'a hazır kabul edilmeden önce: