---
module: recon.atm-cycle-history
title: ATM Cycle History
tab: Internal
order: 20
audience: internal
---

Ops/support view for the ATM Cycle History screen. Owned by **hiveops-recon** (backend port 8091, NGINX `/api/recon/`, prod external 8013; frontend `recon.bcos.cloud`). All cycle/cassette data lives in `hiveiq_recon`.

## Roles & who can do what

- **Read (browse cycles, open detail, view snapshots)** — any authenticated user with a valid JWT. Results are **institution-scoped**: `CycleController` calls `InstitutionContext.resolveScope()` and filters every cycle by `institution`. A null scope (MSP/BCOS admin) sees all institutions.
- **Admin-only writes** — annotated `@PreAuthorize("hasAnyRole('MSP_ADMIN','BCOS_ADMIN')")`:
  - `POST /api/recon/atm/{atmId}/sync` — the **↻ Sync Journal** button
  - `PUT /api/recon/atm/{atmId}/cassettes` — save Cassette Configuration
  - `POST /api/recon/atm/{atmId}/cassettes/sync` — **Sync from Device** in the cassette panel
  - `POST /api/recon/atm/{atmId}/replenishments` (creating/closing cycles), `PUT /replenishments/{id}`, `POST /replenishments/{id}/lock`
- A non-admin who clicks Sync Journal / Save Cassettes / Sync from Device gets **403** — that is expected, not a bug.

## First things to check when it misbehaves

1. **"No cycles recorded yet"** — the ATM has no `reconciliation_cycles` row yet, OR the caller's institution scope excludes it. Confirm the JWT institution matches the device's institution (recon scopes reads by institution). Cycles only exist once a replenishment has been recorded for that ATM.
2. **↻ Sync Journal is greyed out** — the button is disabled unless there is a **current open cycle** (`$currentCycle`). No open cycle → nothing to sync.
3. **Sync Journal returns but totals look empty/wrong** — sync pulls WITHDRAWAL/DEPOSIT/REVERSAL transactions from **hiveops-journal** (`GET /api/journal/transactions`). Check journal is up and that the ATM's journal actually contains transactions for the open cycle window. Requires the `REPLENISHMENT`/txn types to be defined in journal-rules.
4. **Cassette slots wrong/empty after "Sync from Device"** — this does **not** read hiveops-devices. It calls **hiveops-incident**: `GET /api/atms` (to map the string `atmId` → incident's numeric id) then `GET /api/atms/{id}/properties`. Fails/returns empty if incident is down or the ATM is unknown to incident. Fall back to entering cassettes by hand and Save.
5. **"Daily Reboot Snapshots" empty** — snapshots are **not stored**; `GET /cycles/{id}/startup-snapshots` fetches STARTUP transactions live from journal for the cycle window each time. Empty = journal has no STARTUP entries in that window (or journal is down).
6. **Cassette parse is malformed** — the ATM's `journalFormat` (stored on `atm_cash_positions`, shown as the format badge in the header) drives how cassette/denomination blocks are parsed. Wrong format → wrong or missing cassette math.

## Common failure modes → fix

| Symptom | Likely cause | Fix |
|---|---|---|
| 403 on Sync / Save cassettes | user lacks MSP_ADMIN/BCOS_ADMIN | use an admin account |
| Wrong ATM's cycles missing for a user | institution scope excludes it | check JWT `institution` vs device institution |
| Sync succeeds, totals stale/zero | journal down / no txns / rules missing | verify hiveops-journal + journal-rules txn types |
| Sync from Device empty | incident down or ATM not in incident | verify hiveops-incident; enter cassettes manually |
| Device/institution shown wrong | stale `device_summary` mirror (no reconciler) | ensure `hiveops.device.events` is flowing from devices |
| Snapshots always empty | journal has no STARTUP txns in window | expected; not a recon bug |

## Variance sanity check

`expected = opening + added − removed − withdrawals + deposits − reversals`; `variance = actual (physical count) − expected`. Status is **BALANCED** when variance is 0, else **VARIANCE**. If a cycle shows a variance you can't explain, re-run Sync Journal first (pulls fresh journal txns), then confirm the cassette config and opening balance.

Related: [recon.atm-cycle-history] Overview (customer), [technical.recon].
