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
- Tarihler ISO 8601 formatındadır.
- Public kaynak kimlikleri UUID'dir. Sepet item
iddeğeri integer olabilir. - Liste endpointleri genel olarak
?page=1&per_page=20kabul eder. per_pageen fazla100olabilir.- Sayfalı yanıtlar Laravel resource formatındadır:
{
"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:
Idempotency-Keyzorunlu ve 16–255 karakterdir. Her yeni checkout denemesi için UUID önerilir.- Network timeout veya belirsiz cevapta aynı body ve aynı key ile retry yapılır.
- Aynı key farklı body ile kullanılırsa
409 IDEMPOTENCY_KEY_REUSEDdöner. - Registered checkout için aynı isteğe
Authorization: Bearer {customer_token}eklenir. Backend email'i müşteri hesabından alır. billing_addresszorunludur.countryiki harf ISO ülke kodudur.shipping_address,coupon_code,shipping_method_code,payment_methodvephoneopsiyoneldir.payment_methodgönderilmezsesettings.payments.default_methodkullanılır.bank_transfervepaytrdesteklenir. PayTR seçildiğinde sipariş oluşturulduktan sonra/storefront/payments/paytr/tokençağrılarak güvenli iframe URL'si alınır; sipariş durumu yalnız PayTR callback'i sonrasında değişir.- Backend cart fiyatlarını yeniden okur, kuponu/kargoyu yeniden doğrular, fiziksel stok ile EPIN stoklarını transaction içinde rezerve eder.
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ı:
status:pending,confirmed,processing,completed,cancelledpayment_status:pending,authorized,paid,failed,partially_refunded,refundedfulfillment_status:unfulfilled,partial,fulfilled,cancelled
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ışı
- Uygulama açılışında
GET /storefront/storeçağır. - Locale, currency, SEO, announcement ve tema config'ini uygula.
GET /storefront/categoriesile navigasyonu oluştur.GET /storefront/productsile kataloğu, slug endpointiyle ürün detayını göster.- İlk sepete eklemede
POST /storefront/cartçağır ve token'ı sakla. - Varyantları
POST /cart/{token}/itemsile ekle. - Checkout ekranında kargo yöntemlerini al ve her değişiklikte
/calculateçağır. - Customer login olmuşsa bearer token ekle; değilse guest checkout politikasına göre devam et.
- Yeni UUID
Idempotency-Keyile checkout çağır. - Guest siparişte dönen
guest_access_tokendeğerini güvenli sakla. - Sipariş detayını customer veya guest endpointinden takip et.
- Dijital ürünlerde order detail'deki signed download URL'lerini kullan.
17. Frontend güvenlik kontrol listesi
- Yalnız
pk_...public store key'i client tarafında kullan. - Secret API key, merchant token veya platform token'ını temaya gömme.
- API'den gelen HTML metnini sanitize et; ürün açıklamasını kontrolsüz
innerHTMLile basma. custom_cssyalnız mağaza yöneticisinin güvenilen girdisi olarak ele alınmalı,<style>.textContentile uygulanmalı ve HTML/script olarak çalıştırılmamalıdır.- Tema asset URL'lerini yalnız güvenilen Originos/CDN kaynaklarından yükle ve mümkünse CSP allowlist kullan.
- Customer token'ını üçüncü taraf scriptlere aktarma.
- Checkout butonunu çift tıklamaya karşı kilitle; network retry'da aynı idempotency key'i koru.
- Fiyatları client tarafında otorite kabul etme.
- Guest order token'ını URL path, analytics event veya public log içine yazma.
available: falsevaryantları sepete göndermeden engelle; backend kontrolünü yine de esas kabul et.X-Request-ID, hatacodeve HTTP status değerlerini gözlemlenebilirlik için kaydet.
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:
https://originos.netkora.com/docs/openapi.yaml - Postman Collection:
https://originos.netkora.com/docs/postman/collection.json - Production Environment:
https://originos.netkora.com/docs/postman/production-environment.json - Bu rehberin Markdown sürümü:
https://originos.netkora.com/docs/storefront-theme-api.md - Tarayıcıda okunabilir sürüm:
https://originos.netkora.com/docs/storefront-theme-api
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:
- Theme Contract
1.5.0içindeki 84 ayarın tamamıyla çalışmalı. Müşteri hesabı ayarlarına ek olarak favori drawer'ı, cihazda saklanan son görüntülenen ürünler, indirim/karşılaştırma fiyatı ve mobil sticky satın alma seçenekleri desteklenmelidir. homepage.section_ordersırasını, kapalı bölümleri ve bölüm limitlerini dikkate almalı.- Banka havalesi ekranı
settings.payments.bank_transferalanlarını göstermeli; PayTR varsayılan olduğunda resmi PayTR logosu footer'da görünmeli ve ödeme PayTR güvenli iframe'i içinde açılmalıdır. - Tema değiştirme sonrası ek config migration istememeli.
theme: nulldurumunda güvenli fallback göstermeli.- Mobile, tablet ve desktop responsive olmalı.
- Ürün tipi
physical,digitalveepiniçin uygun durumları göstermeli. - Varyant
availabledurumunu dikkate almalı. - Boş katalog, boş kategori, boş sepet, bakım ve API hata ekranları bulunmalı.
- Guest ve registered checkout akışları çalışmalı.
- Minor-unit para değerleri doğru formatlanmalı.
- Loading, retry ve rate-limit durumları yönetilmeli.
- Customer order ve signed digital download akışları doğrulanmalı.
- Secret credential içermemeli.