# ZATCA results

> What each ZATCA status on an invoice or credit note means, what your system should do with it, and how results that arrive later reach you.

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](https://docs.kosoor.com.sa/start-here.md#zatca-in-five-minutes) first.

```json
{
  "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": []
}
```

| Field | Meaning |
|---|---|
| `kind` | `standard` for a company customer, `simplified` for a person |
| `status` | `pending`, `cleared`, `reported` or `rejected` |
| `uuid` | the document's UUID in ZATCA's records |
| `counter` | ZATCA's invoice counter value |
| `hash` | the document's hash, which the next document chains to |
| `qr` | the QR code in Base64; on a standard document, the one ZATCA returned when it cleared it |
| `submittedAt` | when Kosoor signed the document, in UTC |
| `clearedAt` | when ZATCA cleared a standard document, in UTC |
| `reportedAt` | when ZATCA accepted the report of a simplified document, in UTC |
| `errors` | ZATCA'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:

```json
{
  "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`:

```json
{
  "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](https://docs.kosoor.com.sa/test-mode.md).

## 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](https://docs.kosoor.com.sa/webhooks.md). 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.

Source: https://docs.kosoor.com.sa/zatca
