Skip to main content

Credit notes

POST /v1/credit-notes credits items of an issued sales invoice and issues the credit note in one call. There is no draft step, and an issued credit note is never cancelled. The credited goods go back to stock.

Required fields​

Every request sends invoiceId, reason and lines, with an Idempotency-Key header like every POST:

{
"invoiceId": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
"reason": "refund",
"lines": [{ "itemId": "7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f", "quantity": 1 }],
"refund": { "paymentMethodId": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9" }
}

The credit note takes its branch, its customer and its prices from the invoice. Each line names an item sold on that invoice, once, with a whole quantity no larger than what is left of that item to credit. A unit is credited at its share of what the invoice charged for the item. On an invoice issued through the API, each line is rounded to the halala the way ZATCA totals the credit note, so crediting units one at a time can come to a halala more than crediting them together. Such a credit note may therefore pass what is left of the invoice by one halala for each credit line already issued on it, and always by at least one halala, so the last units can always be credited.

The full reply is in the API reference.

reason is sent to ZATCA as the reason for the credit note:

reasonUse it when
cancellationthe sale is cancelled, fully or in part
refundgoods or services are returned and the money is given back
informationChangethe invoice's details were wrong and are being corrected

notes takes up to 500 characters and is printed on the credit note. referenceId takes up to 100 characters and must not be used by any other invoice or credit note of the merchant.

Paying the money back​

With refund, the credit note's total is paid back through refund.paymentMethodId, out of that method's treasury for the invoice's branch:

  • A method whose treasury serves only another branch is refused (422 payment_method_not_in_branch).
  • The refund cannot be more than the invoice has collected, less what was already paid back on it (422 refund_exceeds_collected).

Without refund, the total comes off what the customer owes. The sales invoice's amountDue drops by it, never below 0, and whatever is left over stays as the customer's credit. Only a customer who can hold a balance can be credited this way:

  • A company customer always can.
  • An individual customer carries no balance, so they can be credited this way only up to what the invoice still owes. Above that, send refund (400 invalid_parameter on refund).
  • A sale with no customer needs refund (400 invalid_parameter on refund).

This holds for a sale paid by card at a till too: without refund, the credit goes to the customer's balance, and nothing is refunded to the card.

The reply shows the money paid back as refund.amount, or refund: null when the credit went to the customer's balance.

How much can be credited​

The credits on an invoice never add up to more than its total, whatever channel issued them. Refunds made at the till or on the dashboard, sales returns, and credit notes issued through the API all count against the same total, and against the quantity left of each item. A credit above what is left answers 422 credit_exceeds_invoice:

  • param is lines[i].quantity when that line asks for more than is left of its item.
  • param is lines when the credit note's total is more than is left to credit on the invoice.

Two credit notes for the same invoice sent at the same moment are issued one after the other, so the second one is checked against what the first one left. If the first one is still being issued after 30 seconds, for example while it waits for ZATCA, the second answers 409 invoice_busy. Send it again.

ZATCA​

A credit note is the same kind of ZATCA document as its invoice:

  • Standard invoice:
    • The credit note is cleared by ZATCA before the reply.
    • If ZATCA rejects it, nothing is saved and the reply is 422 zatca_rejected with ZATCA's messages in zatcaErrors.
    • If ZATCA does not answer in time, the reply is 201 with zatca.status: "pending". Kosoor sends it again later, and it becomes cleared, or rejected with ZATCA's messages in zatca.errors. Either way the credit note stays issued.
    • An invoice ZATCA has not cleared yet cannot be credited (409 invoice_not_cleared on invoiceId). Retry once GET /v1/sales-invoices/{id} shows zatca.status as cleared; that read needs sales_invoices:read. A 4xx reply is not stored, so the retry may keep its Idempotency-Key.
  • Simplified invoice: the credit note is reported to ZATCA after the reply. zatca.status is pending until then, and becomes reported, or rejected with ZATCA's messages in zatca.errors.

An invoice ZATCA rejected cannot be credited through the API (422 invoice_not_creditable). Correct the sale with the merchant first.

GET /v1/credit-notes/{id}/pdf and GET /v1/credit-notes/{id}/xml return the credit note's documents:

  • A standard credit note's PDF and XML answer 409 invoice_not_cleared until ZATCA clears it, and for good if ZATCA rejects it.
  • A simplified credit note's PDF is ready straight away. Its XML answers 409 invoice_not_cleared until ZATCA has accepted the report, and for good if ZATCA rejects it.

Refusals​

ErrorWhen
422 referenced_resource_not_foundthe invoice does not exist or is in a branch your key may not use, or the refund's payment method does not exist or is disabled; param names the field
422 invoice_not_creditablethe invoice is not an issued sales invoice, it was imported, or ZATCA rejected it
409 invoice_not_cleared on invoiceIdthe invoice is standard and ZATCA has not cleared it yet
400 invalid_parameter on lines[i].itemIdthe item was not sold on this invoice
422 credit_exceeds_invoicea line asks for more than is left of its item, or the total is more than is left to credit
400 invalid_parameter on refundno refund was sent, and the customer cannot hold the credit as a balance
422 payment_method_not_in_branchthe refund's payment method pays out of a treasury that serves only another branch
422 refund_exceeds_collectedthe refund is more than the invoice has collected
422 used_subscription_not_refundablethe invoice sold a subscription whose visits are already used
422 refund_method_not_supportedthe sale was paid by card on the merchant's online store; a card refund cannot be started through the API
422 loyalty_refund_blockedthe loyalty platform blocked the credit: points or stamps earned on the sale were already spent, the platform could not be reached, or it has not received the sale yet; the message says which. Retry once a few minutes later; if it is refused again, the merchant can issue it from the dashboard, where a supervisor may override
409 reference_id_takenanother invoice or credit note already has this referenceId; existingId names it only when it is a credit note your key may read
409 invoice_busy on invoiceIdanother request held the invoice for more than 30 seconds; send the request again
422 zatca_rejectedZATCA rejected the credit note of a standard invoice; nothing is saved, and ZATCA's messages are in zatcaErrors
422 credit_note_not_issueda business rule with no code of its own refused the credit note; the message names the rule

When a request is refused, no credit note is issued and nothing is saved.

Reading credit notes​

GET /v1/credit-notes lists every issued credit note in the key's branches, whichever channel issued it, including refunds made at the till or on the dashboard. createdVia says which. Filter with invoiceId, customerId, branchId, referenceId, issuedAfter, issuedBefore and zatcaStatus.

Sales returns and credit notes made on the dashboard's accounting screens are not listed, though they count against what is left to credit on the invoice.

refund.paymentMethodId is null when the refund named no payment method, as till refunds usually do: the money went back through the branch's own till, or to the card the sale took. A till refund split between cash and card shows one refund with the two added together.

A refund made before credit notes recorded a reason shows reason: "cancellation", the reason it was sent to ZATCA with.