BR-KSA-60 Warning — the invoice is accepted

Cryptographic stamp (KSA-15) missing from a simplified document

A simplified invoice and its notes are stamped in your own system before they are handed to the customer and reported, and the Authority does not stamp them for you. The test as it runs looks for a cac:Signature block in the document and finds none, or finds it empty. The SDK rates it a warning, but the stamp itself is checked in another stage.

The message text as the Authority sends it in English, unedited

Cryptographic stamp (KSA-15) must exist in simplified tax invoices and associated credit notes and debit notes (KSA-2, position 1 and 2 = 02).

What does this mean?

Who stamps what: a tax invoice (B2B) is sent to the Authority for clearance, and the Authority adds its stamp and QR code and returns the file stamped. A simplified invoice and its notes have no clearance: the Authority's detailed guidelines require the taxpayer's e-invoicing solution to stamp them with the cryptographic stamp identifier (CSID) the Authority issued to it, to include a QR code with nine tags, and then to report them within 24 hours. That is why the rule runs only on a document whose transaction type code (KSA-2) starts with 02 — the simplified invoice and its credit and debit notes. How that code is built is in BR-KSA-06.

What exactly is checked: the executable test in the Authority's SDK is that the document contains a cac:Signature element and that it is not empty. That is UBL's signature reference block, and it carries two fixed values: cbc:ID set to urn:oasis:names:specification:ubl:signature:Invoice, and cbc:SignatureMethod set to urn:oasis:names:specification:ubl:dsig:enveloped:xades. The stamp itself — the XAdES signature with its certificate, the invoice hash and the signature value — lives in the ext:UBLExtensions block at the top of the file, and this rule does not open it.

So the stamp is spread over several checks. Neighbouring rules check the fixed values themselves: BR-KSA-28 the signature information ID, an error; BR-KSA-29 the referenced signature ID, a warning; and BR-KSA-30 the signature method, an error. And whether the signature holds — is the hash the hash of this document, does the signature verify against the certificate — is checked in a separate stage of the Authority's validator, outside these rules, with messages such as wrong invoice hashing and wrong signature Value.

This code is rated a warning in the SDK, so do not read it as permission to send without a stamp: the guidelines require the stamp on a simplified document, and the signature carried in the seventh tag of the QR code does not exist until the document is stamped. The stamp is also a link in the chain: the hash it signs is the hash the next document carries as its previous invoice hash.

Why does it happen?

Ordered from the most common to the least — your cause is most likely the first or the second.

  • Assuming the Authority stamps every invoice the way it stamps a tax invoice, and sending the simplified one to the reporting API unstamped.
  • Sending the file as it was before signing: the signing function returns a new document, and the code sends the variable that holds the old one.
  • The hashing step removes cac:Signature — correctly, for the hash — and the stripped copy is then saved as the final document, so the file goes out with a stamp at the top and without the block this rule looks for.
  • Signing invoices but not notes: the simplified credit or debit note goes through another code path that never reaches the signer.
  • An empty <cac:Signature/> in the template, meant to be filled by the signer, and never filled.

How to fix it

4 steps, then send the invoice again.

  1. 1
    Stamp the simplified document in your system before it leaves

    With the private key of the stamp certificate the Authority issued to the e-invoicing unit that issues the document: compute the hash, sign it, build the stamp block, then build the QR code from the hash and the signature, and only then hand the document to the customer and report it to the Authority within 24 hours. The six steps of computing the hash are in BR-KSA-26.

  2. 2
    Write both blocks

    The ext:UBLExtensions block is the first element in the document, holding the signature information and the XAdES signature. The cac:Signature block sits in the body of the document, after the additional document references (ICV, then PIH, then QR) and before the seller party: <cac:Signature><cbc:ID>urn:oasis:names:specification:ubl:signature:Invoice</cbc:ID><cbc:SignatureMethod>urn:oasis:names:specification:ubl:dsig:enveloped:xades</cbc:SignatureMethod></cac:Signature>. Both values are fixed, character for character, and BR-KSA-29 and BR-KSA-30 check them.

  3. 3
    Send the signer's output as it is

    The hash is computed over the canonicalised document, and canonicalisation keeps the spaces and line breaks inside the content. So reformatting the file after signing — indentation, new lines — changes what was signed, and the signature check fails even with every block in its place. Store the text that came out of the signer, and send exactly that.

  4. 4
    Check the document before you report it

    Three signs are enough: a non-empty ds:SignatureValue inside ext:UBLExtensions, the cac:Signature block with its two values, and a QR code carrying the Phase 2 fields. The last one can be read with the QR code reader, which tells you whether it is a Phase 1 or a Phase 2 code.

This code does not block acceptance, so the invoice you have is compliant. Correct the data so the warnings disappear from future invoices.

Does ZATCA Tools prevent it?

Yes. Every document ZATCA Tools issues is signed before it leaves — the simplified invoice and its notes, and the tax invoice too, before it is sent for clearance — inside the same transaction that claims the counter and the previous hash, with the establishment's certificate or the branch device's. In that same step the library writes the stamp block at the top of the file, the cac:Signature block with its two values, and the QR code, and the file sent to the Authority is the signer's own output, never reformatted. If signing fails, issuing stops and nothing is sent.

Related codes

Frequently asked questions

My tax invoice does not carry my stamp. Does this code apply to it? +
No. The test runs only on a document whose transaction type code starts with 02. A tax invoice is stamped by the Authority at clearance and comes back as a stamped file with its QR code, and that file is the one you keep and share with the buyer. The difference between the two documents is in standard vs simplified tax invoice.
It is a warning. Does that make the stamp optional? +
No. The warning is the rating of this one test, and the test sees nothing but the cac:Signature block. The stamp itself is required by the guidelines on every simplified document, its validity is checked in another stage of the validator, and the QR code cannot carry the invoice signature without it. Do not build on the warning rating.
I stamped the document and the code still appears. Why? +
Because the test looks for cac:Signature, not for the XAdES signature. Open the file that was actually sent: if you find ext:UBLExtensions at the top and no cac:Signature in the body, the signer did not write it or the hashing step removed it. If you find neither, what was sent is the file from before signing.
Is a simplified credit note stamped too? +
Yes. The rule's text names the simplified invoice and its credit and debit notes, and the test runs on everything whose code starts with 02. A note uses up a counter value and a hash just as an invoice does, so it is a link in the same chain. How notes work is in credit and debit notes in Saudi e-invoicing.
Which certificate do I stamp with? +
The stamp certificate the Authority issued to the e-invoicing unit issuing the document. Each unit has its own certificate, its own chain and its own counter; two units stamping with one certificate at the same moment both build on the same previous hash — see BR-KSA-26.
You fixed this one — now avoid the next

ZATCA Tools builds the signature, the PIH, the counter and the encoding for you, and validates your data before it is sent. Start free, with no credit card.

Start for free

← All ZATCA error codes