Sign Receipt
Signs a fiscal invoice, credit note, or debit note and submits it to ZIMRA.
POST /api/receipt/sign
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
ZimraDeviceId | int | Yes | The ZIMRA device ID to sign the receipt with. Obtain from your CloudESD portal. |
Type | string | Yes | "FiscalInvoice", "CreditNote", or "DebitNote" |
Currency | string | Yes | ISO 4217 currency code (3 uppercase letters, e.g. "USD", "ZWG"). Note: "ZIG" is automatically converted to "ZWG". |
Reference | string | Yes | Your unique receipt reference. Must be unique per taxpayer. |
Date | datetime | Yes | Receipt date/time. Milliseconds are truncated. See Device Constraints. |
ReceiptLinesTaxInclusive | bool | Yes | Whether UnitPrice and LineTotal on receipt lines include tax. This significantly affects how tax calculations are validated — see Tax Calculation. |
TotalAmount | decimal | Yes | Receipt total inclusive of all taxes. Max 2 decimal places. Must be >= 0 for FiscalInvoice/DebitNote or <= 0 for CreditNote. |
ReceiptLines | array | Yes | At least one receipt line. See Receipt Line. |
Payments | array | Yes | At least one payment. See Payment. |
Taxes | array | Yes | Tax summary grouped by tax type. See Tax Summary. |
OriginalReference | string | Credit/Debit notes only | The Reference of the original fiscal invoice being credited/debited. See Credit & Debit Notes. |
OriginalFiscalDayNumber | int | Conditional | Required for credit/debit notes only if the original receipt was not processed through this system. See External Original Invoices. |
OriginalGlobalCounter | int | Conditional | Required for credit/debit notes only if the original receipt was not processed through this system. |
OriginalZimraDeviceId | int | Conditional | Required for credit/debit notes only if the original receipt was not processed through this system. |
Notes | string | Credit/Debit notes only | Reason for the credit or debit note. Required for CreditNote and DebitNote. |
ReceiptPrintForm | string | No | "Receipt48" (default, 48 chars/line receipt paper) or "InvoiceA4" (A4 invoice format) |
BuyerTIN | string | Conditional | Buyer's TIN/BP number. Must be exactly 10 digits if supplied. Required if BuyerVAT is supplied. |
BuyerVAT | string | No | Buyer's VAT number. Must be exactly 9 digits if supplied. If supplied, both BuyerTIN and BuyerName become required. |
BuyerName | string | Conditional | Required if BuyerTIN or BuyerVAT is supplied. |
BuyerAddress | string | No | Max 400 characters. Format: house number, street name, city, province (comma or newline separated). e.g. "207, Josiah Tongogara Ave, Harare, Harare" |
BuyerPhone | string | No | Max 20 characters. |
BuyerEmail | string | No | Max 100 characters. |
Cashier | string | No | Cashier name, max 20 characters. May be overridden by bearer token default. |
Receipt Line
| Field | Type | Required | Description |
|---|---|---|---|
Type | string | Yes | "Sale" or "Discount" |
Name | string | Yes | Product/service description, max 200 characters. |
HsCode | string | Yes | HS (Harmonized System) code. Must be 4 or 8 digits when tax % > 0; must be 8 digits when tax % = 0 or exempt. Your tenant may have auto-assignment of default HS codes enabled. |
UnitPrice | decimal | No | Price per unit. If supplied, LineTotal must equal UnitPrice * Quantity exactly. See Sign Rules for positive/negative requirements. |
Quantity | decimal | Yes | Must be greater than zero. |
LineTotal | decimal | Yes | Total for the line. Max 2 decimal places. If ReceiptLinesTaxInclusive is true, this includes tax. See Sign Rules. |
TaxPercent | decimal? | Yes | The tax percentage for this line. A value of 15% VAT should be 15 (not 0.15). Set to null for tax-exempt lines (which is not the same as 0). Retrieve valid tax percentages from the Get Device endpoint. This field must always be present in the JSON, even when null. |
Payment
| Field | Type | Required | Description |
|---|---|---|---|
Type | string | Yes | One of: "Cash", "Card", "MobileWallet", "Coupon", "Credit", "BankTransfer", "Other" |
Amount | decimal | Yes | Must be >= 0 for FiscalInvoice/DebitNote or <= 0 for CreditNote. The sum of all payment amounts must equal TotalAmount. |
Tax Summary
Each entry represents one tax type used across receipt lines. Group by tax percentage.
| Field | Type | Required | Description |
|---|---|---|---|
TaxPercent | decimal? | Yes | The tax percentage (e.g. 15), or null for exempt. Must match a tax type on the device. |
SalesAmountWithTax | decimal | Yes | The total of all receipt line totals for this tax type (including tax). See Tax Calculation. |
TaxAmount | decimal | Yes | The calculated tax amount. See Tax Calculation. |
Example: Tax-Inclusive Fiscal Invoice
{
"ZimraDeviceId": 12345,
"Type": "FiscalInvoice",
"Currency": "USD",
"Reference": "INV-2025-001",
"Date": "2025-03-15T10:30:00",
"ReceiptLinesTaxInclusive": true,
"TotalAmount": 115.00,
"ReceiptPrintForm": "Receipt48",
"BuyerName": "Acme Corp",
"BuyerTIN": "1234567890",
"ReceiptLines": [
{
"Type": "Sale",
"Name": "Widget A",
"HsCode": "84719000",
"UnitPrice": 50.00,
"Quantity": 2,
"LineTotal": 100.00,
"TaxPercent": 15
},
{
"Type": "Sale",
"Name": "Consulting Service",
"HsCode": "99800000",
"UnitPrice": 15.00,
"Quantity": 1,
"LineTotal": 15.00,
"TaxPercent": 0
}
],
"Payments": [
{
"Type": "Card",
"Amount": 115.00
}
],
"Taxes": [
{
"TaxPercent": 15,
"SalesAmountWithTax": 100.00,
"TaxAmount": 13.04
},
{
"TaxPercent": 0,
"SalesAmountWithTax": 15.00,
"TaxAmount": 0.00
}
]
}
Example: Credit Note
{
"ZimraDeviceId": 12345,
"Type": "CreditNote",
"Currency": "USD",
"Reference": "CN-2025-001",
"OriginalReference": "INV-2025-001",
"Date": "2025-03-16T09:00:00",
"Notes": "Customer returned Widget A",
"ReceiptLinesTaxInclusive": true,
"TotalAmount": -50.00,
"ReceiptLines": [
{
"Type": "Sale",
"Name": "Widget A",
"HsCode": "84719000",
"UnitPrice": -50.00,
"Quantity": 1,
"LineTotal": -50.00,
"TaxPercent": 15
}
],
"Payments": [
{
"Type": "Cash",
"Amount": -50.00
}
],
"Taxes": [
{
"TaxPercent": 15,
"SalesAmountWithTax": -50.00,
"TaxAmount": -6.52
}
]
}
Response (200 OK)
The response includes all fields from the request plus the following:
| Field | Type | Description |
|---|---|---|
DeviceSignature | string | Digital signature generated by the device |
DeviceHash | string | Hash value of the receipt data |
DeviceSerialNumber | string | Serial number of the signing device |
FiscalDayCounter | int | Sequential receipt number within the fiscal day |
FiscalDayNumber | int | Fiscal day number |
GlobalCounter | int | Global sequential receipt counter for the device |
VerificationCode | string? | QR code verification code |
QrCodeContent | string? | Full QR code URL for receipt verification |
SubmissionFailed | datetime? | If ZIMRA submission failed, the timestamp of the failure |
SubmissionError | string? | Error message from ZIMRA if submission failed |
Error Responses
| Status Code | Reason |
|---|---|
400 Bad Request | Validation errors in the receipt data. Check the errors array for details. |
401 Unauthorized | Authentication failed |
409 Conflict | A receipt with the same Reference already exists but with different data. See Idempotency. |
503 Service Unavailable | Device is in its 2-hour maintenance window, the fiscal day is not open, or the fiscal day has exceeded its maximum length. See Device Constraints. |