New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@panierapp/zimra

Package Overview
Dependencies
Maintainers
2
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@panierapp/zimra

A type-safe and frictionless library for ZIMRA Fiscalisation

Source
npmnpm
Version
1.0.4
Version published
Weekly downloads
2
-50%
Maintainers
2
Weekly downloads
 
Created
Source

Build Status

ZIMRA Fiscalisation

A type-safe and frictionless library for ZIMRA Fiscalisation allowing you create ZIMRA Fiscal Invoices, Credit Notes and Debit Notes without having to worry about Hashing, Signing Receipts, Opening or Closing fiscal days. If you need more functionality please visit the Panier Developer API.

This library will require you to setup a paid Panier account in order to go into production but we have Test Credentials that you can use to try out the system and see if it's the best fit for your application. These will be hitting the ZIMRA FDMS Test Environment. Don't forget to switch your host to https://panier.app/api/v1 when you are in production so that you can hit the ZIMRA FDMS Production Environment.

Installation

npm install @panierapp/zimra

Usage

Create a Panier instance

First let us create a Panier Client instance

import { type Panier, CreatePanierClient } from '@panierapp/zimra';

// Test Credentials
const options = {
  host: 'https://dev.panier.app/api/v1', // Use https://panier.app/api/v1 in production
  APP_ID: 'zNONt9bq1YASNqaYCkRks',
  API_KEY: 'RaOnN6P9KjPxDm_khLmBqrMXcjlh0yITvVXfHCx2VfTsO5GykW7N_a3Bu53uKhCR',
} satisfies Panier.Credentials;

// Create the Panier Client instance
const panier = new CreatePanierClient(options);

Create a ZIMRA Fiscal Tax Invoices

Now let's use our Panier Client instance to create a ZIMRA Fiscal Tax Invoice

// First Create Panier Client instance

// Create the body
const fiscalInvoiceBody = {
  invoice_number: 'INV000001', // If not provided a NanoID is used e.g XDVP07DIYQDO
  products: [
    {
      name: 'Jumbo Ban',
      selling_price: 0.9, // Selling Price Excluding Tax
      quantity: 2,
      discount: 0, // Optional
      hs_code: '1905.90.00',
      zimra_tax_id: 512,
    },
  ],
  currency_code: 'USD',
  money_type: 'Cash',
} satisfies Panier.CreateFiscalInvoiceBody;

const fiscal_invoice = await panier
  .createFiscalInvoice(fiscalInvoiceBody)
  .catch((error) => console.error(error));

if (fiscal_invoice?.id) {
  console.log('You have successfully created a fiscal invoice');
  console.log(fiscal_invoice);

  // Check for ZIMRA validation errors
  if (fiscal_invoice.validation_errors.length === 0) {
    console.log('No validation Errors ');
  } else {
    console.log(
      `You have ${fiscal_invoice.validation_errors.length} validation errors`,
    );
    console.log(fiscal_invoice.validation_errors);
  }
} else {
  console.log('Failed to create a fiscal invoice');
  console.log(fiscal_invoice);
}

Et voila, that's it 🎉.

Create a Fiscal Tax Invoice with customer details

You can also add customer details to your fiscal tax invoice but you have to add their Tin Number, Phone and Email for their information to appear on the Buyer section of the ZIMRA Fiscal Tax Invoice.

// First Create Panier Client instance

// Create the doc
const fiscalInvoiceWithCustomerBody = {
  invoice_number: 'INV000001', // If not provided a NanoID is used e.g XDVP07DIYQDO
  customer: {
    name: 'Luke Tawanda',
    phone: '0772000001',
    email: 'luke.tawanda@gmail.com',
    address: '123 Harare drive', // Optional
    tin_number: '2000820000',
    vat_number: '220411600', // Optional
  },
  products: [
    {
      name: 'Jumbo Ban',
      selling_price: 0.9, // Selling Price Excluding Tax
      quantity: 2,
      discount: 0, // Optional
      hs_code: '1905.90.00',
      zimra_tax_id: 512, // See ZIMRA Tax ID Table for more optionals
    },
  ],
  currency_code: 'USD',
  money_type: 'Cash',
} satisfies Panier.CreateFiscalInvoiceBody;

const fiscal_invoice_with_customer = await panier.createFiscalInvoice(fiscalInvoiceWithCustomerBody);

if (fiscal_invoice_with_customer?.id) {
  console.log('You have successfully created a fiscal invoice');
  console.log(fiscal_invoice_with_customer);

  // Check for ZIMRA validation errors
  if (fiscal_invoice_with_customer.validation_errors.length === 0) {
    console.log('No validation Errors ');
  } else {
    console.log(
      `You have ${fiscal_invoice_with_customer.validation_errors.length} validation errors`,
    );
    console.log(fiscal_invoice_with_customer.validation_errors);
  }
} else {
  console.log('Failed to create a fiscal invoice');
  console.log(fiscal_invoice_with_customer);
}

Create a Credit Note

Now let us create a Credit Note.

// First Create Panier Client instance

// Create the doc
const creditNoteBody = {
  invoice_number: 'INV000001', // The Invoice Number of the ZIMRA Fiscal Tax Invoice that you want to credit
  products: [
    {
      name: 'Jumbo Ban',
      selling_price: 0.9, // Selling Price Excluding Tax
      quantity: 2,
      discount: 0, // Optional
      hs_code: '1905.90.00',
      zimra_tax_id: 512, // See ZIMRA Tax ID Table for more optionals
    },
  ],
  currency_code: 'USD',
  money_type: 'Cash',
} satisfies Panier.CreateCreditNoteBody;

const credit_note = await panier
  .createCreditNote(creditNoteBody)
  .catch((error) => console.error(error));

if (credit_note?.id) {
  console.log('You have successfully created a credit note');
  console.log(credit_note);

  // Check for ZIMRA validation errors
  if (credit_note.validation_errors.length === 0) {
    console.log('No validation Errors ');
  } else {
    console.log(
      `You have ${credit_note.validation_errors.length} validation errors`,
    );
    console.log(credit_note.validation_errors);
  }
} else {
  console.log('Failed to create a credit note');
  console.log(credit_note);
}

Create a Debit Note

Now let's create a Debit Note

// First Create Panier Client instance

// Create the doc
const debitNoteBody = {
    invoice_number: 'INV000001', // The Invoice Number of the ZIMRA Fiscal Tax Invoice that you want to debit
    products: [
        {
            name: 'Jumbo Ban',
            selling_price: 0.9, // Selling Price Excluding Tax
            quantity: 2,
            discount: 0, // Optional
            hs_code: '1905.90.00',
            zimra_tax_id: 512 // See ZIMRA Tax ID Table for more optionals
        }
    ],
    currency_code: "USD",
    money_type: "Cash"
} satisfies Panier.CreateDebitNoteBody

const debit_note = await panier.createDebitNote(debitNoteBody);
                        .catch(error => console.error(error));

if(debit_note?.id) {
    console.log('You have successfully created a debit note')
    console.log(debit_note)

    // Check for ZIMRA validation errors
    if(debit_note.validation_errors.length === 0) {
        console.log('No validation Errors ')
    }
    else {
        console.log(`You have ${ debit_note.validation_errors.length } validation errors`)
        console.log(debit_note.validation_errors)
    }
}
else {
    console.log('Failed to create a debit note')
    console.log(zimraDebitNote)
}

ZIMRA Tax IDs

Below are tables showing all the valid ZIMRA Tax IDs for the ZIMRA Test and Production Environments

Take special care to check the tax IDs and please note that they are not always the same accross Environments

Test Environment

NamePercentage (%)ZIMRA Tax ID
Exempt1
Zero rated 0%02
Non-VAT Withholding Tax5514
Standard rated 15.5%15.5517

Production Environment

NamePercentage (%)ZIMRA Tax ID
Zero rated 0%02
Exempt3
Non-VAT Withholding Tax5514
Standard rated 15.5%15.5515

Proxy Support

If you want to use a proxy all you have to do is add a proxy_url when you are creating the Panier Client instance.

Node.js

In Node.js (>= 18)

import { type Panier, CreatePanierClient } from '@panierapp/zimra';

const options = {
  host: 'https://panier.app/api/v1',
  proxy_url: 'http://localhost:3128', // 👈 Add the proxy_url
  APP_ID: '******',
  API_KEY: '******',
} satisfies Panier.Credentials;

// Create the Panier Client instance
const panier = new CreatePanierClient(options);

// Now you can use the proxied instance in your app

Example: Allow self-signed certificates (USE AT YOUR OWN RISK!)

This makes fetch unsecure against MITM attacks. USE AT YOUR OWN RISK!

import { type Panier, CreatePanierClient } from '@panierapp/zimra';

const options = {
  host: 'https://panier.app/api/v1',
  proxy_url: 'http://localhost:3128', // 👈 Add the proxy_url
  unsecured_proxy_agent: true, // 👈 Set the unsecured_proxy_agent to true
  APP_ID: '******',
  API_KEY: '******',
} satisfies Panier.Credentials;

// Create the Panier Client instance
const panier = new CreatePanierClient(options);

// Now you can use the proxied instance in your app

Caveats

1. Cold Starts

If you try to create a ZIMRA Fiscal Tax Invoice, Credit Note or Debit Note when your fiscal day is closed, Panier will first open your fiscal day then perform the operation. This will add a delay to the overlay operation. However once the fiscal day has been opened the execution time will reduce and return to normal.

2. Invoice Number Collisions

The ZIMRA FDMS requires that all invoice_numbers be unique for a single tax payer. Meaning that if you were using another fiscal device before, you can not use the same invoice numbers that you used on that device with this library. You you do, ZIMRA will return a RCPT020 error code which means Invoice signature is not valid. This will prevent your fiscal day from beign able to close and you would have to send an email to csimango@zimra.co.zw and gsangare@zimra.co.zw requesting that your fiscal day be manually closed on the ZIMRA side. You must include your Company Name, Device ID and current Fiscal Day in your email.

Methods

createFiscalInvoice()

This method is used to create a ZIMRA Fiscal Tax Invoice

// First Create Panier Client instance

const fiscalInvoiceBody = {
  // add Fiscal Invoice Body
} satisfies Panier.CreateFiscalInvoiceBody;

const fiscal_invoice = await panier.createFiscalInvoice(fiscalInvoiceBody)
                                    .catch((error) => error);

// Now you can use the Fiscal Invoice in our app

createCreditNote()

This method is used to create a Credit Note

// First Create Panier Client instance

const creditNoteBody = {
  // add Credit Note Body
} satisfies Panier.CreateCreditNoteBody;

const credit_note = await panier.createCreditNote(creditNoteBody)
                                .catch((error) => error);

// Now you can use the Credit Note in our app

createDebitNote()

This method is used to create a Debit Note

// First Create Panier Client instance

const debitNoteBody = {
  /** ... add Debit Note Body */
} satisfies Panier.CreateDebitNoteBody;

const debit_note = await panier.createDebitNote(debitNoteBody)
                                .catch((error) => error);

// Now you can use the Debit Note in our app

find()

This method is used to find a ZIMRA Fiscal Invoice and it's associated Credit Notes and Debit Notes

// First Create Panier Client instance
const invoice_number = 'INV000001';
const getFiscalInvoice = await panier.find(invoice_number)
                                    .catch((error) => error);

// Now you can use the Fiscal Invoice in our app

getDeviceInformation()

This method will return return information about your fiscal device, that is, Device ID, Device Serial Number, Fiscal Day, Device Status, Billing Status, Company Name.

// First Create Panier Client instance

const get_device_information = await panier.getDeviceInformation()
                                            .catch((error) => error);

// Now you can use the device information in our app

openDay()

When your fiscal day is closed, Panier automatically opens your fiscal day if you before performing any operation. However this method manually open your fiscal day.

// First Create Panier Client instance

const open_day = await panier.openDay()
                        .catch((error) => error);

// fiscalDayStatus options "FiscalDayOpened", "FiscalDayClosed", "FiscalDayCloseFailed", "FiscalDayCloseInitiated"
if (open_day?.fiscalDayStatus === 'FiscalDayOpened') {
  // Do some operation now that your fiscal day is opened
}

closeDay()

Panier automatically closes your fiscal day 23 hours and 30 minutes after your fiscal day was opened. However this method allows you to manually close your fiscal day.

/** ... First Create Panier Client instance */

const close_day = await panier.closeDay()
                            .catch((error) => error);

// fiscalDayStatus opitons "FiscalDayOpened", "FiscalDayClosed", "FiscalDayCloseFailed", "FiscalDayCloseInitiated"
if (close_day?.fiscalDayStatus === 'FiscalDayClosed') {
  /** Do some operation now that your fiscal day is closed **/
}

Schemas

Credentials

NameTypeRequiredOptionsDescription
hoststringYeshttps://panier.app/api/v1, https://dev.panier.app/api/v1Determines whether you are in the ZIMRA Test Environment or Production Environment
proxy_urlstringNoProxy URL for added Proxy support
unsecured_proxy_agentbooleanNoAllows you to self-signed certificates when using the proxy_url. This makes fetch unsecure against MITM attacks (USE AT YOUR OWN RISK!).
APP_IDstringYes
API_KEYstringYes

Product

NameTypeRequiredMax LengthDescription
namestringYes190Product name
selling_pricenumberYesProduct selling price excluding tax
quantitynumberYesNumber of units being sold
discountnumberNoDiscount amount being applied for the line item
hs_codestringYes10The unique Harmonized System Code of the product. What is a HS Code?.
zimra_tax_idnumberYesZIMRA Tax ID. See the ZIMRA Tax ID section for more information

Customer

NameTypeRequiredMax LengthDescription
namestringYes190Customer name
emailstringYes190Customer email address
phonestringYes20Customer phone number
addressstringNo190Customer physical address
tin_numberstringYes20Customer ZIMRA Tin Number
vat_numberstringNo20Customer ZIMRA VAT Number

CreateZimraFiscalInvoiceBody

NameTypeRequiredMax LengthOptionsDescription
invoice_numberstringNo50The unique identifier of the ZIMRA Fiscal Tax Invoice. If not provided a NanoID is used e.g XDVP07DIYQDO.
customerCustomerNoCustomer details
productsProduct[]Yes1000List of products on the ZIMRA Fiscal Tax Invoice
currency_codestringYesThis is the ISO 4217 Currency Code e.g ZWG or USD
money_typestringYesCash, Card, MobileWallet, Coupon, Credit, BankTransfer, OtherPayment method that your customer paid for the ZIMRA Fiscal Tax Invoice

CreateCreditNoteBody

NameTypeRequiredMax LengthOptionsDescription
invoice_numberstringYes50The invoice number of the ZIMRA Fiscal Tax Invoice that you want to credit
productsProduct[]Yes1000List of products on the Credit Note
currency_codestringYesThis is the ISO 4217 Currency Code e.g ZWG or USD.
money_typestringYesCash, Card, MobileWallet, Coupon, Credit, BankTransfer, OtherPayment method that you have settled the credit note with your customer

CreateDebitNoteBody

NameTypeRequiredMax LengthOptionsDescription
invoice_numberstringYes50The invoice number of the ZIMRA Fiscal Tax Invoice that you want to debit
productsProduct[]Yes1000List of products on the Debit Note
currency_codestringYesThis is the ISO 4217 Currency Code e.g ZWG or USD.
money_typestringYesCash, Card, MobileWallet, Coupon, Credit, BankTransfer, OtherPayment method that you have settled the credit note with your customer

Keywords

typescript

FAQs

Package last updated on 13 May 2026

Related posts