Qoyod
Pricing

Knowledge Base

OAuth Authentication in the Fatoora API

When you build a system that talks to external programming interfaces (APIs), one question comes up before anything else: who are you, and what are you allowed to access? This is the essence of “authentication” and “authorization.” In the world of e-invoicing, systems prove their identity to each other in several ways, and one of the most common is the OAuth 2.0 standard, which has become the shared language of most modern interfaces.

In this guide we explain OAuth authentication from the ground up for developers and technical integrators: what it is, how the access-token flow works, the difference between an access token and a refresh token, and what scopes mean. Most importantly, we clarify a subtle point that is often misunderstood: the ZATCA Fatoora platform APIs do not use OAuth to send invoices; they rely on Basic Authentication with a CSID certificate. Confusing the two is a very common cause of integration errors.

What is OAuth 2.0 authentication?

OAuth 2.0 is an open standard for authorization that lets an application or service access protected resources on another server without sharing the original password. Instead of passing a username and password on every request, the application obtains a temporary “access token” that proves its identity and permissions.

The core idea is simple. Imagine a hotel that gives you an electronic key card instead of a master key to every door. The card opens only your room, for a limited time, and can be revoked at any moment without changing all the hotel’s locks. An access token in OAuth works the same way: limited scope, limited duration, and instant revocability.

It is important to distinguish two terms that are often confused. “Authentication” means proving who you are. “Authorization” means defining what you are allowed to do after your identity is proven. OAuth is at its core an authorization standard, but in practice it is used as a layer that proves identity and grants permission together in system integrations.

OAuth solves an old problem in system integration. Before it, applications stored users’ passwords to act on their behalf — a dangerous practice. With OAuth the application never sees the password; instead it receives a limited-lifetime token that can be revoked without touching the original account.

Why does OAuth matter in invoicing-system integration?

Modern e-invoicing systems rarely operate in isolation. An accounting system like Qoyod may integrate with an e-commerce platform, a point-of-sale system, a payment gateway, or a middleware platform that connects several systems together. Every one of these integrations needs a secure way to prove identity and exchange data.

This is where OAuth comes in. When an external system wants to read your invoices or create invoices in your accounting system through an API, it needs an authenticated, limited permission. OAuth grants that permission without handing over full login credentials, and it allows you to precisely define what each application can access through scopes.

The practical benefit is that scopes enable the principle of “least privilege.” An application that only needs to read invoices is not granted permission to delete them or change account settings. This reduces the damage if a token leaks and makes security auditing clearer.

An important note before we go deeper. Qoyod is an accounting system that manages the e-invoicing cycle and handles the connection to the Fatoora platform on behalf of the business. The authentication mechanisms we explain here relate generally to integrating systems through APIs, not specifically to the step of sending an invoice to the Authority — a point we will detail in a later section.

The Client Credentials Grant flow

The OAuth 2.0 standard defines several types of “grant flows,” each suited to a different scenario. In server-to-server system integration, where there is no human user clicking an approval button, the most suitable flow is the “Client Credentials Grant.”

How this flow works step by step

In this type, the integrated system holds a Client ID and a Client Secret that the service provider issued to it in advance. The system uses these two elements to obtain an access token from the authorization server, then uses the token on every subsequent request to the API.

The Client Credentials flow in OAuth
How a system obtains an access token via OAuth.
1

Send Client ID and Secret

2

The authentication server verifies

3

Access Token with expires_in

4

Use the Bearer Token in requests

The Client Credentials flow is used for server-to-server integration.

In practice, everything starts with a single request to the Token Endpoint. The system sends its credentials and requests a token, as in the following example:

POST /oauth/token HTTP/1.1
Host: api.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=invoices.read invoices.write

If the data is correct, the authorization server responds with an access token and additional data describing its type, lifetime, and granted scopes:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "invoices.read invoices.write"
}

After obtaining the token, the system places it in the header of every subsequent request to the API. The standard authorization header is used with the word Bearer, which means “bearer of the token”:

GET /v2/invoices HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json

The server verifies the token on every request: is it valid? Has it expired? Does it carry the scope required for this operation? If it passes the check, the operation is executed. This separation between permanent credentials and a temporary token is what makes OAuth more secure than passing a password on every request.

Access token and refresh token: the difference and the cycle

An access token is short-lived by nature. The common lifetime is one hour or less, as we saw in the expires_in value in seconds. This brevity is deliberate: if the token leaks, it expires quickly and the window of risk shrinks.

But a token expiring every hour raises a practical question: does the system resend its credentials every time? In the Client Credentials flow, yes — the system requests a new token when the old one expires, because it holds the secret key in the first place. In flows that involve a human user, however, the “refresh token” appears.

A refresh token is a long-lived token used to request a new access token without full re-authentication. When the access token expires, the system sends the refresh token to the authorization server and gets a new access token. This keeps the session going without asking the user to log in every hour.

Access token vs. refresh token
The difference between an Access Token and a Refresh Token.
Criterion Access Token Refresh Token
Lifetime Short Long
Where it is sent With every request To the renewal endpoint only
Purpose Accessing resources Renewing the access token
The access token is short-lived, and the refresh token renews it without re-authentication.

The refresh request looks like this. Note that grant_type has changed to refresh_token:

POST /oauth/token HTTP/1.1
Host: api.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=def502004a8f...
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

An important practical rule for every developer: store the refresh token in a secure place, and never send it with ordinary resource requests. A refresh token is more valuable than an access token because it opens the door to issuing new tokens. Its leak is far more dangerous than the leak of a single access token that will expire within minutes.

Scopes: defining permissions precisely

A scope in OAuth is a text label that defines a specific permission. When requesting a token, the system asks for a set of scopes, and the authorization server grants only those it is entitled to. The resulting token is confined to these scopes and cannot exceed them no matter what.

In the invoicing context, scopes might look like this: a scope to read invoices, a scope to create them, a scope to read customer data, and a scope to manage products. When designing an integration, request only the scopes the application actually needs. Granting excess permissions without need is a security risk with no benefit.

This principle is known as “least privilege,” and it is one of the most important rules of API security. Every extra permission you grant an application is an extra door that could be misused if the application is compromised.

Types of OAuth grant flows and which one suits invoicing

OAuth is not limited to a single flow. The standard defines several types of grants, each designed for a different scenario. Choosing the right type is the first decision a developer makes, because using an unsuitable flow opens security gaps or complicates the integration needlessly.

The Client Credentials flow is the most suitable for server-to-server integration, where no human user is in the picture. This is the prevailing pattern in invoicing- and accounting-system integrations, because the application itself owns the resources rather than acting on a user’s behalf.

The Authorization Code flow suits cases where a human user grants an application permission to access their data. For example, when a store owner links their account in an accounting system to an external tool, a consent screen appears. This flow uses the refresh token heavily to keep the session alive.

There are legacy flows such as the Password Grant and the Implicit flow that are no longer recommended for security reasons in most cases. The practical rule: for technical system-to-system integration use Client Credentials, for authorizing a human user use the Authorization Code, and avoid the rest unless there is a strong reason.

A quick table for choosing the right flow

When building an invoicing integration, ask yourself one question: is there a human user who approves access, or are the two systems talking directly? If the two systems talk directly, Client Credentials is your choice. And if a user authorizes an application on their behalf, the Authorization Code is the most suitable. This distinction settles most design decisions.

JWT tokens vs. opaque tokens

Access tokens in OAuth come in two main forms. The first is a JWT (JSON Web Token), a signed token that carries readable information inside it after decoding, such as the client identity, scopes, and expiry time. The server verifies its signature without going back to a database every time.

The second form is the opaque token, a random string that carries no meaning in itself. To verify it, the server must go back to the authorization server or the database. This form is slightly slower but allows the token to be revoked immediately, whereas a JWT remains valid until it expires unless an additional revocation mechanism is added.

For the integrating developer, the practical difference is simple: do not try to interpret the content of an opaque token, and treat it as a closed box. A JWT, on the other hand, lets you read its data for diagnostics, but do not trust its content without first verifying the signature — reading is one thing and trusting is another.

A practical case: an online store integrating with an accounting system

Let’s bring the concepts together in a real scenario. An online store wants to send every new sale order to an accounting system to be turned into a compliant invoice. How does authentication work here from start to finish?

First, the store registers an application with the accounting system and receives a Client ID, a Client Secret, and specific scopes — most notably the invoice-creation scope. This is a one-time step during setup.

Second, on the first request, the store uses the client credentials to obtain an access token from the token endpoint. The store stores the token and its expiry time in memory and does not request a new token before the current one expires.

Third, with every sale order, the store sends the invoice data to the API carrying the access token in the header. The accounting system verifies the token and the scope, then creates the invoice and in turn handles the connection to the Fatoora platform via a CSID certificate. Note here that the store never touched Basic Authentication with the Authority at all.

Fourth, when the token nears expiry or the server responds with a 401 error, the store requests a new token and retries. Through this simple cycle the integration stays secure and continuous without human intervention.

This scenario illustrates the correct division of responsibilities: the store authenticates with the accounting system via OAuth, and the accounting system authenticates with the Authority via CSID. Each layer with its appropriate mechanism. For more detail on the invoice’s technical layer and the integration test environment, see The developer Sandbox environment.

Start today

Compliant e-invoicing without the technical hassle

Qoyod handles the connection to the Fatoora platform, certificate management, and digital signing on your behalf, so you issue Phase-Two-compliant invoices without building the authentication layer yourself.

Start your free trial and issue your first invoice

A subtle point: the Fatoora platform APIs do not use OAuth

Here is the most important correction in this guide, and a recurring mistake among developers new to Saudi e-invoicing. The Fatoora platform APIs of the Zakat, Tax and Customs Authority, responsible for clearance and reporting, do not use OAuth 2.0 to send invoices. They rely on Basic Authentication using a CSID certificate.

The difference is fundamental. In Basic Authentication, the invoicing system sends credentials based on the Cryptographic Stamp Identifier (CSID) certificate that the Authority issues for each invoice-generation unit. This certificate, together with its associated private key, is what proves the system’s identity to the Fatoora platform during clearance and reporting. There is no temporary access token requested from a token endpoint, and no Client Credentials flow of the kind we described.

OAuth vs. authentication with a CSID certificate
When to use OAuth and when to use Basic Auth with a CSID certificate.
Criterion OAuth Basic Auth with CSID
Use General server-to-server integration Fatoora platform APIs
Mechanism Temporary access token Fixed CSID certificate
Lifetime Expires and is renewed According to the certificate’s validity
The Fatoora invoice APIs use Basic Auth with CSID, not OAuth.

Why did the Authority choose this approach? Because the goal is not merely temporary identity proof, but binding each invoice to a fixed cryptographic identity that cannot be forged. An X.509 CSID certificate provides this binding through a digital signature, a requirement that goes beyond what a simple access token offers. For details on the certificate itself, see the guide The CSID and the Cryptographic Stamp Identifier.

The practical takeaway: if you are building a direct integration with the Fatoora platform, you will deal with Basic Authentication and a CSID certificate, not with OAuth. But if you are building an integration with an accounting system or a middleware platform that in turn handles the connection to the Authority, you may deal with OAuth at that system’s layer. Understanding which layer you operate on determines the correct authentication mechanism.

Where does OAuth actually appear in the invoicing ecosystem?

After clarifying that the Fatoora platform does not use OAuth, the question remains: where does it appear, then? The answer is in the layers that precede the Authority or surround it, not in the step of sending to it.

The first scenario is middleware platforms. Many large enterprises use a middleware layer that gathers invoices from several internal systems and then connects them to the Fatoora platform. The internal systems talk to the middleware through an API protected by OAuth, and the middleware in turn handles Basic Authentication with the Authority via CSID.

The second scenario is integration with accounting and commercial systems. When an online store links itself to an accounting system to send order data to be turned into invoices, this interface is usually protected by OAuth. The accounting system is the one that later handles dealings with the Authority. This is the pattern by which Qoyod’s integration with external systems operates.

The third scenario is data-reading and reporting interfaces. A dashboard application that reads invoice data to display reports does not need create or send permission, so it is granted an access token with a read-only scope. Here the benefit of scopes in restricting permission precisely becomes clear.

To understand how the actual connection with the Authority works and the sequence of steps, see the guides API integration with the Fatoora platform andOnboarding and connecting to the Fatoora platform, both of which explain the layer that the Authority handles directly.

OAuth security best practices for developers

Building a sound authentication layer requires adhering to a set of rules that condense years of industry mistakes. Here are the most important:

  • Store the Client Secret in a secrets vault, not in source code and not in a Git repository. Its leak means the complete exposure of your identity.
  • Use the HTTPS protocol on every request without exception. Sending an access token over an unencrypted connection makes it vulnerable to interception.
  • Request the fewest possible scopes. Do not request write permission if your application only reads.
  • Handle token expiry gracefully. When the server responds with a 401 error, request a new token and retry instead of showing the user an error.
  • Store the refresh token more securely than the access token, and send it only to the token endpoint.
  • Monitor issued tokens, and immediately revoke any token suspected of leaking through the revocation mechanism the service provider offers.

These practices are not a luxury. The authentication layer is the first door to any system, and once it weakens, all security collapses no matter how strong the other layers are.

Add to that two practical rules that are often neglected. The first is setting time-outs for token requests, so your system does not stall waiting for a slow or unresponsive authorization server. The second is adopting a smart retry mechanism with escalating delay when a request fails, instead of bombarding the server with successive requests that increase load and may lead to a temporary block. A sound integration tolerates temporary failures calmly rather than collapsing at the first network error.

Handling common authentication errors

When building the integration, you will inevitably encounter authentication errors. Understanding their codes saves hours of tracing. The most common is the 401 code, which means the request is unauthorized: either the token is missing, expired, or invalid. The fix is usually to issue a new token.

The 403 code, on the other hand, means your identity is established but your permission is insufficient for this operation. Here the problem is with scopes: the token is valid but does not carry the required scope. The fix is to request a token with an appropriate scope, not merely to re-authenticate.

The 400 code when requesting the token itself usually points to an error in the request parameters: a wrong grant_type, a missing parameter, or incorrect encoding of the body. Review the request structure character by character, as small encoding errors are a recurring cause of token-issuance failure.

A final golden rule: do not print secret tokens in system logs. Many leaks happened because an access token or a secret key appeared in a log file viewed by an unauthorized party. Log that the operation took place, not the token value itself.

How Qoyod simplifies the authentication layer for you

All of the above shows that building a sound authentication layer is delicate work and a major security responsibility. The good news is that Qoyod handles the hardest part on your behalf in everything related to e-invoicing.

Qoyod is a cloud accounting system that manages the entire e-invoice cycle. It connects your business to the Fatoora platform, securely manages the CSID certificate and the private key, digitally signs every invoice, and handles clearance for business-to-business invoices and reporting for individual invoices. You do not deal with Basic Authentication or certificate details yourself.

And when you need to connect your external systems to Qoyod, such as your online store or point-of-sale system, you deal with a modern, protected API. The result is that you focus on your business, while Qoyod handles the complexity of technical compliance and authentication layers together.

Try Qoyod free for 14 days without a credit card.

Frequently asked questions

Does the Fatoora platform use OAuth to send invoices?
No. The Fatoora platform APIs of the Zakat, Tax and Customs Authority use Basic Authentication built on a CSID certificate for clearance and reporting, not OAuth. OAuth appears in general system-integration layers and middleware platforms, not in the step of sending to the Authority.

What is the difference between an access token and a refresh token?
An access token is short-lived and is sent with every request to access protected resources. A refresh token is long-lived and is used only to request a new access token when the old one expires, and it is stored more securely.

What is the Client Credentials Grant flow?
It is a grant type in OAuth dedicated to server-to-server integration without human-user intervention. The system uses the Client ID and its Client Secret to obtain an access token directly from the authorization server.

What are scopes?
Scopes are labels that define a token’s permissions precisely, such as reading or creating invoices. They enable applying the principle of least privilege, so the application is granted only what it actually needs.

Do I need to build an OAuth layer myself to use e-invoicing in Qoyod?
No. Qoyod handles the connection to the Fatoora platform, certificate management, digital signing, clearance, and reporting on your behalf. You use the system directly without building an authentication layer with the Authority.

What does the 401 error mean when calling an API?
It means the request is unauthorized, usually due to a missing, expired, or invalid token. The solution is usually to issue a new access token and retry.

Guides

Continue your learning journey

Explore the rest of Qoyod’s guides, or start applying what you’ve learned.

Live webinars hosted by the Qoyod team to help you use the software easily and answer your questions.

Discover Qoyod’s latest updates, ongoing improvements, and new features in one place.

Our team is ready to help you and provide instant support for any issue you face, around the clock.