At the end of each trading day, the fiscal day must be closed by submitting a signed summary of all fiscal counters to ZIMRA FDMS.
from fiscguy import close_day
result = close_day()
# {"fiscalDayStatus": "FiscalDayClosed", ...}
Or via REST:
POST /fiscguy/close-day/
ClosingDayService.close_day() performs these steps in order:
deviceID + fiscalDayNo + fiscalDayDate + countersPOST /CloseDayGET /getStatusFiscalDay.is_open = False on successFrom ZIMRA API spec section 13.3.1. Fields concatenated in this exact order:
| Order | Field | Format |
|---|---|---|
| 1 | deviceID |
Integer as-is |
| 2 | fiscalDayNo |
Integer as-is |
| 3 | fiscalDayDate |
YYYY-MM-DD — date the fiscal day was opened, not today |
| 4 | fiscalDayCounters |
Concatenated counter string (see below) |
All text uppercase. No separators between fields.
Each counter line: TYPE || CURRENCY || [TAX_PERCENT or MONEY_TYPE] || VALUE_IN_CENTS
Sort order:
SaleByTax=0 → BalanceByMoneyType=6)Tax percent formatting:
15 → 15.00, 0 → 0.0014.5 → 14.50BalanceByMoneyType: has a literal L between currency and money type:
BALANCEBYMONEYTYPEUSDLCASH3700
BALANCEBYMONEYTYPEZWGLCARD1500000
BALANCEBYMONEYTYPEZWGLCASH2000000
Zero-value counters: excluded entirely (per spec section 4.11).
Amounts: in cents, preserving sign. -699.75 → -69975.
From ZIMRA spec section 13.3.1:
321842019-09-23
SALEBYTAXZWL2300000
SALEBYTAXZWL0.001200000
SALEBYTAXUSD14.502500
SALEBYTAXZWL15.001200
SALETAXBYTAXUSD15.00250
SALETAXBYTAXZWL15.00230000
BALANCEBYMONEYTYPEUSDLCASH3700
BALANCEBYMONEYTYPEZWLCASH2000000
BALANCEBYMONEYTYPEZWLCARD1500000
Hash (SHA-256, base64): OdT8lLI0JXhXl1XQgr64Zb1ltFDksFXThVxqM6O8xZE=
CountersMismatchFDMS computed different counter values from what was submitted.
Causes:
fiscalDayDate in the closing string uses today’s date instead of the fiscal day open date15 instead of 15.00)BalanceByMoneyType missing the L separatorreceiptTotal instead of per-tax salesAmountWithTaxBadCertificateSignatureFDMS cannot verify the device signature.
Causes:
POST /fiscguy/issue-certificate/FiscalDayCloseFailedFDMS accepted the request but validation failed. The day remains open and can be retried.
Check fiscalDayClosingErrorCode in the response for the specific reason.
| Status | Meaning |
|---|---|
FiscalDayOpened |
Day is open, receipts can be submitted |
FiscalDayCloseInitiated |
Close request submitted, processing |
FiscalDayClosed |
Day closed successfully |
FiscalDayCloseFailed |
Close attempt failed — day remains open, retry allowed |
If close_day() raises CloseDayError with FiscalDayCloseFailed, the day remains open and you can correct the issue and retry:
from fiscguy import close_day
from fiscguy.exceptions import CloseDayError
try:
close_day()
except CloseDayError as e:
print(f"Close failed: {e}")
# Investigate, fix, then retry:
close_day()
FDMS allows close retries when the fiscal day status is FiscalDayOpened or FiscalDayCloseFailed.