Skip to main content

ZATCA results

Every sales invoice and credit note carries a zatca object that says where it stands with ZATCA. If ZATCA is new to you, read Start here first.

{
"kind": "standard",
"status": "cleared",
"uuid": "e7f8a9b0-c1d2-4e3f-a4b5-c6d7e8f9a0b1",
"counter": 18,
"hash": "zXab+32ksuccBzrDiE27f65AmOvbZ2ixbnSSRnoRKzA=",
"qr": "ARBTYW5kYm94IE1lcmNoYW50Ag8zOTk5OTk5OTk5MDAwMDMDFDIwMjYtMTEtMDdUMDk6NDE6MjJaBAYyMzAuMDAFBTMwLjAw",
"submittedAt": "2026-11-07T09:41:21.884Z",
"clearedAt": "2026-11-07T09:41:22.517Z",
"reportedAt": null,
"errors": []
}
FieldMeaning
kindstandard for a company customer, simplified for a person
statuspending, cleared, reported or rejected
uuidthe document's UUID in ZATCA's records
counterZATCA's invoice counter value
hashthe document's hash, which the next document chains to
qrthe QR code in Base64; on a standard document, the one ZATCA returned when it cleared it
submittedAtwhen Kosoor signed the document, in UTC
clearedAtwhen ZATCA cleared a standard document, in UTC
reportedAtwhen ZATCA accepted the report of a simplified document, in UTC
errorsZATCA's messages when it rejected the document, each with code, category and message

uuid, counter, hash, qr and submittedAt are null until Kosoor signs the document.

What to do with each status​

pending​

The document is issued and valid in Kosoor; ZATCA has not accepted it yet.

  • Simplified: this is the normal state right after issue. Kosoor reports the document after its reply, and it turns reported. Its PDF is ready at once; its XML answers 409 invoice_not_cleared until ZATCA accepts the report.
  • Standard: ZATCA did not answer while Kosoor was clearing it. Kosoor sends it again later, and it turns cleared or rejected. Until then its PDF and XML answer 409 invoice_not_cleared, and a credit note against it answers 409 invoice_not_cleared too.

Do not issue the sale again: a new invoice is a second sale. If your request timed out and you do not know whether it went through, send it again with the same Idempotency-Key, which returns the first reply.

cleared​

ZATCA cleared this standard document. Its PDF and XML are ready, and qr holds ZATCA's QR code. Nothing to do.

reported​

ZATCA accepted the report of this simplified document. Its XML is ready. Nothing to do.

rejected​

ZATCA refused the document. errors holds its messages:

{
"kind": "standard",
"status": "rejected",
"uuid": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
"counter": 20,
"hash": "PO9Je+Enxi/tc010iSgP6H+piJDaQh6zQZ41v6aDPsk=",
"qr": "ARBTYW5kYm94IE1lcmNoYW50Ag8zOTk5OTk5OTk5MDAwMDMDFDIwMjYtMTEtMDdUMTA6MDI6MTFaBAYxMTUuMDAFBTE1LjAw",
"submittedAt": "2026-11-07T10:02:11.430Z",
"clearedAt": null,
"reportedAt": null,
"errors": [
{ "code": "BR-KSA-63", "category": "KSA", "message": "Buyer street is missing" }
]
}

The document stays in Kosoor, but:

  • its XML answers 409 invoice_not_cleared for good, and so does a standard document's PDF;
  • an invoice ZATCA rejected cannot be credited through the API (422 invoice_not_creditable).

Show the merchant ZATCA's messages. The merchant corrects the sale on the Kosoor dashboard.

When ZATCA rejects a standard invoice at issue​

A standard invoice is cleared before Kosoor replies. If ZATCA rejects it then, nothing is saved, no number is used, and the call answers 422 zatca_rejected with ZATCA's messages in zatcaErrors:

{
"error": {
"type": "business_rule_error",
"code": "zatca_rejected",
"message": "ZATCA rejected the invoice, so nothing was saved. ZATCA's messages are in zatcaErrors.",
"param": null,
"docUrl": "https://docs.kosoor.com.sa/errors#zatca_rejected",
"zatcaErrors": [
{ "code": "BR-KSA-63", "category": "KSA", "message": "Sandbox sample rejection: the buyer's street is missing" }
]
}
}

Fix the data ZATCA names, usually on the customer with PATCH /v1/customers/{id}, and send the invoice again under a new Idempotency-Key. The same holds for a credit note on a standard invoice.

In the sandbox, the fixture customers Sandbox ZATCA Pending Co and Sandbox ZATCA Rejected Co give these two outcomes every time. See Test mode.

Results that arrive later​

A document that answered pending gets its result later, and Kosoor pushes it to your system: register a webhook endpoint for the salesInvoice.zatca* and creditNote.zatca* events. See Webhooks. Without one, read the document again with GET /v1/sales-invoices/{id} or GET /v1/credit-notes/{id} when your system needs its status, and use zatcaStatus=pending on either list to find the documents still waiting.