A Postman collection is the fastest way to test your integration with the Fatoora platform before writing a single line of production code. It lets you send authentication, Clearance, and Reporting requests manually, read ZATCA (Zakat, Tax and Customs Authority) responses in real time, and set up an environment of variables once to reuse across every request. This hands-on guide explains how to build a complete Postman collection for the Fatoora API from scratch: from creating the environment and defining the base URL and the Compliance CSID, through building the authentication header, all the way to exporting the collection and sharing it with your team.
This guide assumes you have completed the earlier steps in the developer hub: you obtained the Compliance CSID, understood how authentication works, and got familiar with the API endpoints. If you have not, review the Authentication guide and theAPI Endpoints guide first. Everything below is tested on the Authority’s Sandbox environment, not on production.
What is a Postman collection and why you need it with the Fatoora API
Postman is a tool for testing APIs without writing code. You use it to send HTTP requests to any server, read the response in a formatted view, and keep your requests organized in “Collections”. A collection is simply a folder holding your recurring requests in order, with environment variables shared among them.
Phase Two integration with the Fatoora platform requires a chain of sequential requests: a compliance request for the CSID, then Clearance requests for B2B invoices, and Reporting requests for B2C invoices. Each request carries precise headers and a body in UBL 2.1 format. Trying these requests manually in code is slow and error-prone. With Postman you build the request once, change a single variable, and resend it instantly.
The bigger benefit is that the collection becomes a living document for your team. Any new developer imports the collection, fills in their own environment variables, and starts testing within minutes without reading hundreds of lines of documentation. It also helps you isolate problems: if the request succeeds in Postman but fails in your application, the fault is in your code, not in the integration with the Authority.
There is a third practical reason that makes Postman indispensable in e-invoicingprojects. The Authority’s API is strict in validation, and any minor deviation in document format or field order returns a detailed rejection. When you test manually, you see the full error message and correct the document step by step before you write the generation logic in your application. This saves hours of debugging inside the code, because you separate the invoice-building problem from the invoice-sending problem.
Remember that every test in this guide runs on the Sandbox environment dedicated to developers. Do not send real invoices to production while learning, because an invoice cleared in production becomes a binding tax document. The Sandbox environment is completely safe for experimentation, and it returns responses matching production behavior with no tax impact.
Step one: create the Postman environment and its variables
Install Postman and create the environment
Download the Postman desktop app or use the web version. After opening it, create a new Environment from the sidebar. An environment is a container that stores changing values so you do not type them into every request. Give the environment a clear name such as Fatoora Sandbox to distinguish it from the production environment later.
Define the core variables
Add the following variables inside the environment. Leave the Initial Value column empty for secret values and fill in only the Current Value, because the initial value is exported with the collection and secret values could leak.
The base URL (baseUrl) points to the Authority’s Sandbox environment. When you move to production, you change only this value without touching the rest of the requests. The value in V2 in the variable acceptVersion is used in the header Accept-Version which the Authority requires on every call to the Phase Two API.
The Compliance CSID and the secret paired with it are obtained from the compliance step: you send a certificate signing request (CSR) through the Fatoora portal with a one-time password (OTP), and the Authority returns the CSID and its secret. Qoyod manages this CSID automatically inside the platform, but during manual testing you place it in Postman yourself to inspect the responses directly.
Why we separate the initial value from the current value
Postman distinguishes between two columns for each variable: the initial value and the current value. The initial value is stored inside the environment file and travels with it on export or cloud sync, while the current value stays on your machine only. The golden rule is to place every secret value in the current value alone, and leave the initial value empty. This way you share the environment structure with your team without leaking your secrets.
In practice: when you create the csidSecretvariable, write the secret in the Current Value field only. When you later export the environment to a colleague, they receive the full structure with the variable names but without the secret, so they fill in their own secret locally. This is a fundamental security habit in every project that handles credentials, and it grows more important with the Authority’s identifiers because they enable signing tax invoices on behalf of the establishment.
Manage two separate environments: Sandbox and production
Create two independent environments from the start: one for the Sandbox and another for production. They carry the same variable names but with different values, most notably baseUrl and the CSID. This separation prevents the most dangerous mistake in e-invoicing projects, which is sending a test invoice to production or vice versa. To switch between the two environments, you simply select one from the top menu in Postman without touching any request.
The Sandbox base URL differs from the production URL. The CSID in the Sandbox is the compliance CSID, and in production it is the production CSID you obtain after passing the compliance checks. Keep this distinction explicit in naming the two environments so you do not mix them during fast work.
baseUrl: the environment address (Sandbox/production)
acceptVersion: API version
csid and csidSecret: the credentials (secret)
authHeader: the built Basic header
otp: the verification code during setup
Step two: build the authentication header (Authorization Header)
The Fatoora API uses Basic authentication over an OAuth 2.0 layer. The header consists of the CSID and its secret, separated by a colon, then encoded in Base64. The format is as follows:
Instead of computing the encoding manually every time, add a Pre-request Script at the collection level. The script reads the csid and thecsidSecretvariables, combines them, encodes them, and stores the result in the authHeader variable that all requests reference.
This builds the header automatically once. Any request inside the collection adds the following line in the Headers tab, and the variable is replaced by its computed value at the moment of sending:
The Accept-Version header is mandatory and specifies the API version you are addressing. The Content-Type header tells the server that the request body is in JSON and holds the encoded UBL payload. Omitting any of these headers usually returns a 400 or 401 response, so set them at the collection level to be inherited by every request.
The reason for placing the script and headers at the collection level rather than on each individual request is inheritance. Postman applies the collection settings to every request inside it unless you explicitly override them. This means you configure authentication once, and every new request you add later benefits from it without reconfiguration. When you change the CSID or its secret, you edit the variable value in the environment only, and the header is recomputed automatically in the next request.
The nature of the Base64 encoding here is merely a transport encoding, not confidentiality encryption. Its purpose is to carry the CSID and secret in a safe text form within an HTTP header, not to hide them. So the real protection lies in not leaking the original values, not in the encoding itself. Anyone holding the encoded string can decode it easily, which is an additional reason to keep credentials local and unshared.
Combine csid:csidSecret
Base64 encoding
Add the Basic prefix
Let Qoyod manage the CSID on your behalf
Qoyod is an accounting platform ready for Phase Two of e-invoicing. It manages the CSID automatically and handles Clearance and Reporting with the Fatoora platform without manual integration.
Step three: send the compliance request (Compliance Request)
Before the CSID is approved for production, the Authority requires you to prove that your solution issues valid invoices through compliance requests on the Sandbox environment. You send samples of standard and simplified invoices and credit and debit notes, and the Authority verifies their conformance with UBL 2.1 and the Phase Two rules.
Create a new request in the collection with the POST method on the following path:
The three fields are mandatory. The invoiceHash field is the SHA-256 hash of the invoice after canonicalization, theuuid is a unique identifier for each invoice, and theinvoice is a complete UBL 2.1 document Base64-encoded. A successful compliance response returns the status CLEARED or REPORTED depending on the invoice type, in addition to any warning messages worth reviewing.
Step four: Clearance and Reporting requests (Clearance & Reporting)
Clearance for B2B invoices
The standard tax invoice between businesses (B2B) is subject to real-time clearance: you send it to the Authority first, it returns a copy stamped with its seal, and only then are you allowed to deliver it to the buyer. In Postman, create a POST request on the clearance path:
The Clearance-Status with the value 1 asks the Authority to perform full clearance and return the stamped invoice. The successful response carries the status CLEARED with the signed XML copy in the field clearedInvoice.
Reporting for B2C invoices
The simplified tax invoice for the consumer (B2C) does not require prior clearance. You issue it and deliver it to the buyer immediately, then report it to the Authority within twenty-four hours. The path is different:
The fundamental difference is that the reporting path returns the status REPORTED without a stamped invoice, because the simplified invoice was already delivered to the buyer. This distinction between clearance and reporting is the core of Phase Two integration, and testing it in Postman immediately reveals whether you are calling the correct path for each invoice type.
| Criterion | Clearance (B2B) | Reporting (B2C) |
|---|---|---|
| Endpoint | clearance/single | reporting/single |
| Clearance-Status | 1 | 0 |
| Response | clearedInvoice | REPORTED |
Step five: read the response and interpret errors
Postman displays the response in three parts: the Status Code, the headers, and the body. A 200 code means the request succeeded,202 means accepted with warnings,400 indicates an invalid request body, and401 a fault in authentication. Focus on the validationResults field in the body, as it details the warnings and errors the Authority detected.
Warnings do not block clearance but are worth addressing before production. Errors (errorMessages) block acceptance, and you must correct the invoice and resend. Note that the Authority is the party that validates the invoice and authorizes its acceptance, not the tool that issues it. Qoyod sends what you issue, and the Authority remains the reference that accepts or rejects.
When a 401 code appears, review the authHeadervariable: make sure the CSID and its secret match, that the pre-request script is running, and that the base URL is correct. The most common error in manual testing is mixing up the compliance CSID and the production CSID, or using the production environment URL with a Sandbox CSID.
Table of common errors and their solutions
A few patterns of errors recur during manual testing. Knowing them in advance shortens diagnosis time:
A 400 code with a message about an invalid format usually means the UBL payload is not correctly Base64-encoded, or that the value of invoiceHash does not match the sent document. Recompute the hash immediately after canonicalization, and verify that you are encoding the same document you computed its hash from.
A 401 always points to authentication: a wrong CSID, a wrong secret, or an Authorization header that was not injected because the pre-request script did not run. Open the Postman Console and check the actually computed value of authHeader before sending.
A 403 means the CSID is correct but does not have permission on the requested path, such as using a compliance CSID to call a production path. A 500 code is rare and comes from the server side, so retry after a short interval. As for a missing Accept-Version header, it returns an immediate rejection, so set it at the collection level as we recommended.
Batch requests to test volume
Alongside the single request, the API offers batch paths that send several invoices in one call, useful for testing integration behavior under realistic load. The batch path is analogous to the single one but receives an array of invoices instead of a single invoice, and returns a separate validation result for each element:
Testing batch requests in Postman reveals how the Authority handles the rejection of a single element within a batch: does it accept the rest or reject the whole batch. Understanding this behavior early spares you surprises in production when you send large batches.
Automate validation via the Tests tab
Postman lets you write assertions in the Tests tab for each request, so you verify the response automatically instead of inspecting it by eye. Add a script that asserts the status code is 200 and the status field holds the expected value:
These assertions turn into a safety net when you run the whole collection with Newman. Any request whose assertion fails shows up immediately in the run report, so you know the API behavior changed before your customers discover it. Build at least one assertion for every essential request in your collection.
Prepare the UBL payload before sending
The request body holds a UBL 2.1 document Base64-encoded, but before encoding you must canonicalize the document (Canonicalization) to standardize its format, then compute its SHA-256 hash which you place in the invoiceHashfield. Any difference between the encoded document and its hash returns an immediate rejection. So prepare one correct sample document, and document it inside the collection as a reference example your team measures the rest of the invoices against.
Step six: organize the collection into folders
As requests multiply, organize your collection into logical folders that ease navigation and sharing. A suggested structure:
Each folder inherits the headers and scripts from the collection level, so you do not repeat the authentication setup. This arrangement mirrors the actual integration path: compliance first, then clearance and reporting in production, with helper requests to renew the CSID when it expires.
Step seven: export the collection and share it with the team
After configuring the collection, export it to share. From the collection menu choose “Export”, then the Collection v2.1format. You get a JSON file holding all the requests, folders, and scripts, but without the secret environment values if you left the Initial Value empty as we recommended.
Share the collection file through your code repository or a Postman share link, and export the environment in a separate file where each developer fills in their own secret values locally. This way any new member imports the collection, sets their own CSID, and starts testing immediately without anyone’s credentials leaking.
For repeated automated testing, use the Newman command-line tool that runs the whole collection from the terminal, so you integrate it into your continuous integration pipeline and verify the integration’s soundness on every update:
Renew the CSID
The CSID is not permanent. Each certificate has a validity period set by the Authority, and before it expires you must renew it so invoices do not stop clearing. Add to the tools folder in your collection a dedicated renewal request that regenerates the certificate signing request and sends it to the Authority, so you get a new CSID that replaces the old one.
Testing the renewal path in Postman matters because it simulates a critical production case: a certificate suddenly expiring. When you try it on the Sandbox environment, you confirm the renewal logic works before you actually need it. In Qoyod this renewal happens automatically in the background, so the establishment is not exposed to an unexpected halt in issuing invoices.
Also watch the response headers, which sometimes carry an alert about the approaching expiry. Catching this alert early lets you schedule the renewal without interruption. These small details are what separate an integration that survives in production from one that breaks at the worst time.
Security practices during testing
Handling the Authority’s identifiers demands security discipline. The secret paired with the CSID is equivalent to a key that signs tax invoices on behalf of the establishment, and leaking it is a real risk. Follow three basic rules during testing.
First, do not put any secret in the variable’s initial value, and leave it in the current value only as we explained. Second, do not include credentials in code files or in the repository history; read them from a local, untracked environment file. Third, always use the Sandbox environment identifiers for testing, and keep the production CSID away from your daily experimentation tools.
When you share the collection through a Postman cloud workspace, remember that a shared workspace may sync the initial values. So before sharing, verify the secret fields are empty, or share the collection file only without the environment file. This habit protects your establishment from the most common credential leaks.
Frequently asked questions about the Postman collection for the Fatoora API
Do I need a Postman collection if I use Qoyod? Not for compliance itself. Qoyod handles the full integration with the Fatoora platform. But if you are a developer who wants to understand the API’s behavior or isolate a problem, the collection is an excellent diagnostic tool.
What is the difference between the compliance CSID and the production CSID? The compliance CSID is used on the Sandbox environment to pass the Authority’s checks, and the production CSID signs live invoices after passing those checks. Each environment has its own CSID.
Why do I get a 401 code even though the CSID is correct? Usually because the pre-request script did not build the Authorizationheader, or because the secret does not match. Open the Postman console and check the actual value of authHeader .
Are test invoices saved in my tax record? No. Sandbox environment invoices have no tax impact at all. The tax impact begins only with production invoices cleared with the production CSID.
How do I share the collection without exposing my secrets? Export the collection file alone, and leave the secret values in the current value of the local environment only. Your colleague imports the structure and fills in their own CSID.
How Qoyod shortens these steps
Everything above is necessary for anyone building a direct integration with the Fatoora platform. Qoyod is an accounting platform ready for Phase Two that handles this entire layer: it manages the CSID automatically, builds the authentication headers, sends B2B invoices for clearance and B2C invoices for reporting, and stores the invoice hash chain to verify compliance. You issue the invoice from the Qoyod interface, and the platform handles the dialogue with the Authority behind the scenes.
The Postman collection remains a valuable tool for developer teams to understand the integration, isolate problems, and verify the API’s behavior. But an establishment that wants immediate compliance without building an integration finds it ready in Qoyod from day one.
In short, a Postman collection gives you a direct view of every step in the e-invoicing dialogue with the Authority: from setting up the variables and building the header, to sending the compliance, clearance, and reporting requests, and reading the responses and exporting the collection for your team. Master this tool to understand the integration deeply, then let Qoyod handle running it in production on your behalf with stability and security.