Skip to main content

Keys

POST /pos/keys

Downloads the encryption key set for the POS device. Keys are wrapped in TR31 format with AES-256 encryption. The device must install these keys before it can process payment transactions. This is the sixth step in the POS activation flow.

Key hierarchy on device

TMK  →  KEK  →  MSK
└→ TPK / TDK / MAC

PIN / data / MAC crypto at runtime
LayerKeys deliveredWrapped under (export)
TerminalTMKZMK (host-side; device uses pre-provisioned ZMK to unwrap TMK)
Key encryptionKEKTMK
Data sessionMSKKEK
TransactionTPK, TDK, MACKEK

Purpose

  • Download a set of terminal encryption keys (TMK, KEK, MSK, TPK, TDK, MAC)
  • Keys follow the hierarchy: TMK → KEK → MSK (data) + transaction keys (TPK/TDK/MAC wrapped under KEK)
  • Key Check Values (KCVs) are provided for verification after installation
  • The key set has an issuance date and expiration date

Authentication

POS Attestation Auth — requires the attestation token received from POST /pos/attest.

HeaderRequiredFormatDescription
AuthorizationYesAttestation {token}The attestation token from the attest step. Uses the Attestation scheme (not Bearer). The token starts with att_, is cached in Redis, and is valid for 5 minutes from issuance. Example: Attestation att_f83kLmP9s2ab
X-Device-IdYesPOS-{8_HEX_CHARS}The same device ID used during attestation. The server verifies that this device ID matches the one bound to the attestation token. Example: POS-8F3A2C91

See the Headers Reference for complete details.

Request

No request body is required.

Response

200 OK

{
"key_set": {
"key_set_id": "ks-2025-01",
"issued_at": "2025-12-13T14:25:30Z",
"expires_at": "2026-12-13T14:25:30Z"
},
"transport": {
"format": "TR31",
"encryption": "AES-256",
"wrapped_under": "kek"
},
"keys": {
"tmk": {
"key_id": "tmk-2025-01",
"key_block": "BASE64_TR31_TMK",
"usage": "key-encryption"
},
"kek": {
"key_id": "kek-2025-01",
"key_block": "BASE64_TR31_KEK",
"usage": "key-encryption"
},
"msk": {
"key_id": "msk-2025-01",
"key_block": "BASE64_TR31_MSK",
"usage": "data-encryption"
},
"tpk": {
"key_id": "tpk-2025-01",
"key_block": "BASE64_TR31_TPK",
"usage": "pin-encryption"
},
"tdk": {
"key_id": "tdk-2025-01",
"key_block": "BASE64_TR31_TDK",
"usage": "data-encryption"
},
"mac": {
"key_id": "mac-2025-01",
"key_block": "BASE64_TR31_MAC",
"usage": "message-authentication"
}
},
"verification": {
"kcv": {
"tmk": "A1B2C3",
"kek": "B2C3D4",
"msk": "C3D4E5",
"tpk": "D4E5F6",
"tdk": "112233",
"mac": "778899"
}
}
}

Key Types

KeyFull NamePurpose
tmkTerminal Master KeyTop-level terminal key; wraps KEK for transport
kekKey Encryption KeyWraps MSK and protects key delivery to the terminal
mskMaster Session KeyEncrypts sensitive API payloads (config, activate, charge) on the device; API decrypts server-side
tpkTerminal PIN KeyEncrypts PIN blocks during transactions
tdkTerminal Data KeyLegacy/auxiliary data encryption key
macMAC KeyGenerates message authentication codes for HMAC signing

Terminal install order

  1. Unwrap TMK (using pre-provisioned ZMK or host-injected wrapping key)
  2. Unwrap KEK with TMK, then MSK with KEK
  3. Unwrap TPK, TDK, MAC with KEK
  4. Use MSK for field-level data encrypt (send ciphertext to API), TPK for PIN, MAC for message authentication

MSK-protected API payloads

After keys are installed, use MSK (AES-256-CBC, hex IV + hex ciphertext) for these endpoints:

EndpointDirectionNotes
POST /pos/configResponse onlyDecrypt envelope → core config JSON
POST /pos/terminal-parametersResponse onlyMSK envelope; inner gzip JSON (TR31-DATA or TR31-DATA-CHUNKED)
POST /pos/activateRequest + responseEncrypt readiness JSON; decrypt activation result
POST /pos/chargeRequest + responseHMAC signs the envelope body
POST /pos/charge/:id/refundRequest + responseSame envelope format
POST /pos/charge/:id/cancelResponse onlyEmpty HMAC body

Envelope format:

{
"format": "TR31-DATA",
"ciphertext": "A1B2C3...",
"initialization_vector": "00010203...",
"mode": "CBC"
}

Full walkthrough: End-to-End Example.

Transport Fields

FieldDescription
formatKey block format — always TR31
encryptionEncryption algorithm — always AES-256
wrapped_underWrapping key for MSK and transaction keys — kek

Verification

The kcv (Key Check Values) are used to verify keys were installed correctly on the device. After decrypting each key, encrypt a block of zeros and compare the first 3 bytes with the KCV.

401 Unauthorized

{
"error": {
"code": "4001",
"message": "Invalid or expired attestation token",
"trace_id": "abc123..."
}
}

Code Examples

curl -X POST https://api.viopay.io/pos/keys \
-H "Authorization: Attestation att_f83kLmP9s2ab" \
-H "X-Device-Id: POS-8F3A2C91" \
-H "Content-Type: application/json"

What's Next?

After installing the keys, download the device configuration:

Next step → Get Config