ZatcaX

Frequently Asked Questions

Answers based on the current SDK implementation.

Does the SDK require Laravel?+
No. The package has no runtime dependency on Laravel. Use ZatcaClient and Config in plain PHP, or use auto-discovery, dependency injection, and the Facade in Laravel.
Which PHP versions are supported?+
The package declares PHP 8.1, 8.2, and 8.3 support. The cURL extension is required by ZatcaClient.
Where do I get the client ID, secret, and owner UUID?+
The platform owner creates an SDK client in the owner dashboard. The client portal also displays the integration values after authentication.
Is the portal password the same as the API secret?+
No. The portal password authenticates the human user. The API secret signs server-to-server requests and must never be used in a browser.
Standard or simplified invoice?+
Use standard() for B2B tax invoices that require clearance, and simplified() for B2C invoices that are reported.
How is taxable_amount calculated?+
When taxableAmount() was not set to a positive value, InvoiceBuilder sums quantity × unit_price − discount for every item and rounds to two decimals.
Does InvoiceBuilder generate UUIDs?+
Yes. A UUID v4 and the current issue timestamp are generated in the constructor. You can override both with uuid() and issueAt().
Where does previous_hash come from?+
Read data.invoice_hash from the response returned for the immediately preceding generated document, then persist it as the chain head for that owner UUID. Only the first document uses the seed initialized by InvoiceBuilder.
Where should I store the previous invoice hash?+
Use a durable database row per EGS unit or owner UUID and retain the hash on each invoice record for audit. Never rely only on .env, sessions, process memory, or expiring cache. Serialize submissions so two documents cannot consume the same chain head.
What is the difference between a credit note and a debit note?+
A credit note reduces or cancels an amount from an original invoice; a debit note adds an amount that was omitted or undercharged. Both are new immutable documents with their own IDs and UUIDs, must reference the original invoice with billingReferenceId(), and must use the latest chain hash.
Can I import a certificate from another accounting system?+
Yes. importCertificate() accepts the certificate, private key, authorization token, optional secret, environment, and optional organization metadata.
How do I renew a certificate?+
Generate a fresh six-digit OTP in Fatoora, then call renewCertificate($ownerUuid, $otp). A completed certificate must already exist.
What invoice statuses should my application store?+
The server uses pending while processing, reported after successful reporting or clearance, and rejected after a failed ZATCA submission.
How do I get PDF and QR outputs?+
Call getPdfUrl($invoiceUuid) and getQrCodeUrl($invoiceUuid). These methods construct URLs; they do not download the files.
Can I pass arrays instead of builders?+
Yes. ComplianceResource::credence() and InvoiceResource::submit() accept builders or arrays. The array must match the builder toArray() structure.
Should SSL verification ever be disabled?+
Only in a controlled local environment with a self-signed certificate. It must remain enabled in production.
How should I handle timeouts?+
Keep the same invoice UUID, check whether the request was processed, and retry with bounded backoff. Do not create duplicate invoice identities after an ambiguous response.