Skip to main content

Overview

The POS device goes through a multi-step activation flow before it can process payments. Each step must be completed in order.

Complete walkthrough

See End-to-End Example for sample requests, MSK envelopes, and a charge after activation.

Flow Diagram

┌──────────────────────────────────────────────────────────────────────┐
│ POS DEVICE ACTIVATION FLOW │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ 1. Bootstrap│────▶│ 2. Pairing │────▶│ 3. Status │ │
│ │ (POS) │ │ Code (POS)│ │ (POS) │ │
│ └─────────────┘ └──────────────┘ └──────┬──────┘ │
│ │ │
│ ┌─────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ 4. Claim Device (Web/Portal) │ │
│ │ (Merchant enters pairing │ │
│ │ code in backoffice UI) │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 5. Attest │────▶│ 6. Keys │────▶│ 7. Config │ │
│ │ (POS) │ │ (POS) │ │ (POS) │ │
│ └─────────────┘ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 7b. Terminal│ │
│ │ Parameters │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 8. Activate │ │
│ │ (POS) │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 9. Charge │ │
│ │ (HMAC+MSK) │ │
│ └─────────────┘ │
│ ✅ Payment processing │
└──────────────────────────────────────────────────────────────────────┘

Steps Explained

StepEndpointCalled ByAuthPurpose
1POST /pos/bootstrapPOS DevicePOS ActivationConnectivity check, get server time and min supported version
2POST /pos/pairing-codePOS DevicePOS ActivationGenerate a 6-char pairing code (valid for 5 min)
3GET /pos/statusPOS DevicePOS ActivationPoll to check if the device has been claimed
4POST /pos/claimWeb PortalBearer TokenMerchant enters pairing code in backoffice to claim the device
5POST /pos/attestPOS DevicePOS Activation + HMACProve device identity, receive an attestation token (valid 5 min)
6POST /pos/keysPOS DeviceAttestation TokenDownload encryption keys (TMK, KEK, MSK, TPK, TDK, MAC)
7aPOST /pos/configPOS DeviceAttestation TokenDownload MSK-encrypted core config (EMV, security, branding, merchant tip/tax/surcharge JSON)
7bPOST /pos/terminal-parametersPOS DeviceAttestation TokenDownload MSK-encrypted legacy terminal_parameters (gzip inside envelope; chunked when large)
8POST /pos/activatePOS DeviceAttestation TokenMSK-encrypted activation (request + response)
9POST /pos/chargePOS DeviceHMAC + MSKMSK-encrypted charge (request + response) — see POS Charges

Key hierarchy delivered at step 6: TMK → KEK → MSK + TPK / TDK / MAC. MSK encrypts core config, activate, and charge API payloads. See Keys and End-to-End Example.

Device Status Lifecycle

inactive  ──▶  claimed  ──▶  activated
│ │
│ (pairing code used) │ (POST /pos/activate)
│ ▼
│ Ready to process
│ POS charges

Headers Reference

The POS APIs use three different authentication levels, each requiring different headers. This section explains every header in detail.


POS Activation Headers

Used by: Bootstrap, Pairing Code, Status, Attest

X-Device-Id

Unique identifier for the physical POS device. Assigned when the device is pre-provisioned by a merchant or reseller.

  • Required: Yes
  • Format: POS- followed by an 8-character hex string
  • Example: POS-8F3A2C91
User-Agent

Identifies the POS application version, OS, and hardware model. Must start with Viopay-POS/ followed by a semver version. The parenthetical section contains the OS version and device model.

  • Required: Yes
  • Format: Viopay-POS/{version} ({OS}; {model})
  • Example: Viopay-POS/1.4.2 (Android 12; PAX-A920)
X-Client-Type

Identifies the type of client making the request. For POS devices, this is always pos.

  • Required: Yes
  • Format: pos
  • Example: pos

Attestation Signature Headers

Used by: Attest — in addition to the activation headers above.

X-Key-Id

Identifier of the device identity key used to generate the signature. This key must be registered and active (not revoked) in the merchant_device_identity_keys table for the device.

  • Required: Yes
  • Format: Free-form string
  • Example: device-id-key-2025-01
X-Timestamp

Current time in RFC3339 / ISO 8601 format. Used to prevent replay attacks.

  • Required: Yes
  • Format: RFC3339 UTC timestamp
  • Validation: Must be within 5 minutes of the server time (past). Future timestamps are tolerated up to 1 minute.
  • Example: 2025-12-13T14:25:30Z
X-Nonce

A unique random value generated fresh for every request. Combined with the timestamp, prevents replay attacks.

  • Required: Yes
  • Format: Alphanumeric string (at least 12 characters recommended)
  • Example: a1b2c3d4e5f6
X-Signature

HMAC-SHA256 signature of the request. Prefixed with v1= to allow future signature versions.

  • Required: Yes
  • Format: v1={base64_encoded_hmac}
  • Example: v1=SGVsbG8gV29ybGQ=
  • How to compute: Sign the concatenation of device_id, key_id, timestamp, and nonce (joined with \n) using the device's HMAC secret. Then Base64-encode the result.

Attestation Token Headers

Used by: Keys, Config, Terminal Parameters, Activate

Authorization

The attestation token received from POST /pos/attest. Uses the Attestation scheme — not Bearer.

  • Required: Yes
  • Format: Attestation {token}
  • Token prefix: att_
  • Lifetime: Valid for 5 minutes. Cached in Redis and tied to a specific device ID.
  • Example: Attestation att_f83kLmP9s2ab
X-Device-Id

Same device ID that was used during attestation. The server verifies that this matches the device ID bound to the attestation token.

  • Required: Yes
  • Format: POS-{8_HEX_CHARS}
  • Example: POS-8F3A2C91

HMAC Charge Headers

Used by: POST /pos/charge, POST /pos/charge/:chargeID/refund, POST /pos/charge/:chargeID/cancel — all use MSK-encrypted request/response bodies where applicable (see Create POS Charge).

X-Terminal-Id

The terminal key assigned to the device after activation. This is different from the device ID — it's the logical terminal identifier used for payment processing. Found in the config response as terminal.terminal_id.

  • Required: Yes
  • Format: Free-form string
  • Example: TID-004812
X-Timestamp

Current time in RFC3339 format. Same rules as attestation.

  • Required: Yes
  • Format: RFC3339 UTC timestamp
  • Validation: Within 5 minutes past, 1 minute future.
  • Example: 2025-12-13T14:25:30Z
X-Nonce

Unique random value per request.

  • Required: Yes
  • Format: Alphanumeric string
  • Example: f9e8d7c6b5a4
X-Key-Id

Identifier of the HMAC key used to sign the request. This is the MAC key from the key set downloaded during activation.

  • Required: Yes
  • Format: Free-form string
  • Example: hmac-key-2025-01
X-Signature

HMAC-SHA256 signature of the full request, Base64-encoded and prefixed with v1=.

  • Required: Yes
  • Format: v1={base64_encoded_hmac}
  • Example: v1=dGVzdCBzaWduYXR1cmU=
  • How to compute: Build the signature string by joining these values with newlines (\n):
METHOD
PATH
QUERY
BODY
TERMINAL_ID
TIMESTAMP
NONCE

Then compute HMAC-SHA256(signature_string, hmac_secret) and Base64-encode the result.

X-Client-Type

Client type identifier. Always pos for POS devices.

  • Required: Yes
  • Format: pos
User-Agent

POS application identifier. Same format as activation headers.

  • Required: Yes
  • Format: Viopay-POS/{version} ({OS}; {model})
  • Example: Viopay-POS/1.4.2 (Android 12; PAX-A920)
Idempotency-Key

Unique key to ensure the charge is only processed once. If a charge with the same idempotency key already exists, the existing response is returned instead of creating a duplicate.

  • Required: No (optional)
  • Format: UUID or free-form string
  • Example: 550e8400-e29b-41d4-a716-446655440000

Bearer Token Header

Used by: Claim Device — called from the web portal, not the POS device.

Authorization

Keycloak JWT access token. Obtained via user login or POST /client/session (API client credentials). A session must be initiated via /session/initiate before making merchant-scoped requests.

  • Required: Yes
  • Format: Bearer {jwt_token}
  • Example: Bearer eyJhbGciOiJSUzI1NiIs...

What Happens After Activation?

Once the device is activated, it uses HMAC signature authentication to process payments:

  • POST /pos/charge — Create a payment (MSK encrypt request + decrypt response)
  • POST /pos/charge/:chargeID/refund — Refund a payment (MSK encrypt request + decrypt response)
  • POST /pos/charge/:chargeID/cancel — Cancel a payment (MSK decrypt response)
  • POST /pos/charge/:chargeID/reverse — Reverse a payment (same as cancel)