by Intelliverse X

Set up a new ZHZN machine with Nayax

Installer runbook · reviewed 10 September 2026. If an existing machine is broken, start with Debug a Nayax reader.

Use this sequence for every cabinet. Identity comes from the cabinet APK's first successful registration. Payment enablement follows a verified physical reader assignment. Neither “online” nor a copied configuration is sufficient acceptance.

On-site help, clicks and restart instructions

Keep the visual troubleshooting walkthrough open on your phone during setup. It shows Core and MoMa reader restarts, Operator X app restart, command collection checks and the full cabinet power cycle.

Contact details and hours are sourced and dated in the troubleshooting guide. Reader restart and app restart do not replace complete cabinet acceptance.

Before arriving at the cabinet

Have the approved signed vending APK and release checksum, the cabinet's installation instructions, access to Operator X, authorized Nayax Core/MoMa access, the service PIN through the approved private channel, network access, stocked test product and a person able to observe the reader and dispense. The installer records physical evidence; the platform administrator handles restricted API and enrollment operations; the Nayax account owner confirms the settlement actor.

Use Android installation and handover and Android operation for installing the APK, network setup and authorized service access. Download the release approved for this cabinet; a filename or the newest advertised version is not an installation acceptance result.

Order of work: install → read returned ID → enroll and claim → identify and bind reader → verify controller/MDB → enable Card → restart cabinet → paid acceptance → record handover. Keep the machine attended until acceptance is complete.

1. Install once and record the returned machine ID

Install the approved signed ZHZN vending APK, package ai.intelliverse.zhzn.kioskx, on the cabinet. Operator X is the management app, not the cabinet APK. Record the installed version and release checksum. Use the Android installation guide supplied with that approved release.

On first launch, ConfigStore.hardwareSerial() uses a persisted serial, then the ROM serial, then an AID-… Android-ID fallback. AgentService sends registration to /zhzn/register, saves the returned machineCode as machineId, and uses it for subsequent calls. Device credential enrollment is a separate operation and may require an authorized per-device enrollment window.

Read Machine and Serial on the APK status screen while registration is pending/completing; the successful registration log also reports serial → machine. Record the full returned Machine ID. “Not yet registered” is not an ID. If already provisioned into the storefront, use the authorized service/status diagnostics or the registration record to confirm it.

Maintain these distinct values:

Field Meaning Rule
Cabinet/plate serial Physical asset identity Record separately if different from Android serial
APK hardware serial First registration input Never clone it from another tablet
Kiosk-X machine ID Server-returned machineCode, saved by APK Permanent key for catalog, orders and reader binding
Android device ID Device credential/duplicate detection binding Verify it belongs to this head unit
Site name Human-readable location Can change without changing machine ID
Nayax Device Number Physical reader's 16-digit number Preserve leading zeros; bind this value
Nayax Core Machine ID Core's separate internal record ID Never enter this as terminalId

An APK update should retain the existing ID; it should not generate a new cabinet on every install. Do not clear app data, copy app storage, uninstall, or factory-reset as a normal setup step. A head-unit replacement or factory reset requires the existing identity-recovery procedure and a check of prior sales/ownership.

If the APK reports needs-arming, the authorized platform/operator opens POST /api/v1/machines/{id}/device-credential/arm with an install reason, a short ttlMinutes window and the confirmed deviceId. Let the APK consume that one-use window and persist its own key; verify state=enrolled, lastAuthScheme=device-key, and that the window is no longer open. The API’s enrolmentBinding field describes the original bootstrap trust, so an explicitly authorized enrollment can retain self-asserted; confirm the authorizing installer and actual device-key authentication rather than resetting a working identity to change that label. Do not simulate enrollment from a laptop or copy one cabinet’s key to another. An expired/unused window is an incomplete setup, not a pass.

Claim the exact returned ID into the intended operator using the existing machine registration/claim surface. A conflict means inspect the existing cabinet/owner; do not invent a suffix to bypass it. Confirm /identity has a device binding and no conflict, and /device-credential reports enrollment. Do not put operator/admin API credentials in the APK or enrollment paperwork.

2. Associate the physically installed reader

Read the serial on the reader and find the same Device Number in Nayax Core. Record its Core Machine ID and actor/operator. Verify the settlement actor belongs to the intended operator before enabling card payments. Give the Core machine a useful reference including the full Kiosk-X machine ID; renaming does not itself change the binding.

With the cabinet claimed, use Operator X's Nayax binding or the supported endpoint:

POST /api/v1/machines/{APK_RETURNED_MACHINE_ID}/nayax

Supply terminalId and deviceSerial as the same physically confirmed Device Number, and cardMode: "mdb". Record coreActorName, settlesToOperator, and whether settlement notifications are actually configured (nayaxWebhookExpected). Do not set the latter merely because webhooks are desired. Merchant-account overrides are unnecessary for ordinary assignment and must not be copied from another operator.

Before binding, check both terminalId and deviceSerial across the operator's active, offline and returned records. The backend rejects duplicate terminal IDs, but stale serial aliases can also match settlement notifications. The check script below catches both within the explicit operator scope; server conflict checks remain responsible for other operators.

Binding example for an authorized technician

Use the live API schema at API reference. The following body shows the identity fields; substitute the real serial in both fields. Add the actor/settlement assertions only after verifying them in Core.

{
  "terminalId": "REPLACE_WITH_PHYSICAL_DEVICE_NUMBER",
  "deviceSerial": "REPLACE_WITH_PHYSICAL_DEVICE_NUMBER",
  "cardMode": "mdb"
}

Perform an independent GET /api/v1/machines/{id}/nayax afterward. Verify the full cabinet ID and both serial fields again, then check for duplicate aliases including offline inventory. Saving a site name in Core or seeing a green reader Online badge does not perform this binding.

Pass: the physical reader, the Core Device Number and both Kiosk-X binding fields match, the actor is correct, and no former cabinet claims the same real reader.

Reader transfer or return

  1. Let active payments finish, record both old/new IDs and the reader serial, and disable the old cabinet's hosted card option.
  2. Preserve the old binding/transfer evidence. Release the old association through the authorized supported workflow. If the old record already has an unassigned NYX{oldMachineID} placeholder, ensure both terminalId and deviceSerial use that placeholder. Never leave the moved reader's real number in an active matching field on the old record. This is a bookkeeping placeholder, not a real reader and not payment-ready.
  3. Bind the real Device Number to the destination's existing APK machine ID. A failed destination bind must leave card checkout disabled there until corrected; the multi-call transfer is not atomic.
  4. Update the Core association/reference as appropriate and repeat commissioning. Keep original order records intact; do not reattribute historical transactions by editing orders.

3. Discover hardware before saving the cabinet profile

Enable mdbEnabled in this cabinet's agent configuration. On the current ZHZN/CSM family, the observed baseline is:

Setting Confirmed current baseline
Controller SH (CSM)
Vend UART / baud /dev/ttyS4 / 9600
MDB bridge UART /dev/ttyS1
Cashless peripheral Address 0x10; ready/enabled
Hosted card option cardTapStorefront=true after binding and hardware checks
Diagnostic force-card override cardTapForceTile=false
Real acceptance purchase testMode=false

These port/module values are a reference for matching hardware, not universal defaults for every future ZHZN machine. Require that cabinet's own fresh telemetry. Save a confirmed controller module instead of relying on an incorrect cloud default plus auto-detection. Count physical shelves/coils before recording rows and columnsPerRow; do not copy layout because the APK is the same.

The observed working Nayax profile is MDB Level 3 Always Idle with Product transaction start. Use the confirmed profile appropriate to the actual controller/bridge. Do not apply the historical Reyeah Level-1 instructions to a ZHZN bridge or blanket-copy Ignore flags, credit limits, currency or merchant settings.

Save the two controls independently

The authorized technician reads this cabinet's current configuration, then makes only the required changes:

Endpoint Minimal body Purpose
PUT /api/v1/machines/{id}/agent-config {"mdbEnabled":true} Enable MDB integration
PUT /api/v1/machines/{id}/features {"cardTapStorefront":true} Enable hosted Card after readiness checks
PUT /api/v1/machines/{id}/features {"cardTapForceTile":false,"testMode":false} Remove diagnostic/test overrides for acceptance

Read back each changed endpoint and confirm fresh device telemetry after configuration pickup. For module/port settings, use the approved schema and that cabinet's observed values; never paste the other cabinet's entire response. Preserve its own identity, stock, prices and geometry.

Enable the card option only after the assignment, reader and board checks. mdbEnabled=true does not turn on the shopper's Card button. htmlStorefront selects Reyeah behavior; it is not ZHZN's card switch.

4. Run the reusable configuration check

Create a commissioning manifest using the full ID read from the APK and the serial read from the installed Nayax reader:

{
  "operatorEmail": "REPLACE_WITH_OPERATOR",
  "machines": [{
    "machineNo": "REPLACE_WITH_APK_MACHINE_ID",
    "nayaxDeviceNumber": "REPLACE_WITH_16_DIGIT_READER_NUMBER",
    "module": "SH",
    "vendPort": "/dev/ttyS4",
    "mdbPort": "/dev/ttyS1",
    "baudRate": 9600,
    "apkVersion": "REPLACE_WITH_APPROVED_INSTALLED_VERSION",
    "geometry": {"rows": 5, "columnsPerRow": 2}
  }]
}

Replace every example value, including geometry, with that cabinet's evidence. Keep the manifest with the asset handover record; it contains identities/configuration, not credentials.

# Supply KIOSKX_KEY through the approved environment/secret manager.
python3 scripts/check_zhzn_commissioning.py commissioning.json --output commissioning-result.json

The checker lives in the private Kiosk-X repository at scripts/check_zhzn_commissioning.py; run it from that repository. Installers without repository/API access submit the manifest and checklist to the platform team, who return the timestamped result. Manual verification of the same fields remains available through authorized diagnostics.

The current raw-telemetry endpoint requires an authorized platform administrator; do not distribute an admin key to installers. The platform runs this check on the installer's recorded manifest. It reads only the specified operator's inventory, paginates it, checks offline aliases too, and then checks only the named cabinets. It rejects stale heartbeats even if an online/delivered badge remains green. Exit 0 means configuration checks passed; exit 1 lists setup failures; exit 2 means inspection failed and is not a pass.

This is an executable commissioning procedure, not an installed server policy or background automation. It makes no writes, does not create IDs, and cannot certify physical acceptance. Its output deliberately keeps physicalAcceptanceVerified=false.

5. Record acceptance before handing over

During an idle maintenance window, restart the complete cabinet using its normal power procedure. Confirm the same machine ID returns, the APK starts automatically, new heartbeats arrive, and board/MDB initialization succeeds. App reboot, Android reboot and reader-only reboot do not establish that all cabinet hardware power-cycled.

Then record, with timestamps and the installer's name:

Do not mark a fresh cabinet accepted solely from a successful motor test, an online reader, a screenshot command receipt or a “shipped” status. Any failed step stays explicitly pending in the handover record.

6. Copyable installation and handover checklist

Use one record per cabinet. Store completed records privately, with the operator's asset inventory. Do not copy a completed record as the identity of another machine.

Field Record
Installer / date / timezone / site ________
Cabinet plate serial / model / measured shelf geometry ________
APK hardware serial / returned full Kiosk-X machine ID ________
Android device ID / installed APK version / approved checksum ________
Claimed operator / identity conflict check ________
Credential enrolled / last device-key authentication / arm consumed ________
Physical Nayax Device Number / Core internal Machine ID ________
Verified Core actor / settlement owner / webhook expectation ________
terminalId / deviceSerial / duplicate and returned-record check ________
Saved and detected module / vend UART / baud / MDB UART ________
Fresh board init / MDB ready-state-address / timestamp ________
MDB enabled / Card enabled / force override off / test mode off ________
Full cabinet restart / same ID / automatic APK startup ________
Buy Now → Card usable / reader price and currency observed ________
Supervised order ID / product physically received / stock decrement ________
Nayax transaction ID / authorization / final settlement ________
Configuration audit result / unresolved warnings ________
Remaining failed or pending checks / owner / next action ________
Installer and operator acceptance / date ________

Acceptance rule: configuration checks, physical delivery and processor settlement are separate checkpoints. Mark unobserved steps pending. Resolve discrepancies before declaring the cabinet fully commissioned. An offline old machine still counts in reader-assignment checks.

7. Keep the pattern when the fleet grows

Repeat the same sequence for each new APK installation. The first successful registration supplies the cabinet ID; the installer then pairs the physically observed reader with that ID. Never assign sequential names such as “machine 4” as a substitute for the returned machine ID, and never assume the fourth inventory record is the physical fourth cabinet.

APK updates retain the established machine identity. Reader replacement keeps the cabinet identity and changes the verified reader association through the transfer procedure. Head-unit replacement or reset requires identity recovery and credential review. Re-run acceptance after a material controller, reader, APK or payment-profile change.

The SH/CSM profile above was observed on two cabinets on 10 September 2026. They had different APK versions and shared an ID suffix. Their profile is a useful comparison for matching hardware, but a new machine must supply its own identity and fresh hardware evidence. This runbook and the read-only checker are an operating procedure, not automatic enforcement installed in the onboarding server.