Fiziksel POS
API Referansı
Cihaz Bağı

Cihaz Bağı

Bu uçları kim çağırır?Dış API (s2s)
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ıca Digest. 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 anahtar 403 PRODUCT_NOT_ENABLED, kapsamı olmayan anahtar 403 API_INSUFFICIENT_SCOPE alı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.

Cihaz bağı, bir mantıksal terminalin hangi fiziksel cihazda çalıştığını gösterir. Cihaz değiştiğinde terminal, terminal kodu ve banka satırları aynı kalır; yalnız bağ değişir. → Temel kavramlar

  • Bir terminalin aynı anda en çok bir bağlı cihazı olur; bir cihaz aynı anda en çok bir terminale bağlıdır.
  • Her bağın bir başlangıcı (validFrom) ve kapandığında bir bitişi (validTo) vardır; eski bağlar silinmez, bağ geçmişinde kalır.
  • Terminal ve cihaz aynı ortamda olmalıdır. Bağ işlemleri terminalin rowVersion değerini ister ve başarılı her işlem bu değeri artırır.
  • Cihaz emekliye ayrıldığında bağı da kapanır.
  • Test anahtarı bu uçlarda yalnız bağ geçmişini okur; yazma istekleri 403 physical_pos.environment.test_key_read_only alır.
YöntemYolKapsam
POST/api/v1/physical-pos/terminals/{terminalId}/device-linkphysical_pos:manage
POST/api/v1/physical-pos/terminals/{terminalId}/device-link/closephysical_pos:manage
GET/api/v1/physical-pos/terminals/{terminalId}/linksphysical_pos:view

cURL örnekleri imzayı lunixi-sign.sh ile hesaplar: Kimlik Doğrulama › İmza yardımcısı.

Bağ nesnesi

AlanTipAçıklama
idstring (UUID)Bağın kimliği.
terminalIdstring (UUID)Terminal.
deviceIdstring (UUID)Cihaz.
validFromstringBağın açıldığı zaman.
validTostring | nullBağın kapandığı zaman; açık bağda null.
reasonCodestringBağı açan işlemin gerekçe kodu.
createdByTypestringBağı açan: USER, API_KEY, OPERATOR ya da SYSTEM.
createdByIdstringBağı açanın kimliği; API anahtarında kid:<anahtar kimliği>.
createdAtstringKaydın oluşturulma zamanı.

Cihaz bağlama ve değiştirme

POST /api/v1/physical-pos/terminals/{terminalId}/device-link

Terminale bir cihaz bağlar. Terminalin açık bir bağı varsa eski bağ kapanır ve yenisi açılır; ikisi tek işlemde yapılır.

AlanTipZorunluAçıklama
rowVersionintegerEvetTerminalin son okuduğunuz rowVersion değeri.
deviceIdstring (UUID)EvetBağlanacak cihazın kimliği: cihaz listesindeki ya da ayrıntısındaki id. Cihaz terminalle aynı ortamda olmalıdır.
reasonCodestringEvetAşağıdaki tabloya bakın.
DurumKabul edilen reasonCode
Terminalin bağlı cihazı yok (ilk bağlama)INITIAL_SETUP, RELOCATION, CORRECTION, OTHER
Terminalin bağlı cihazı var (değiştirme)DEVICE_REPLACEMENT, DEVICE_FAULT, DEVICE_LOST, DEVICE_STOLEN, RELOCATION, CORRECTION, OTHER

Duruma uymayan kod (ör. değiştirmede INITIAL_SETUP) 400 physical_pos.input.reason_code_invalid alır.

source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/terminals/00000000-0000-0000-0000-000000000301/device-link"
BODY='{"rowVersion":3,"deviceId":"00000000-0000-0000-0000-000000000402","reasonCode":"DEVICE_FAULT"}'
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": {
    "terminal": {
      "id": "00000000-0000-0000-0000-000000000301",
      "terminalCode": "IST-KADIKOY-01",
      "terminalStatus": "ACTIVE",
      "linkedDevice": {
        "linkId": "00000000-0000-0000-0000-000000000502",
        "deviceId": "00000000-0000-0000-0000-000000000402",
        "displayName": "Kasa 1 POS (yedek)",
        "serialNumber": "SN0000000002",
        "lifecycleStatus": "ACTIVE",
        "linkedAt": "2026-01-10T10:00:00.000Z"
      },
      "rowVersion": 4
    },
    "link": {
      "id": "00000000-0000-0000-0000-000000000502",
      "terminalId": "00000000-0000-0000-0000-000000000301",
      "deviceId": "00000000-0000-0000-0000-000000000402",
      "validFrom": "2026-01-10T10:00:00.000Z",
      "validTo": null,
      "reasonCode": "DEVICE_FAULT",
      "createdByType": "API_KEY",
      "createdById": "kid:mk_live_00000000",
      "createdAt": "2026-01-10T10:00:00.000Z"
    },
    "previousLinkId": "00000000-0000-0000-0000-000000000501"
  },
  "statusCode": 200,
  "requestId": "00000000-0000-0000-0000-000000000000"
}

Örnekte terminal nesnesi kısaltılmıştır; yanıt bütün alanları içerir. previousLinkId kapanan eski bağın kimliğidir; ilk bağlamada null.

EngelHata
Cihaz yok, size ait değil ya da diğer ortamda404 physical_pos.device.not_found
Cihaz zaten bu terminale bağlı409 physical_pos.terminal.device_already_linked
Cihaz başka bir terminale bağlı409 physical_pos.terminal.link_conflict — önce o terminalin bağını çözün.
Cihaz emekliye ayrılmış (RETIRED)409 physical_pos.device.retired
Terminalin üreticisi cihazın üreticisinden farklı400 physical_pos.terminal.device_vendor_mismatch
Terminal kapatılmış409 physical_pos.terminal.closed

Bu uç Idempotency-Key kullanmaz; tekrarları terminalin rowVersion değeri korur. Zaman aşımından sonra isteği yinelemeden önce terminali okuyun: linkedDevice.deviceId yeni cihazı gösteriyorsa işlem tamamlanmıştır.

Cihaz bağını çözme

POST /api/v1/physical-pos/terminals/{terminalId}/device-link/close · Idempotency-Key zorunlu

Terminalin açık bağını kapatır. Terminal açık kalır; banka satırları değişmez. Daha sonra yeni bir cihaz bağlayabilirsiniz.

AlanTipZorunluAçıklama
rowVersionintegerEvetTerminalin son okuduğunuz rowVersion değeri.
reasonCodestringEvetDEVICE_REPLACEMENT, DEVICE_FAULT, DEVICE_LOST, DEVICE_STOLEN, RELOCATION, CORRECTION, OTHER.
source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/terminals/00000000-0000-0000-0000-000000000301/device-link/close"
BODY='{"rowVersion":4,"reasonCode":"DEVICE_LOST"}'
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-000000000005" \
  --data-raw "$BODY"
{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "terminal": {
      "id": "00000000-0000-0000-0000-000000000301",
      "terminalCode": "IST-KADIKOY-01",
      "terminalStatus": "ACTIVE",
      "linkedDevice": null,
      "rowVersion": 5
    },
    "link": {
      "id": "00000000-0000-0000-0000-000000000502",
      "terminalId": "00000000-0000-0000-0000-000000000301",
      "deviceId": "00000000-0000-0000-0000-000000000402",
      "validFrom": "2026-01-10T10:00:00.000Z",
      "validTo": "2026-02-01T12:00:00.000Z",
      "reasonCode": "DEVICE_FAULT",
      "createdByType": "API_KEY",
      "createdById": "kid:mk_live_00000000",
      "createdAt": "2026-01-10T10:00:00.000Z"
    },
    "replayed": false
  },
  "statusCode": 200,
  "requestId": "00000000-0000-0000-0000-000000000000"
}

link kapanan bağdır; reasonCode bağı açan işlemin kodudur, çözme gerekçesi terminalin değişiklik geçmişine yazılır. Aynı Idempotency-Key ve aynı gövdeyle tekrar replayed: true döner. Terminalin bağlı cihazı yoksa 409 physical_pos.terminal.device_not_linked.

Bağ geçmişi

GET /api/v1/physical-pos/terminals/{terminalId}/links

Sorgu parametresiTipAçıklama
limitintegerSayfa başına bağ, 1–100. Varsayılan 25.
cursorstringÖnceki yanıttaki pageInfo.nextCursor.

Yanıt: { "items": [ <bağ nesnesi> ], "pageInfo": { … } }, en yeni bağ önce.

Hatalar

HTTPcodeNe zaman
400VALIDATION_ERRORdeviceId UUID değil; tanımsız gövde alanı.
400physical_pos.idempotency.key_required / physical_pos.idempotency.key_invalidBağ çözmede Idempotency-Key yok ya da biçim dışı.
400physical_pos.input.reason_code_invalidreasonCode listede yok ya da işleme uymuyor.
400physical_pos.terminal.device_vendor_mismatchTerminal ile cihazın üreticileri farklı.
400physical_pos.cursor.invalidBozuk imleç.
403physical_pos.environment.test_key_read_onlyYazma isteği test anahtarıyla yapıldı.
404physical_pos.terminal.not_foundTerminal yok, size ait değil ya da diğer ortamda.
404physical_pos.device.not_foundCihaz yok, size ait değil ya da diğer ortamda.
409physical_pos.terminal.closedTerminal kapatılmış.
409physical_pos.terminal.device_already_linkedCihaz zaten bu terminale bağlı.
409physical_pos.terminal.link_conflictCihaz başka bir terminale bağlı.
409physical_pos.terminal.device_not_linkedÇözülecek bağ yok.
409physical_pos.device.retiredCihaz emekliye ayrılmış.
409physical_pos.version_conflictTerminalin rowVersion değeri güncel değil.
409physical_pos.idempotency_mismatchAynı Idempotency-Key farklı bir istekle kullanılmış.
429RATE_LIMITEDYazma sınırı aşıldı. → Oran sınırı

Bütün kodlar: Hata Kodları.