MCP tools
Invoices and e-invoicing
MCP tools for ZATCA tax invoices, credit and debit notes, the activity log, the archive and the chain verification.
An invoice here is a tax document issued under ZATCA's e-invoicing rules: a tax invoice, a credit note or a debit note. It starts as a draft you can edit or delete freely, then it is issued: it gets its sequential number, its cryptographic stamp and its QR code, and goes to ZATCA. After that it cannot be changed; a correction is a credit or debit note that references it. The feature is explained in full in E-Invoices (ZATCA).
zatca_status stays none. The unit is set up once in the app, under Settings → ZATCA. The feature stops at the document: there are no payments, due dates or receivables here, and your accounting software takes the issued invoice from here as PDF or XML.| Tool | What it does |
|---|---|
| invoices_list | List invoices |
| invoices_get | Get an invoice |
| invoices_create | Create an invoice draft |
| invoices_update | Update an invoice draft |
| invoices_delete | Delete an invoice draft |
| invoices_issue | Issue an invoice |
| invoices_submit | Send an invoice to ZATCA again |
| invoice_pdf | Download the invoice PDF |
| invoice_xml | Download the invoice XML |
| invoice_archive_zip | Download the invoice XML archive |
| invoice_events_list | List the invoice activity log |
| zatca_chain_verify | Verify the invoice chain and activity log |
Finding and reading invoices
invoices_list
Lists your organization's invoices, credit notes and debit notes, newest first. Filter by stage, ZATCA outcome, document or kind, the sales order they bill or the invoice a note corrects, or search by free text.
Read-only · scope invoices.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Only drafts (draft) or only issued documents (issued). |
zatca_status | string | No | Only documents with this ZATCA outcome: none (no outcome yet: a draft, or an invoice issued without a live unit), pending (ZATCA could not be reached), cleared, reported or rejected. |
document_type | string | No | The document: invoice for a tax invoice, credit_note or debit_note. |
transaction_type | string | No | The kind: standard for B2B or simplified for B2C. |
sales_order_id | integer | No | Only documents that bill this sales order. The ID comes from sales_orders_list. |
original_invoice_id | integer | No | Only the credit and debit notes that correct this invoice. |
q | string | No | A word or number to look for in the invoice number, the customer name and the buyer's VAT number, up to 200 characters. |
page | integer | No | Page number, starting at 1. |
page_size | integer | No | Results per page: 20 by default, 100 at most. |
{
"status": "issued",
"zatca_status": "rejected",
"page_size": 50
}Returns: A page of invoices, each with its number, UUID, kind, stage, ZATCA outcome, buyer, totals and the sales order and tender it is linked to, and the total count.
- Drafts also carry
zatca_statusnone. Addstatus: issuedto find only the invoices issued without a live unit.
invoices_get
Returns one invoice in full: header, lines, buyer, totals, ZATCA's outcome and messages and the QR code, with the sales order, quotation and tender it is linked to and the notes that correct it. For a draft it also lists what is still missing before it can be issued.
Read-only · scope invoices.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The invoice's ID, from invoices_list. |
Returns: An object with invoice, items, readiness_issues, qr_image (a PNG data URI, empty for a draft), sales_order, quotation, tender, original_invoice, corrections (the notes that correct it), egs (the unit's environment and status) and events (the invoice's 50 most recent activity rows).
readiness_issuesis a list of codes for what a draft lacks, and it is empty once issued. Codes starting withseller_belong to the organization record in settings and cannot be fixed on the invoice. The other codes name a missing buyer, line or note field, such asbuyer_identity,supply_date,original_invoiceandline_exemption_reason.- ZATCA's messages on a rejection are in
invoice.zatca_errorandinvoice.zatca_response. The signed and the cleared XML are not in this reply; download them with invoice_xml.
Drafts
A draft has no number, hash or XML. Save it half-filled if you like: nothing is checked against ZATCA's requirements until you issue, and invoices_get shows what is missing.
invoices_create
Saves a tax invoice, credit note or debit note as a draft with at least one line. Nothing is numbered, signed or sent until you issue it. Name a customer profile to fill the buyer's name, identifier and address, and send any field you want to win over the profile.
Changes data · scope invoices.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
customer_id | integer | No | A customer profile to start from, from customers_list. Every buyer field you leave out is filled from it according to the customer's tax treatment, and anything you send wins over the profile. Send null to use none. |
customer_name | string | No | The buyer's name as printed, 1 to 200 characters. Required unless customer_id is given; if you send both, this name is used. |
document_type | string | No | The document: invoice for a tax invoice (the default), credit_note or debit_note. |
transaction_type | string | No | The kind: standard is a B2B invoice that ZATCA clears before the buyer receives it (the default), simplified is a B2C invoice that is reported. A note whose original invoice you name takes that invoice's kind when you send none. |
original_invoice_id | integer | No | For a credit or debit note: the issued tax invoice it corrects. It is required to issue the note and may be left empty while it is a draft. It must be an issued tax invoice of your organization, not a draft and not another note. Ignored for invoice. Send null to clear it. |
reason | string | No | For a credit or debit note: why it is issued, up to 500 characters. Required to issue the note. Send null to clear it. |
buyer_vat_number | string | No | The buyer's Saudi VAT number: 15 digits starting and ending with 3. A malformed number blocks issue. Send null to clear it. |
buyer_id_scheme | string | No | The kind of the buyer's other identifier, for a buyer with no VAT number: CRN commercial registration, MOM municipal licence (MOMRA), MLS HR ministry licence (MHRSD), 700 the unified 700 number, SAG investment licence (MISA), NAT national ID, GCC GCC citizen ID, IQA iqama, PAS passport, OTH other. Send it with buyer_id_value. Send null to clear it. |
buyer_id_value | string | No | The value of the other identifier, such as the commercial registration number, up to 50 characters. A standard invoice to a buyer with no VAT number needs it together with buyer_id_scheme. Send null to clear it. |
buyer_street_name | string | No | The street of the buyer's national address, up to 200 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_building_number | string | No | The building number, up to 10 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_district | string | No | The district, up to 100 characters. Send null to clear it. |
buyer_city | string | No | The city, up to 100 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_postal_code | string | No | The postal code, up to 10 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_additional_number | string | No | The additional number of the national address, up to 10 characters. Send null to clear it. |
buyer_country_code | string | No | The buyer's two-letter country code (ISO 3166-1). Defaults to SA. |
sales_order_id | integer | No | The sales order the invoice bills, from sales_orders_list. It must be one of your organization's orders. Send null to unlink. |
quotation_id | integer | No | The quotation the sale came from, from quotations_list. It must be one of your organization's quotations. Send null to unlink. |
tender_id | integer | No | The tender the sale relates to, for reference, from tenders_list. Send null to unlink. |
currency | string | No | The three-letter currency code (ISO 4217). Defaults to SAR. |
supply_date | string | No | The date of supply, as YYYY-MM-DD. A standard invoice needs it to be issued. Send null to clear it. |
payment_means_code | string | No | How the buyer pays, as a UNTDID 4461 code: 10 cash, 30 credit transfer (the default), 42 bank account, 48 card, 1 unspecified. It is printed on the document and does not record a payment. |
notes | string | No | Free-form notes on the invoice, up to 2,000 characters. Send null to clear them. |
items | object[] | Yes | The invoice lines, from 1 to 500. Each line's fields are described below as items[].…. |
items[].product_id | integer | No | The catalog product this line is for, from products_list. It must be one of your organization's products. |
items[].sales_order_item_id | integer | No | The sales order line this invoice line bills. |
items[].description | string | Yes | What is invoiced, 1 to 1,000 characters. |
items[].quantity | number | Yes | The quantity, above 0. |
items[].unit_code | string | No | The unit of measure as a UN/ECE Recommendation 20 code, up to 10 characters. Defaults to PCE (piece); others include BX (box), PK (pack) and KGM (kilogram). |
items[].unit_price | number | Yes | The price per unit before VAT, in the invoice's currency, 0 or more, with up to four decimals. |
items[].discount_amount | number | No | A discount as an amount, not a percentage, taken off this line, 0 or more. Anything above the line's gross amount is cut off. |
items[].vat_category | string | No | The VAT category: S standard-rated (the default), Z zero-rated, E exempt or O out of scope. |
items[].vat_rate | number | No | The VAT rate as a whole percent, 0 to 100. Defaults to 15 for S and 0 for the other categories. To issue, an S line needs a rate above 0 and a Z, E or O line needs 0. |
items[].vat_exemption_code | string | No | ZATCA's exemption reason code for a Z, E or O line, up to 30 characters, for example VATEX-SA-35 for medicines and medical equipment. It is required to issue such a line and ignored on an S line. Send null to clear it. |
items[].vat_exemption_reason | string | No | The exemption reason as text, up to 500 characters. If you leave it out, it is filled from the code when the code is on ZATCA's list. Send null to clear it. |
{
"customer_id": 214,
"transaction_type": "standard",
"sales_order_id": 87,
"supply_date": "2026-10-04",
"payment_means_code": "30",
"items": [
{
"description": "Disposable syringe 5 ml, box of 100",
"quantity": 40,
"unit_code": "BX",
"unit_price": 38.5,
"vat_category": "Z",
"vat_exemption_code": "VATEX-SA-35"
},
{
"description": "Delivery to Riyadh warehouse",
"quantity": 1,
"unit_price": 150
}
]
}Returns: The new draft's ID as invoice_id. Read it back with invoices_get.
- Totals are calculated per line and rounded to the cent: the net is quantity times unit price minus the discount, VAT is applied at the line's rate, and the invoice totals are the sums of its lines.
- A standard invoice needs the buyer's VAT number or another identifier, a street, building number, city and postal code, and a supply date before it can be issued. A simplified invoice needs only the customer name. A zero-rated medical line takes category
ZwithVATEX-SA-35. - A customer, sales order, quotation, product or original invoice that is not found in your organization, or a tender you cannot see, answers 404. A note whose original is not an issued tax invoice answers 400.
invoices_update
Changes a draft. Only the fields you send change, null clears a field that can be empty, and items, when sent, replaces all the lines. An issued invoice cannot be changed: issue a credit or debit note that references it instead.
Changes data · scope invoices.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The invoice's ID, from invoices_list. |
customer_id | integer | No | The customer profile the document is linked to, from customers_list. It does not refill the buyer fields, so send the ones you want changed. Send null to unlink. |
customer_name | string | No | The buyer's name, 1 to 200 characters. |
document_type | string | No | The document: invoice, credit_note or debit_note. Switching back to invoice clears the original invoice and the reason. |
transaction_type | string | No | The kind: standard for B2B or simplified for B2C. |
original_invoice_id | integer | No | For a credit or debit note: the issued tax invoice it corrects. It is required to issue the note and may be left empty while it is a draft. It must be an issued tax invoice of your organization, not a draft and not another note. Ignored for invoice. Send null to clear it. |
reason | string | No | For a credit or debit note: why it is issued, up to 500 characters. Required to issue the note. Send null to clear it. |
buyer_vat_number | string | No | The buyer's Saudi VAT number: 15 digits starting and ending with 3. A malformed number blocks issue. Send null to clear it. |
buyer_id_scheme | string | No | The kind of the buyer's other identifier, for a buyer with no VAT number: CRN commercial registration, MOM municipal licence (MOMRA), MLS HR ministry licence (MHRSD), 700 the unified 700 number, SAG investment licence (MISA), NAT national ID, GCC GCC citizen ID, IQA iqama, PAS passport, OTH other. Send it with buyer_id_value. Send null to clear it. |
buyer_id_value | string | No | The value of the other identifier, such as the commercial registration number, up to 50 characters. A standard invoice to a buyer with no VAT number needs it together with buyer_id_scheme. Send null to clear it. |
buyer_street_name | string | No | The street of the buyer's national address, up to 200 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_building_number | string | No | The building number, up to 10 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_district | string | No | The district, up to 100 characters. Send null to clear it. |
buyer_city | string | No | The city, up to 100 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_postal_code | string | No | The postal code, up to 10 characters. A standard invoice needs it to be issued. Send null to clear it. |
buyer_additional_number | string | No | The additional number of the national address, up to 10 characters. Send null to clear it. |
buyer_country_code | string | No | The buyer's two-letter country code (ISO 3166-1). Defaults to SA. |
sales_order_id | integer | No | The sales order the invoice bills, from sales_orders_list. It must be one of your organization's orders. Send null to unlink. |
quotation_id | integer | No | The quotation the sale came from, from quotations_list. It must be one of your organization's quotations. Send null to unlink. |
tender_id | integer | No | The tender the sale relates to, for reference, from tenders_list. Send null to unlink. |
currency | string | No | The three-letter currency code (ISO 4217). Defaults to SAR. |
supply_date | string | No | The date of supply, as YYYY-MM-DD. A standard invoice needs it to be issued. Send null to clear it. |
payment_means_code | string | No | How the buyer pays, as a UNTDID 4461 code: 10 cash, 30 credit transfer (the default), 42 bank account, 48 card, 1 unspecified. It is printed on the document and does not record a payment. |
notes | string | No | Free-form notes on the invoice, up to 2,000 characters. Send null to clear them. |
items | object[] | No | When sent, this list replaces all the current lines (1 to 500) and the totals are recalculated. Leave it out to keep the lines as they are. |
items[].product_id | integer | No | The catalog product this line is for, from products_list. It must be one of your organization's products. |
items[].sales_order_item_id | integer | No | The sales order line this invoice line bills. |
items[].description | string | Yes | What is invoiced, 1 to 1,000 characters. |
items[].quantity | number | Yes | The quantity, above 0. |
items[].unit_code | string | No | The unit of measure as a UN/ECE Recommendation 20 code, up to 10 characters. Defaults to PCE (piece); others include BX (box), PK (pack) and KGM (kilogram). |
items[].unit_price | number | Yes | The price per unit before VAT, in the invoice's currency, 0 or more, with up to four decimals. |
items[].discount_amount | number | No | A discount as an amount, not a percentage, taken off this line, 0 or more. Anything above the line's gross amount is cut off. |
items[].vat_category | string | No | The VAT category: S standard-rated (the default), Z zero-rated, E exempt or O out of scope. |
items[].vat_rate | number | No | The VAT rate as a whole percent, 0 to 100. Defaults to 15 for S and 0 for the other categories. To issue, an S line needs a rate above 0 and a Z, E or O line needs 0. |
items[].vat_exemption_code | string | No | ZATCA's exemption reason code for a Z, E or O line, up to 30 characters, for example VATEX-SA-35 for medicines and medical equipment. It is required to issue such a line and ignored on an S line. Send null to clear it. |
items[].vat_exemption_reason | string | No | The exemption reason as text, up to 500 characters. If you leave it out, it is filled from the code when the code is on ZATCA's list. Send null to clear it. |
{
"id": 311,
"supply_date": "2026-10-05",
"buyer_vat_number": "300012345600003"
}Returns: The draft's ID as invoice_id.
- An issued invoice answers 409 whatever you send, and an invoice that is not in your organization answers 404.
- Sending
itemsdeletes the current lines and puts the new ones in their place, so send the whole list, not only the lines that changed.
invoices_delete
Deletes a draft. An issued invoice is a tax record and cannot be deleted. The deletion stays in the activity log.
Deletes or overwrites data · scope invoices.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The invoice's ID, from invoices_list. |
Returns: A confirmation (ok: true).
- An issued invoice answers 409. Correct an issued invoice with a credit or debit note.
Issuing and sending to ZATCA
Issuing is the one step that cannot be undone, and only an admin or the owner may take it.
invoices_issue
Issues a draft: it assigns the sequential number and the issue date and time (Riyadh), builds and stamps the invoice XML, adds the QR code, freezes the document and sends it to ZATCA, for clearance if it is a standard invoice or reporting if it is a simplified one. This cannot be undone.
Changes data · scope invoices.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The invoice's ID, from invoices_list. |
Returns: invoice_id, invoice_number, signed (false when issued without a live unit), zatca_status (cleared, reported, rejected, pending or none), zatca_has_warnings and zatca_error (ZATCA's messages on a rejection).
- A draft that lacks something ZATCA requires answers 400 with
issues, a list of field codes, and stays a draft with no number used. Readreadiness_issuesfrominvoices_getbefore issuing. - With no live e-invoicing unit the invoice is still issued, with a five-field QR code and
zatca_statusnone, and it can never be sent to ZATCA afterwards. Set the unit up first if the invoice must reach ZATCA. pendingmeans ZATCA could not be reached: the invoice is issued and stamped, and invoices_submit sends the same file again. Arejectedinvoice keeps its number, and if the cause was on the unit's side and is fixed, it can be sent again.- Answers 409 when the invoice is already issued, and when another invoice of your organization is being issued at that moment (try again shortly).
invoices_submit
Sends an issued invoice to ZATCA again with the same stored, stamped file, so its hash does not change. Use it for an invoice left pending by an outage, or rejected for a reason on the unit's side that has since been fixed.
Changes data · scope invoices.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The invoice's ID, from invoices_list. |
Returns: invoice_id, invoice_number, signed, zatca_status, zatca_has_warnings and zatca_error, as in invoices_issue.
- Answers 409 for a draft, for an invoice issued without a live unit (it carries no stamp), for an invoice ZATCA has already accepted (
clearedorreported), and when the unit that stamped it is no longer live.
Files and the archive
invoice_pdf
Prints the invoice as a PDF in Arabic with English, with its QR code and VAT breakdown. A draft prints as a watermarked preview without a QR code.
Read-only · scope invoices.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The invoice's ID, from invoices_list. |
Returns: A PDF file with filename, content_type, size_bytes and the content as base64 in base64.
- A file over 4 MB is not embedded in the reply; the tool answers with an error that names the REST endpoint to download it from. Every download is recorded in the activity log.
invoice_xml
Returns an issued invoice's signed XML, the very file ZATCA received (UBL 2.1). With cleared: true it returns the copy ZATCA stamped at clearance instead.
Read-only · scope invoices.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The invoice's ID, from invoices_list. |
cleared | boolean | No | Set true for the copy ZATCA stamped at clearance instead of the submitted one. Only a cleared standard invoice has one. Defaults to false. |
Returns: An XML file with filename, content_type, size_bytes and the content as base64 in base64.
- A draft has no XML and answers 404, and so does
cleared: truefor an invoice ZATCA returned no cleared copy of. Every download is recorded in the activity log.
invoice_archive_zip
Packs the signed XML of every issued invoice, credit note and debit note into one ZIP, for your archive or an auditor. Files are named the way ZATCA asks you to keep them, and a manifest.json lists what is inside.
Read-only · scope invoices.read · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | No | The first issue date to include, as YYYY-MM-DD. |
to | string | No | The last issue date to include, as YYYY-MM-DD, inclusive. It must not be before from. |
Returns: A ZIP file with filename, content_type, size_bytes and the content as base64 in base64. Each document is a file named <VAT number>_<issue date>T<issue time>_<invoice number>.xml, with ZATCA's stamped copy beside it as .cleared.xml where held, plus manifest.json with numbers, UUIDs, counters and hashes.
- A window with more than 5,000 documents answers 413: narrow it with
fromandto. A window with no issued invoices answers 404. - An archive over 4 MB is not embedded in the reply; the tool answers with an error that names the REST endpoint to download it from. Every export is recorded in the activity log.
Activity log and verification
The platform writes the activity log itself and nobody can edit or delete a row, each row being chained to the previous one by hash. A verification tool checks the records as a whole.
invoice_events_list
Lists the e-invoicing activity log, newest first: every draft created, edited or deleted, each issue and submission to ZATCA, each PDF, XML and archive download, each verification and every step in the unit's life. Each row says who did it and through which channel.
Read-only · scope invoices.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
invoice_id | integer | No | Only the rows about this invoice. |
event | string | No | Only this event, one of invoice.created, invoice.updated, invoice.deleted, invoice.issued, invoice.submitted, invoice.pdf_downloaded, invoice.xml_downloaded, invoices.archived, chain.verified, unit.created, unit.compliance_csid, unit.compliance_checks, unit.production_csid, unit.renewed or unit.reset. |
scope | string | No | all for everything (the default), invoice for rows about a document, or unit for rows about the unit, archive exports and verifications. |
from | string | No | The start of the period, inclusive, as an ISO date or timestamp. A date alone means the start of that day (UTC). |
to | string | No | The end of the period, exclusive, as an ISO date or timestamp. |
page | integer | No | Page number, starting at 1. |
page_size | integer | No | Rows per page: 50 by default, 100 at most. |
{
"scope": "invoice",
"event": "invoice.issued",
"from": "2026-10-01",
"page_size": 25
}Returns: A page of rows, each with id, invoice_id, invoice_number, event, actor_email, channel (app, api or system), detail, created_at, prev_hash and entry_hash, and the total count.
- The channel
appis the web app,apiis any call through the API, MCP or the assistants on a member's behalf, andsystemis the platform acting on its own. - A row without an
invoice_idis about the unit, an archive export or a verification.
zatca_chain_verify
Proves the e-invoicing records intact. It re-hashes every issued document from its stored XML and checks each stamp against the certificate inside the file, each invoice's link to the previous one and the counter sequence, the unit's counter and last hash, and the activity log's own chain. It changes nothing except adding one chain.verified row to the log. Run it before an audit.
Read-only · scope settings.write · roles: owner · Pro and Enterprise plans
No parameters.
Returns: An object with ok, checked_at, invoices (documents examined), chains (one per unit that stamped documents, each with ok, issues, last_hash and highest_icv), phase1 (documents issued without a unit), unit (the counter and last-hash checks) and log (the activity log's chain).
- Each problem in
issuesnames the invoice and a code for what does not hold:hash_mismatch,signature_invalid,signature_missing,pih_mismatch,icv_gap,icv_duplicate,xml_row_mismatch,xml_missingorcertificate_unreadable. - It needs the write scope
settings.writealthough none of your invoice data changes, because the run is recorded in the activity log.