Error Handling
The client converts transport and non-success HTTP responses into typed exceptions before returning a Response.
Exception hierarchy
Exception
└── ZatcaException
└── ZatcaApiException
├── ZatcaValidationException // HTTP 422
└── ZatcaDomainUnauthorizedException // domain-related HTTP 403
Complete handling pattern
use ZatcaX\SDK\Exceptions\ZatcaApiException;
use ZatcaX\SDK\Exceptions\ZatcaDomainUnauthorizedException;
use ZatcaX\SDK\Exceptions\ZatcaValidationException;
try {
$response = Zatca::invoice()->submit($invoice);
$data = $response->getData();
} catch (ZatcaDomainUnauthorizedException $e) {
// Fix the configured domain or its allowlist. Do not retry unchanged.
logger()->warning($e->getMessage());
} catch (ZatcaValidationException $e) {
// Map field-level errors back to the source record.
$errors = $e->getErrors();
} catch (ZatcaApiException $e) {
// Includes cURL failures and all other HTTP 4xx/5xx responses.
logger()->error('ZatcaX request failed', [
'status' => $e->getStatusCode(),
'response' => $e->getResponseBody(),
]);
}
Behavior by failure type
| Condition | Exception | Recommended action |
|---|---|---|
| cURL, DNS, timeout, or TLS failure | ZatcaApiException (status 400) | Retry with bounded backoff after checking network and TLS. |
| Domain-related HTTP 403 | ZatcaDomainUnauthorizedException | Correct ZATCAX_CLIENT_DOMAIN or the dashboard allowlist. |
| HTTP 422 | ZatcaValidationException | Read getErrors(), correct the payload, then resubmit. |
| Other HTTP 4xx | ZatcaApiException | Correct credentials or request; do not blindly retry. |
| HTTP 5xx | ZatcaApiException | Log a correlation identifier and retry using backoff. |
Response inspection
Successful HTTP calls return Response. Use dot notation for nested values:
$requestId = $response->json('data.request_id');
$message = $response->getMessage();
$status = $response->getStatusCode();
$all = $response->toArray();
Retry and idempotency guidance
- Persist the generated invoice UUID before the first submission and reuse it for a retry.
- A reported invoice is final and the server rejects attempts to modify it.
- A rejected invoice can be corrected and resubmitted with the same UUID.
- Never regenerate the invoice UUID merely because the network response was lost.
- Log response status and safe identifiers, but never the secret, private key, authorization token, or OTP.