Ortak Kurallar
Bu sayfadaki kurallar Fiziksel POS yönetim API'sinin bütün uçlarında geçerlidir. Uç sayfaları bu kurallara bağlantı verir.
Yanıt zarfı
Başarılı yanıtta veri data altındadır. Bu API'de tek kayıt dönen her uç kaydı varlık adıyla sarar; ilişkili veriler kardeş alanlarda durur:
| Uç türü | data biçimi | Örnek |
|---|---|---|
| Tek kayıt okuma, güncelleme, durum değişikliği | { <varlık> } ve varsa ilişkili alanlar | { "store": { … } }, { "terminal": { … }, "acquirers": { … } } |
| Oluşturma | { <varlık>, replayed } | { "register": { … }, "replayed": false } |
| Liste | { items, pageInfo } | { "items": [ … ], "pageInfo": { … } } |
| Katalog listesi | Dizi | [ { … }, { … } ] |
{
"status": "success",
"code": "SUCCESS",
"data": {
"store": {
"id": "00000000-0000-0000-0000-000000000101",
"code": "IST-KADIKOY",
"name": "Kadıköy Mağazası",
"storeStatus": "ACTIVE",
"rowVersion": 1
},
"replayed": false
},
"statusCode": 201,
"requestId": "00000000-0000-0000-0000-000000000000"
}Örnekte mağaza nesnesi kısaltılmıştır; yanıt bütün alanları içerir.
- Oluşturma uçları yeni kayıtta
201, aynıIdempotency-Keyile yapılan tekrarda200döner. → Idempotency-Key - Liste uçlarında
pageInfozarfın üst düzeyinde de bulunur; iki kopya aynıdır. - Örneklerde kısalık için gösterilmeyen zarf alanları (
message,timestamp…) da yanıtta bulunur. Zarfın bütün alanları ve hata zarfı: Hata Yönetimi. - Hata durumunda
message'a göre değilcode'a göre dallanın. Bu ürünün kodları: Hata Kodları. physical_pos.*hatalarında yanıtdocsUrlalanı taşır; bağlantı, Hata Kodları sayfasında o kodun satırına gider.- Hata ayrıntısı
detailsiçindedir: tek alanlı hatalardadetails.fieldvedetails.reason; birden çok alanı kapsayan doğrulama hatasında (physical_pos.validation.invalid)details.errorsdizisi, her öğe{ field, errors: [<sebep>] }. Gönderdiğiniz değerdetails'te yankılanmaz.
Alan kuralları
| Kural | Ayrıntı |
|---|---|
| Kimlikler | Bütün kimlikler (id, storeId, terminalId …) UUID'dir. Yoldaki biçim dışı kimlik, olmayan kayıtla aynı 404 cevabını alır. |
| Zamanlar | ISO 8601, UTC (2026-01-01T07:00:00.000Z). |
| Boş değer | İsteğe bağlı bir alanın değeri yoksa alan yanıtta null olarak bulunur. |
| Durum alanları | Durum alanları varlığa göre adlandırılır: storeStatus, registerStatus, terminalStatus, acquirerStatus, lifecycleStatus. |
| Bilinmeyen alan | Tanımlanmamış gövde alanı ya da sorgu parametresi her uçta 400 VALIDATION_ERROR döner. |
| Ortam | Sorguda ya da gövdede environment gönderilirse istek 400 physical_pos.input.environment_invalid alır (details.reason: not_allowed). Organizasyon ve ortam yalnız anahtarınızdan çözülür. → Ortamlar |
| Boş güncelleme | Değişecek alan içermeyen PATCH isteği 400 physical_pos.input.empty_patch alır. Değerleri mevcutla aynı olan PATCH hata değildir: 200 döner, kayıt değişmez, rowVersion artmaz ve değişiklik geçmişine olay yazılmaz. |
| Liste süzgeçleri | Geçersiz süzgeç değeri (küme dışı durum, biçim dışı kimlik ya da kod, kurala uymayan ya da 64 karakteri aşan q) 400 physical_pos.input.filter_invalid alır; details.field süzgecin adını verir. Değer kümeleri büyük/küçük harfe duyarlıdır. |
Sayfalama
Liste uçları cursor tabanlı sayfalama kullanır:
| Parametre | Açıklama |
|---|---|
limit | Sayfa başına kayıt, 1–100. Varsayılan 25. Aralık dışı değer 400 VALIDATION_ERROR döner. |
cursor | Önceki yanıttaki pageInfo.nextCursor. İlk sayfada gönderilmez. |
includeTotal | Kayıt listelerinde (mağazalar, kasalar, terminaller, banka satırları, cihazlar). true ise pageInfo.totalCount doldurulur. Geçmiş listeleri (…/audit, …/assignments, …/links) bu parametreyi almaz. |
"pageInfo": { "hasMore": true, "nextCursor": "eyJ0IjoiMjAyNi0…", "totalCount": null }- Sıralama her listede en yeni kayıt önce (
createdAtazalan, eşitlikteidazalan) ve değiştirilemez. pageInfo.hasMoretrueise sonraki sayfayıcursor=<nextCursor>ile isteyin; son sayfadanextCursornull'dır.totalCount,includeTotal=truegöndermediğiniz sürecenull'dır. Toplam sayı hesaplaması maliyetlidir; ilerlemek içinhasMoreyeterlidir.- İmleci kendiniz üretmeyin ve değiştirmeyin. Bozuk imleç
400 physical_pos.cursor.invaliddöner; ilk sayfadan yeniden başlayın. - Süzgeçleri değiştirdiğinizde imleci sıfırlayın.
Katalog uçları sayfalanmaz; bütün liste tek yanıtta dizi olarak döner.
Idempotency-Key
Kayıt oluşturan uçlar, ağ hatasından sonra güvenle tekrar deneyebilmeniz için Idempotency-Key başlığı ister:
| Uç | İşlem |
|---|---|
POST /stores | Mağaza oluşturma |
POST /stores/{storeId}/registers | Kasa oluşturma |
POST /terminals | Mantıksal terminal oluşturma |
POST /terminals/{terminalId}/acquirers | Banka satırı ekleme |
POST /terminals/{terminalId}/device-link/close | Cihaz bağını çözme |
POST /devices | Cihaz kaydetme |
POST /devices/{deviceId}/assignment/close | Cihazı depoya alma |
POST /devices/{deviceId}/retire | Cihazı emekliye ayırma |
Biçim: 8–200 karakter, boşluksuz yazdırılabilir ASCII. Değer kırpılmaz ve düzeltilmez. Başlık yoksa 400 physical_pos.idempotency.key_required, biçim dışıysa 400 physical_pos.idempotency.key_invalid.
Davranış:
| Durum | Sonuç |
|---|---|
| Yeni anahtar | İşlem yapılır; oluşturma uçlarında 201, replayed: false. |
| Aynı anahtar, aynı uç, aynı gövde | İşlem tekrarlanmaz; ilk işlemin kaydı güncel hâliyle döner, 200, replayed: true. |
| Aynı anahtar, farklı gövde | 409 physical_pos.idempotency_mismatch. Yeni kayıt oluşmaz. |
| Aynı anahtar, başka bir işlem (ör. önce mağaza, sonra terminal oluşturma) | 409 physical_pos.idempotency_mismatch. |
- Gövdeler, alan kuralları uygulandıktan sonraki hâlleriyle karşılaştırılır; alanların sırası fark etmez.
- Kasa oluşturma ve banka satırı ekleme gibi bir kayda bağlı işlemlerde yol parametresi de karşılaştırmaya girer: aynı anahtarı başka bir mağaza için kullanmak
409alır. - Bir anahtar, anahtarınızın ortamında yalnız bir işlem için kullanılabilir ve süresiz saklanır. Kullanılmış bir anahtarı yeni bir işlem için yeniden kullanmayın.
- Test ve canlı anahtarların değerleri birbirinden ayrı tutulur.
Her yeni işlem için yeni bir UUID kullanın ve anahtarı işlemle birlikte saklayın. Zaman aşımı ya da bağlantı kopması sonrası aynı anahtar ve aynı gövdeyle yeniden deneyin; işlem ilk denemede tamamlandıysa replayed: true ile aynı kaydı alırsınız.
Diğer yazma uçları (PATCH, arşivleme, yeniden açma, terminal kapatma, cihaz atama, cihaz değiştirme) Idempotency-Key kullanmaz; bu uçlarda başlık dikkate alınmaz. Bu uçları rowVersion korur: işlem ilk denemede tamamlandıysa tekrar 409 physical_pos.version_conflict alır (terminal kapatmada 409 physical_pos.terminal.closed). Bu durumda kaydı okuyun ve değişikliğin uygulanıp uygulanmadığını kontrol edin.
Eşzamanlılık: rowVersion
Değiştirilebilen her kayıt (mağaza, kasa, mantıksal terminal, banka satırı) bir rowVersion tam sayısı taşır. Kaydı değiştiren isteklerde son okuduğunuz rowVersion değerini gövdede gönderirsiniz:
{ "rowVersion": 3, "name": "Kadıköy Mağazası (Yeni)" }rowVersionzorunludur; 1 ile 2147483647 arasında bir JSON tam sayısıdır. Dize ("3") gönderirseniz istek400 VALIDATION_ERRORalır.- Kayıt siz okuduktan sonra başka bir istekle değiştiyse istek
409 physical_pos.version_conflictalır ve hiçbir değişiklik yapılmaz. Kaydı yeniden okuyun, değişikliğinizi güncel hâline uygulayın ve yenirowVersionile gönderin. - Başarılı her değişiklikten sonra yanıttaki güncel
rowVersiondeğerini kullanın. - Banka satırı güncellemesi satırın kendi
rowVersiondeğerini, cihaz bağı işlemleri terminalinrowVersiondeğerini, cihaz işlemleri cihazınrowVersiondeğerini ister.
Kod kuralları
Mağaza, kasa ve terminal kodları kanonik biçime çevrilerek saklanır:
| Alan | Kural | Örnek |
|---|---|---|
code (mağaza, kasa, terminal) | Baştaki ve sondaki boşluk kırpılır, büyük harfe çevrilir. Yalnız A-Z, 0-9, ., _, -; harf ya da rakamla başlar; en çok 64 karakter. | ist-kadikoy → IST-KADIKOY |
vendorCode | Büyük harfe çevrilir. Harfle başlar, yalnız A-Z ve 0-9, 2–32 karakter. Katalogdaki bir üreticinin kodu olmalıdır. | pavo → PAVO |
externalRef (mağaza) | Kendi sisteminizdeki kimlik. Boşluksuz yazdırılabilir ASCII, en çok 128 karakter. Kırpılmaz, büyük/küçük harf korunur. | store_00042 |
- ASCII dışı karakter içeren kod reddedilir, dönüştürülmez:
KADIKÖYkabul edilmez,KADIKOYyazın. - Biçim dışı kod
400 physical_pos.input.code_invalid, biçim dışı üretici kodu400 physical_pos.input.vendor_code_invalid, biçim dışı dış referans400 physical_pos.input.ref_invalidalır. - Kodlar oluşturulduktan sonra değişmez.
Metin kuralları
Serbest metin alanlarına (name, displayName, city, district, addressLine, label, arama parametresi q) şu kurallar uygulanır:
- Metin Unicode NFC biçimine getirilir, baştaki ve sondaki boşluk kırpılır.
- Kırpıldıktan sonra boş kalan metin reddedilir.
- Şu karakterler reddedilir: kontrol karakterleri, sıfır genişlikli ve görünmez karakterler, yazı yönünü değiştiren karakterler, normal boşluk dışındaki boşluk karakterleri (bölünemez boşluk vb.), varyasyon seçicileri ve etiket karakterleri.
- Uzunluk karakter (Unicode kod noktası) sayısıyla ölçülür; sınırlar her alanın tablosunda yazar.
Kurala uymayan metin düzeltilmez, istek 400 physical_pos.input.text_invalid alır. details.field alan adını, details.reason sebebi verir. Liste aramasındaki (q) aynı ihlal 400 physical_pos.input.filter_invalid alır.
details.reason | Anlamı |
|---|---|
not_string | Değer metin değil. |
empty | Kırpıldıktan sonra boş. |
malformed_unicode | Geçersiz Unicode dizisi. |
forbidden_character | Yasak karakter içeriyor. |
too_long | Alanın sınırını aşıyor. |
Türkçe karakterler ve emoji gibi görünür karakterler serbest metinde kullanılabilir.
Saat dilimi
Mağazanın timezone alanı bir IANA saat dilimi adıdır (ör. Europe/Istanbul). Gönderilmezse Europe/Istanbul kullanılır.
- Kabul edilen adlar IANA saat dilimi veritabanının (tzdb) bölge adları ve
UTC'dir. Ad, büyük/küçük harfiyle birebir yazılmalıdır. - Eski ya da yeniden adlandırılmış adlar güncel adlarına çevrilerek saklanır; yanıtta her zaman güncel ad döner:
| Gönderilen | Saklanan |
|---|---|
Europe/Kiev | Europe/Kyiv |
Asia/Calcutta | Asia/Kolkata |
Asia/Istanbul | Europe/Istanbul |
Etc/UTC, Universal, Zulu | UTC |
- Tanınmayan adlar ile tek bir bölgeye karşılık gelmeyen eski adlar ve kısaltmalar (
EET,HST,Turkeygibi) reddedilir:400 physical_pos.validation.invalid,details.errors[0]={ "field": "timezone", "errors": ["iana_unknown"] }.
Gerekçe kodları
Arşivleme, yeniden açma, terminal kapatma, cihaz bağı ve cihaz işlemleri bir reasonCode ister. Kodlar sabit listelerdendir, büyük harfle ve birebir yazılır; listede olmayan ya da işleme uymayan kod 400 physical_pos.input.reason_code_invalid alır.
| İşlem | Kabul edilen kodlar |
|---|---|
| Mağaza arşivleme | STORE_CLOSED, TEMPORARILY_CLOSED, RELOCATED, MERGED, CREATED_IN_ERROR, DATA_CORRECTION, OTHER |
| Kasa arşivleme | STORE_ARCHIVED, REGISTER_REMOVED, REGISTER_REPLACED, STORE_CLOSED, TEMPORARILY_CLOSED, CREATED_IN_ERROR, DATA_CORRECTION, OTHER |
| Mağaza ya da kasa yeniden açma | REOPENED, ARCHIVED_IN_ERROR, DATA_CORRECTION, OTHER |
| Terminal kapatma | MERCHANT_REQUEST, CONTRACT_ENDED, BANK_TERMINATED, CREATED_IN_ERROR, DUPLICATE_RECORD, MIGRATED, OTHER |
| Terminale ilk cihazı bağlama | INITIAL_SETUP, RELOCATION, CORRECTION, OTHER |
| Bağlı cihazı değiştirme | DEVICE_REPLACEMENT, DEVICE_FAULT, DEVICE_LOST, DEVICE_STOLEN, RELOCATION, CORRECTION, OTHER |
| Cihaz bağını çözme | DEVICE_REPLACEMENT, DEVICE_FAULT, DEVICE_LOST, DEVICE_STOLEN, RELOCATION, CORRECTION, OTHER |
| Cihaz atama, depoya alma, emeklilik | Cihazlar sayfasındaki tablolar |
- Mağaza arşivlendiğinde aktif kasaları aynı işlemde arşivlenir; bu kasaların değişiklik geçmişine
STORE_ARCHIVEDkodu yazılır, mağazanın gerekçesichanges.storeReasonalanında durur. OTHERyalnız listede karşılığı olmayan durumlar içindir.
Oran sınırı
Yazma uçlarında (POST ve PATCH), organizasyonunuz ve API anahtarınız başına 60 saniyelik bir pencere uygulanır. Bir uç ailesinin bütün yazmaları aynı sayacı paylaşır; okumalar sınırlanmaz:
| Uç grubu | 60 saniyede en çok |
|---|---|
| Mağaza ve kasa yazmaları (oluşturma, güncelleme, arşivleme, yeniden açma) | 60 istek |
| Terminal ailesi yazmaları (terminal, banka satırı, cihaz bağı) | 30 istek |
| Cihaz yazmaları (kaydetme, güncelleme, atama, depoya alma, emeklilik) | 30 istek |
Sınır aşılırsa istek 429 RATE_LIMITED alır; Retry-After başlığı ve details.retryAfterSeconds beklemeniz gereken saniyeyi verir. Platform geneli sınırlar: Hız Sınırları.
Değişiklik geçmişi
Mağaza, kasa ve terminalde yapılan her değişiklik, işlemle aynı anda değişiklik geçmişine yazılır. Geçmişi GET …/audit uçlarından sayfalı okursunuz.
| Alan | Açıklama |
|---|---|
id | Olayın kimliği. |
action | Olayın türü, physical_pos.audit.<varlık>_<eylem> biçiminde (ör. physical_pos.audit.store_archived). |
actorType | İşlemi yapan: USER (panel kullanıcısı), API_KEY (API anahtarı) ya da platform tarafı işlemlerde OPERATOR / SYSTEM. |
actorId | Panel kullanıcısında auth-user:<kullanıcı kimliği>, API anahtarında kid:<anahtar kimliği>. |
reasonCode | İşlemin gerekçe kodu; gerekçe istemeyen işlemlerde null. |
changes | Değişikliğin özeti. Yalnız tanımlı alanları ve basit değerleri taşır; ad ve adres gibi serbest metinlerin değeri yazılmaz, yalnız değiştiği bilgisi yazılır. |
createdAt | Olay zamanı. |
Mağaza, kasa ve cihaz olaylarında ayrıca requestId (değişikliği yapan isteğin kimliği), terminal olaylarında entityType, entityId ve environment bulunur.
Yeniden deneme
4xxhatalar yeniden denemeyle düzelmez; isteği düzeltin.503 physical_pos.service.busy(details.retryable: true) kaydın o an başka bir işlemle meşgul olduğunu söyler; kısa bir beklemeden sonra aynı istekle yeniden deneyin.- Diğer
5xxhatalarda geri çekilerek yeniden deneyin. Oluşturma isteklerinde aynıIdempotency-Key'i kullanın.