Mağazalar
- Taban yol
/api/v1/physical-pos- Kimlik
- Her istekte Ed25519 istek imzası —
X-Key-Id,X-Date,X-Nonce,X-Signature; gövdeli isteklerde ayrıcaDigest. Zaman penceresi ±5 dk, nonce tek kullanımlık. Bearer jetonu ya da panel oturumu bu uçlarda kabul edilmez. - Yetki
- Anahtarınız Fiziksel POS ürününü (
PHYSICAL_POS) ve bu sayfadaki uçların kapsamını taşımalıdır:physical_pos:view·physical_pos:manage. Ürünü olmayan anahtar403 PRODUCT_NOT_ENABLED, kapsamı olmayan anahtar403 API_INSUFFICIENT_SCOPEalır. Bkz. Kimlik Doğrulama ve Kapsamlar. - Çapraz yüzey
- Bu uçlar s2s yüzeyindedir; kendi sunucunuzdan imzalı istekle çağırırsınız. Aynı kayıtların panelde ekranları var, ama panel uçları API anahtarıyla çağrılamaz; bu uçlar da panel oturumuyla çağrılamaz.
Mağaza, işletmenizin bir satış noktasıdır. Kasalar mağazaya bağlıdır: → Kasalar. Mağazalar ortamsızdır; test anahtarı mağazaları yalnız okuyabilir, yazma uçları test anahtarıyla 403 physical_pos.environment.test_key_read_only alır. → Ortamlar
| Yöntem | Yol | Kapsam |
|---|---|---|
GET | /api/v1/physical-pos/stores | physical_pos:view |
POST | /api/v1/physical-pos/stores | physical_pos:manage |
GET | /api/v1/physical-pos/stores/{storeId} | physical_pos:view |
PATCH | /api/v1/physical-pos/stores/{storeId} | physical_pos:manage |
POST | /api/v1/physical-pos/stores/{storeId}/archive | physical_pos:manage |
POST | /api/v1/physical-pos/stores/{storeId}/restore | physical_pos:manage |
GET | /api/v1/physical-pos/stores/{storeId}/audit | physical_pos:view |
cURL örnekleri imzayı lunixi-sign.sh ile hesaplar: Kimlik Doğrulama › İmza yardımcısı.
Mağaza nesnesi
| Alan | Tip | Açıklama |
|---|---|---|
id | string (UUID) | Mağazanın kimliği. |
code | string | Mağaza kodu; büyük harfli, organizasyonunuzda tekil. Oluşturulduktan sonra değişmez. |
name | string | Mağaza adı. |
city | string | null | Şehir. |
district | string | null | İlçe. |
addressLine | string | null | Adres satırı. |
timezone | string | IANA saat dilimi, ör. Europe/Istanbul. |
storeStatus | string | ACTIVE ya da ARCHIVED. |
externalRef | string | null | Kendi sisteminizdeki mağaza kimliği; organizasyonunuzda tekil. |
rowVersion | integer | Eşzamanlılık sürümü. → rowVersion |
createdAt | string | Oluşturulma zamanı. |
updatedAt | string | Son değişiklik zamanı. |
Mağazaları listeleme
GET /api/v1/physical-pos/stores
| Sorgu parametresi | Tip | Açıklama |
|---|---|---|
status | string | ACTIVE ya da ARCHIVED. Gönderilmezse ikisi de döner. Başka değer 400 physical_pos.input.filter_invalid. |
q | string | Mağaza kodunun ya da adının başıyla eşleşen kayıtlar, en çok 64 karakter. |
limit | integer | Sayfa başına kayıt, 1–100. Varsayılan 25. |
cursor | string | Önceki yanıttaki pageInfo.nextCursor. |
includeTotal | boolean | true ise pageInfo.totalCount doldurulur. |
Liste satırları mağaza nesnesinin alanlarına ek olarak registerCount (mağazanın aktif kasa sayısı) taşır.
source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/stores?status=ACTIVE&q=IST&limit=50"
lunixi_sign GET "$REQ_PATH"
curl "https://api-gateway.lunixi.com$REQ_PATH" \
-H "X-Key-Id: $LUNIXI_KEY_ID" \
-H "X-Date: $DATE" \
-H "X-Nonce: $NONCE" \
-H "X-Signature: $SIGNATURE"{
"status": "success",
"code": "SUCCESS",
"data": {
"items": [
{
"id": "00000000-0000-0000-0000-000000000101",
"code": "IST-KADIKOY",
"name": "Kadıköy Mağazası",
"city": "İstanbul",
"district": "Kadıköy",
"addressLine": "Örnek Cad. No: 1",
"timezone": "Europe/Istanbul",
"storeStatus": "ACTIVE",
"externalRef": "store_00042",
"rowVersion": 2,
"createdAt": "2026-01-01T07:00:00.000Z",
"updatedAt": "2026-01-05T09:30:00.000Z",
"registerCount": 3
}
],
"pageInfo": { "hasMore": false, "nextCursor": null, "totalCount": null }
},
"pageInfo": { "hasMore": false, "nextCursor": null, "totalCount": null },
"statusCode": 200,
"requestId": "00000000-0000-0000-0000-000000000000"
}Mağaza oluşturma
POST /api/v1/physical-pos/stores · Idempotency-Key zorunlu
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
code | string | Evet | Mağaza kodu: A-Z, 0-9, ., _, -; en çok 64 karakter. Büyük harfe çevrilir. → Kod kuralları |
name | string | Evet | Mağaza adı, en çok 200 karakter. |
city | string | Hayır | Şehir, en çok 100 karakter. |
district | string | Hayır | İlçe, en çok 100 karakter. |
addressLine | string | Hayır | Adres satırı, en çok 300 karakter. |
timezone | string | Hayır | IANA saat dilimi. Varsayılan Europe/Istanbul. → Saat dilimi |
externalRef | string | Hayır | Kendi sisteminizdeki kimlik: boşluksuz yazdırılabilir ASCII, en çok 128 karakter. Olduğu gibi saklanır. |
Serbest metin alanları metin kurallarına tabidir.
source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/stores"
BODY='{"code":"ist-kadikoy","name":"Kadıköy Mağazası","city":"İstanbul","district":"Kadıköy","addressLine":"Örnek Cad. No: 1","externalRef":"store_00042"}'
lunixi_sign POST "$REQ_PATH" "$BODY"
curl -X POST "https://api-gateway.lunixi.com$REQ_PATH" \
-H "Content-Type: application/json" \
-H "X-Key-Id: $LUNIXI_KEY_ID" \
-H "X-Date: $DATE" \
-H "X-Nonce: $NONCE" \
-H "Digest: $DIGEST" \
-H "X-Signature: $SIGNATURE" \
-H "Idempotency-Key: 4f9b2c1e-0000-4000-8000-000000000001" \
--data-raw "$BODY"Yeni mağazada 201, aynı anahtar ve aynı gövdeyle tekrarda 200 ve replayed: true döner:
{
"status": "success",
"code": "SUCCESS",
"data": {
"store": {
"id": "00000000-0000-0000-0000-000000000101",
"code": "IST-KADIKOY",
"name": "Kadıköy Mağazası",
"city": "İstanbul",
"district": "Kadıköy",
"addressLine": "Örnek Cad. No: 1",
"timezone": "Europe/Istanbul",
"storeStatus": "ACTIVE",
"externalRef": "store_00042",
"rowVersion": 1,
"createdAt": "2026-01-01T07:00:00.000Z",
"updatedAt": "2026-01-01T07:00:00.000Z"
},
"replayed": false
},
"statusCode": 201,
"requestId": "00000000-0000-0000-0000-000000000000"
}Mağaza kodu ve externalRef arşivli mağazalar dahil tekildir: arşivlediğiniz bir mağazanın kodunu yeni mağazada kullanamazsınız. Mağazayı yeniden kullanmak istiyorsanız yeniden açın.
Mağaza ayrıntısı
GET /api/v1/physical-pos/stores/{storeId}
{
"status": "success",
"code": "SUCCESS",
"data": {
"store": {
"id": "00000000-0000-0000-0000-000000000101",
"code": "IST-KADIKOY",
"name": "Kadıköy Mağazası",
"city": "İstanbul",
"district": "Kadıköy",
"addressLine": "Örnek Cad. No: 1",
"timezone": "Europe/Istanbul",
"storeStatus": "ACTIVE",
"externalRef": "store_00042",
"rowVersion": 2,
"createdAt": "2026-01-01T07:00:00.000Z",
"updatedAt": "2026-01-05T09:30:00.000Z"
},
"registerSummary": { "activeCount": 3, "archivedCount": 1 },
"assignedDeviceCount": 0
},
"statusCode": 200,
"requestId": "00000000-0000-0000-0000-000000000000"
}| Alan | Açıklama |
|---|---|
store | Mağaza nesnesi. |
registerSummary.activeCount | Aktif kasa sayısı. |
registerSummary.archivedCount | Arşivli kasa sayısı. |
assignedDeviceCount | Mağazaya (ve kasalarına) atanmış cihaz sayısı. |
Olmayan, başka bir organizasyona ait ya da biçim dışı kimlik 404 physical_pos.store.not_found döner.
Mağaza güncelleme
PATCH /api/v1/physical-pos/stores/{storeId}
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
rowVersion | integer | Evet | Son okuduğunuz rowVersion. |
name | string | Hayır | Yeni ad. |
city | string | null | Hayır | null alanı temizler. |
district | string | null | Hayır | null alanı temizler. |
addressLine | string | null | Hayır | null alanı temizler. |
timezone | string | Hayır | Yeni IANA saat dilimi. |
externalRef | string | null | Hayır | null alanı temizler. |
- Gönderilmeyen alan değişmez.
codedeğiştirilemez; gövdedecodegönderilirse400 VALIDATION_ERROR. - Değişecek alan içermeyen istek
400 physical_pos.input.empty_patchalır. - Gönderilen değerler mevcut değerlerle aynıysa kayıt değişmez,
rowVersionartmaz ve değişiklik geçmişine olay yazılmaz. - Arşivli mağaza güncellenemez:
409 physical_pos.store.archived. Önce yeniden açın.
source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/stores/00000000-0000-0000-0000-000000000101"
BODY='{"rowVersion":2,"name":"Kadıköy Moda Mağazası","addressLine":null}'
lunixi_sign PATCH "$REQ_PATH" "$BODY"
curl -X PATCH "https://api-gateway.lunixi.com$REQ_PATH" \
-H "Content-Type: application/json" \
-H "X-Key-Id: $LUNIXI_KEY_ID" \
-H "X-Date: $DATE" \
-H "X-Nonce: $NONCE" \
-H "Digest: $DIGEST" \
-H "X-Signature: $SIGNATURE" \
--data-raw "$BODY"Yanıt: { "store": { … } } — güncel mağaza nesnesi, yeni rowVersion ile.
Mağaza arşivleme
POST /api/v1/physical-pos/stores/{storeId}/archive
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
rowVersion | integer | Evet | Son okuduğunuz rowVersion. |
reasonCode | string | Evet | STORE_CLOSED, TEMPORARILY_CLOSED, RELOCATED, MERGED, CREATED_IN_ERROR, DATA_CORRECTION, OTHER. → Gerekçe kodları |
Mağaza arşivlendiğinde aktif kasaları da aynı işlemde arşivlenir. Yanıt, arşivlenen kasa sayısını da verir:
source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/stores/00000000-0000-0000-0000-000000000101/archive"
BODY='{"rowVersion":3,"reasonCode":"STORE_CLOSED"}'
lunixi_sign POST "$REQ_PATH" "$BODY"
curl -X POST "https://api-gateway.lunixi.com$REQ_PATH" \
-H "Content-Type: application/json" \
-H "X-Key-Id: $LUNIXI_KEY_ID" \
-H "X-Date: $DATE" \
-H "X-Nonce: $NONCE" \
-H "Digest: $DIGEST" \
-H "X-Signature: $SIGNATURE" \
--data-raw "$BODY"{
"status": "success",
"code": "SUCCESS",
"data": {
"store": {
"id": "00000000-0000-0000-0000-000000000101",
"code": "IST-KADIKOY",
"storeStatus": "ARCHIVED",
"rowVersion": 4
},
"archivedRegisterCount": 3
},
"statusCode": 200,
"requestId": "00000000-0000-0000-0000-000000000000"
}Örnekte mağaza nesnesi kısaltılmıştır; yanıt bütün alanları içerir.
| Engel | Hata |
|---|---|
| Mağazaya ya da kasalarından birine atanmış cihaz var | 409 physical_pos.store.has_devices — cihazları başka mağazaya taşıyın, depoya alın ya da emekliye ayırın. |
| Mağazanın 200'den fazla aktif kasası var | 409 physical_pos.store.too_many_active_registers (details.limit: 200) — önce kasaları tek tek arşivleyin. |
| Mağaza zaten arşivli | 409 physical_pos.store.invalid_transition |
Mağazayı yeniden açma
POST /api/v1/physical-pos/stores/{storeId}/restore
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
rowVersion | integer | Evet | Son okuduğunuz rowVersion. |
reasonCode | string | Evet | REOPENED, ARCHIVED_IN_ERROR, DATA_CORRECTION, OTHER. |
Arşivli mağaza ACTIVE olur; kodu ve externalRef değeri korunur. Kasalar arşivli kalır; ihtiyacınız olanları tek tek yeniden açın. Mağaza zaten aktifse 409 physical_pos.store.invalid_transition.
Yanıt: { "store": { … } }.
Değişiklik geçmişi
GET /api/v1/physical-pos/stores/{storeId}/audit
| Sorgu parametresi | Tip | Açıklama |
|---|---|---|
limit | integer | Sayfa başına olay, 1–100. Varsayılan 25. |
cursor | string | Önceki yanıttaki pageInfo.nextCursor. |
{
"status": "success",
"code": "SUCCESS",
"data": {
"items": [
{
"id": "00000000-0000-0000-0000-000000000901",
"action": "physical_pos.audit.store_updated",
"actorType": "API_KEY",
"actorId": "kid:mk_live_00000000",
"reasonCode": null,
"changes": {
"storeId": "00000000-0000-0000-0000-000000000101",
"storeNo": "IST-KADIKOY",
"nameChanged": true
},
"requestId": "00000000-0000-0000-0000-000000000000",
"createdAt": "2026-01-05T09:30:00.000Z"
}
],
"pageInfo": { "hasMore": false, "nextCursor": null, "totalCount": null }
},
"pageInfo": { "hasMore": false, "nextCursor": null, "totalCount": null },
"statusCode": 200,
"requestId": "00000000-0000-0000-0000-000000000000"
}Mağaza olayları: physical_pos.audit.store_created, …store_updated, …store_archived, …store_restored. Alanların anlamı: Ortak Kurallar › Değişiklik geçmişi.
Hatalar
| HTTP | code | Ne zaman |
|---|---|---|
400 | physical_pos.idempotency.key_required / physical_pos.idempotency.key_invalid | Oluşturmada Idempotency-Key yok ya da biçim dışı. |
400 | physical_pos.input.code_invalid | code biçim dışı. |
400 | physical_pos.input.text_invalid | Serbest metin kurala uymuyor. |
400 | physical_pos.input.ref_invalid | externalRef biçim dışı. |
400 | physical_pos.input.reason_code_invalid | reasonCode listede yok ya da işleme uymuyor. |
400 | physical_pos.validation.invalid | Tanınmayan saat dilimi. |
400 | physical_pos.input.empty_patch | Boş güncelleme. |
400 | physical_pos.cursor.invalid | Bozuk imleç. |
400 | physical_pos.input.filter_invalid | Liste süzgeci geçersiz. |
403 | physical_pos.environment.test_key_read_only | Yazma isteği test anahtarıyla yapıldı. |
404 | physical_pos.store.not_found | Mağaza yok ya da size ait değil. |
409 | physical_pos.store.code_taken | Kod kullanımda (arşivli mağazalar dahil). |
409 | physical_pos.store.external_ref_taken | externalRef kullanımda (arşivli mağazalar dahil). |
409 | physical_pos.store.archived | Arşivli mağaza güncellenmek istendi. |
409 | physical_pos.store.has_devices | Cihaz atanmış mağaza arşivlenmek istendi. |
409 | physical_pos.store.too_many_active_registers | Aktif kasa sayısı tek seferde arşivleme sınırını aşıyor. |
409 | physical_pos.store.invalid_transition | Arşivli mağazayı arşivleme ya da aktif mağazayı yeniden açma. |
409 | physical_pos.version_conflict | rowVersion güncel değil. |
409 | physical_pos.idempotency_mismatch | Aynı Idempotency-Key farklı bir istekle kullanılmış. |
429 | RATE_LIMITED | Mağaza ve kasa yazma sınırı aşıldı. → Oran sınırı |
Bütün kodlar: Hata Kodları.