Actions and results
What each E-invoicing button and automatic behaviour does, with worked numbers and what the system refuses.
On this page (21)
DashboardSettingsOnboardingAlertsProvidersCountry profilesRetry and outage policiesCode mappingsPartner endpointsRetention policiesSubmissionsProvider outagesInvoicesE-invoice smart buttonReceived e-invoicesSubmission monitor (R040)Reject analysisInvoice-to-provider bridgeArchive integrityEvent logFeature switches
Dashboard
| Action | When | What you do | What happens |
|---|---|---|---|
| Start with the sandbox | Company with e-invoicing off (banner 'E-invoicing is switched off for this company.' visible); user has configure + secret | Open Dashboard; press 'Start with the sandbox'; then open Configuration > Onboarding and Credentials; press the button again from the API or reopen | E-invoicing flips on, banner disappears; an Active Test onboarding with SANDBOX exists with two credentials (callback secret and signing key, both Active, signing certificate self-signed); the four profiles (AE B2B, AE B2C, SA standard, SA simplified) are Active in Test; pressing again creates no second onboarding or duplicate credentials |
| Dashboard tiles agree with the list | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; a mix of pending, queued, submitted, accepted, rejected, unknown, blocked submissions | Compare each tile with the Submissions tab counts; click a recent row | Waiting to send = Pending + Queued; Awaiting answer = Submitted; Status unknown; Accepted; Rejected with open issues count; Pending clearance (legal state, not superseded); at risk; credentials expiring within the alert days; 'Accepted - last 14 days' bars sum to accepted in the window; superseded is not charted |
Settings
| Action | When | What you do | What happens |
|---|---|---|---|
| Save settings and detect an edit conflict | Settings open in two browser tabs (same revision) | Tab 1: change 'Warn before a credential expires' from 30 to 45, Save. Tab 2 (stale): change Submit automatically, Save | Tab 1 shows 'Saved.'. Tab 2 is refused with 'This record changed since you opened it. Reload it and try again.' (409) and nothing of tab 2 is stored |
| Master switch off stops hand-over | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; one draft invoice ready | Turn 'E-invoicing is on' off and Save; post the invoice; check Submissions; turn it on again and post another | While off: no submission is created for the posted invoice, smart button absent, scheduler ignores the company. After switching on the next posted invoice gets a submission (the first one does NOT appear retroactively) |
Onboarding
| Action | When | What you do | What happens |
|---|---|---|---|
| Test onboarding: draft to active in two clicks | Active SANDBOX provider; user with configure | New onboarding: provider SANDBOX, environment Test, registration = company TRN; Save; open it; press Start testing; press Request activation | State goes Draft > Testing > Active with no second person (a test onboarding cannot send a legal document). Actions: Edit is no longer offered once Active; audit lines 'einvoicing.onboarding.start_testing' and '.request_activation' |
| Edit is refused while active | An Active onboarding | Open it; look for Edit; try PUT through the API | No Edit button; API: 'An active onboarding is not edited; suspend it first.' After Suspend the Edit button returns |
| Production onboarding needs another person and every gate | A production provider (kind ZATCA or UAE ASP) Active, a production profile, onboarding created by user A in Production and requested for activation | As user B (approver, not A) press Approve with: no evidence; evidence but no certified profile; a certified profile that never ran conformance; no auth credential; a self-signed signing key. Fix one gate at a time | Each refusal names its gate: 'Blocked pending the authority's or provider's acceptance evidence.', 'Blocked pending a certified production profile that passed its conformance run.', 'Bind an active production authentication credential.', 'Bind an active production signing key.', 'A production signing key needs the authority's certificate, not a self-signed one.'. As user A pressing Approve: 'Somebody other than the person who prepared this onboarding must approve it.' Only when every gate passes does it become Active |
| Sandbox provider can never go to production | Onboarding in Production environment pointing at the SANDBOX provider is attempted | Create onboarding with provider SANDBOX, environment Production; separately make a provider of kind Sandbox with environment Production | Onboarding: 'The onboarding's environment is the provider's.'. Provider: 'The sandbox provider is only ever a test environment.'. A worker never sends to production through the sandbox: 'The sandbox provider is never used for production.' |
| Suspend, reinstate and retire | An Active test onboarding; approver user other than the requester | Suspend with reason 'Provider maintenance'; look at the banner; as approver (not the requester) Reinstate; then Retire | Suspended shows the reason in a banner and sending stops ('The company has no active test onboarding with SANDBOX.' alert 'not_ready'). Reinstate refused for the requester, allowed for another approver. Retire is final (no actions left except none) |
| Bind a test credential (auto-active) | Active test onboarding; user with secret | Bind credential: Purpose Authentication, secret 'test-token-0001', Valid to 2027-03-31; then Purpose Signing key with Generate on; then Purpose Callback secret with Generate on | Each credential shows Active at once (test environment), reference 'vault:xxxxxx…', no secret anywhere in the screen, the signing one has a thumbprint and a certificate valid for 365 days; second credential of the same purpose marks the older one 'Rotated' |
| Production credential needs a second person | Production onboarding; user A (secret) and user B (activate) | As A bind an auth credential on the production onboarding; look at its state; as A press Approve; as B press Approve | Credential starts 'Awaiting approval'; A is refused with 'Somebody other than the person who prepared this credential must approve it.'; B approves (needs einvoicing.activate) and it becomes Active; an old credential of the same purpose becomes Rotated |
| Credential health check | Active credentials of a test onboarding | In the onboarding dialog press Check on the signing credential; on an expired one; on a rotated one | Active sandbox credential: health 'ok - The sandbox answers.'. Expired: 'expired - The credential has expired.'. Not active: 'inactive - The credential is rotated.' Last health time is stamped |
| Report a credential compromised | Active signing credential; one submission Submitted or Status unknown | Press Compromised and type 'Laptop stolen' | Credential state Compromised and its vault secret destroyed (unreadable); the onboarding is Suspended with reason 'Credential <thumbprint> reported compromised: Laptop stolen'; unsent signed documents will be re-signed after a new key; uncertain sends are queried first; red alert 'A signing credential was reported compromised; sending is suspended and N documents will be reconciled.' |
| Rotate a signing key (T013) | KSA company on the sandbox with: one invoice accepted, one pending unsent (auto submit off), one Status unknown | Bind a new signing key (Generate on) to the same onboarding; check the old key; open the unsent and unknown submissions | New key Active, old key Rotated. The Status-unknown invoice is queried FIRST (questions before sends); the unsent invoice is re-signed with the new key keeping the same counter (ICV) and previous hash, so its invoice hash is unchanged; nothing is sent twice |
| ZATCA compliance CSID by API [Blocked if no sandbox] | Blocked if no sandbox: needs a real authority / provider sandbox account and credentials. ZATCA developer-portal provider (https, allowlisted host), KSA onboarding with the 15-digit VAT, OTP from the Fatoora portal | As custodian call POST onboarding/<id>/request_compliance_csid with {otp: '123456'}; read the onboarding | A new signing key and CSR are made, ZATCA answers a compliance CSID: signing and auth credentials bound, solution unit serial and request id stored, evidence line 'Compliance CSID <id> issued <time> UTC.' appended. Without OTP: 'Enter the one-time password from the Fatoora portal.'; VAT not 15 digits: 'The VAT number must be the 15 digits ZATCA registered.'; non-ZATCA provider: 'Only a ZATCA onboarding asks ZATCA for a CSID.' |
| ZATCA production CSID [Blocked if no sandbox] | Blocked if no sandbox: needs a real authority / provider sandbox account and credentials. Compliance CSID obtained and compliance invoices passed | Call request_production_csid | Without a compliance CSID: 'Request the compliance CSID first.'. With it: production certificate must belong to the same key ('ZATCA's production certificate is not for this unit's key.' otherwise); new signing and auth credentials bound; production evidence line 'Production CSID <id> issued...' |
Alerts
| Action | When | What you do | What happens |
|---|---|---|---|
| Credential expiry scan | Credential with Valid to 20 days from today (alert window 30); another with Valid to yesterday | Wait for the daily scan (or run the scheduler tick); open Alerts and Credential health | 20-day credential: alert 'A <purpose> credential expires on <date>; rotate it before then.'; yesterday's: state Expired and red alert 'A <purpose> credential expired on <date>; nothing is sent with it.'. Credential health report shows Days left (20) and counts it in 'expiring_30_days' |
| Escalation and deadline arithmetic | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; simplified (B2C) invoice with policy deadline 24 h and escalation 6 h; a standard invoice stuck Pending clearance with escalation 2 h | Create the simplified invoice with the provider unavailable; read Deadline; wait or use a back-dated test company clock; read Alerts, the Unknown and deadline queue and the dashboard tile 'Deadline at risk' | Deadline = creation + 24 h. Dashboard 'at risk' counts items whose deadline is within 6 hours. The alert 'must reach the authority by <date time> UTC' is raised once when deadline - 6 h (18 h after creation) has passed, and 'is past its deadline' after 24 h; the standard invoice raises 'is still not cleared, so it has not been issued' after 2 h; a Status-unknown item raises 'has had no confirmed status for too long' after the policy hours (UAE 4 h). Each only once per submission (escalated_at); alert times are shown in UTC in the text |
| Acknowledge and one alert per subject per day | Several alerts; user with operate | Acknowledge one; switch tab to All; cause the same rejection kind twice on the same submission on one day | Acknowledged alerts leave 'To acknowledge' and show 'Acknowledged' in All; the dashboard list excludes them; a second alert of the same kind for the same submission on the same company day is not created |
Providers
| Action | When | What you do | What happens |
|---|---|---|---|
| Create, review and activate a provider with two people | Users A (configure) and B (activate) | A: New provider code 'ASP1', kind UAE accredited service provider, Production, base URL https://api.asp.example.ae, allowed host api.asp.example.ae, Authentication Bearer; Save. A: look for Review. B: Review, then Activate | Starts Draft. A is not offered Review/Activate (author). B reviews (Reviewed) then activates (Active). B cannot activate a record B edited last. Any edit by A sends it back to Draft. A production provider needs a base URL and allowlist: sandbox kind refused ('The sandbox provider is never used for production.') |
| Provider address safety | New provider form | Try base URLs: http://api.x.ae; https://localhost/a; https://10.0.0.5/a; https://api.x.ae:8443; https://user:pw@api.x.ae; a host not in the allowlist; allowed host entries 'localhost', 'https://x.com', '192.168.1.5' | Refused with: 'A provider address must use HTTPS.'; 'That address points at this machine or an internal network.' (x2); 'Providers are reached on the standard HTTPS port.'; 'Credentials do not belong in the address; add them as a credential.'; 'The provider's address must be on its reviewed allowlist.'; allowlist entries 'localhost cannot be a provider host.', 'https://x.com cannot be a provider host.', '192.168.1.5 is not a public address.' |
| Sandbox behaviour switch | Active SANDBOX provider; user with configure | Open SANDBOX; press Sandbox behaviour; type 'reject'; post an invoice; repeat with 'timeout_after_accept', 'unavailable', 'async', then 'accept'; try 'foo' | Next sends follow the chosen mode (rejected with SIM-ADDR-001; accepted then timeout; unavailable; submitted/pending; accepted). 'foo' -> 'Choose one of: accept, reject, timeout_after_accept, unavailable, async.' Behaviour changes do not need review or a second person |
Country profiles
| Action | When | What you do | What happens |
|---|---|---|---|
| New version of a used profile | AE-PINT-B2B v1 Active and used by at least one submission; users A (configure) and B (activate) | Try Edit on v1; press New version as A; change Priority nothing else; B: Review and Activate v2 | v1 has no Edit ('Submissions use this profile version; make a new version instead.' via API). v2 is a Draft copy (version 2, certified off, evidence cleared). Activating v2 archives v1; later invoices use v2, earlier submissions keep showing v1 |
| Two profiles cannot overlap | AE-PINT-B2B v1 Active (priority 10) | Create a new profile code AE-PINT-X: UAE, Business, Invoice + Credit note, same dates, priority 10; review (B) and activate (B) | Activation refused: 'AE-PINT-B2B v1 already covers these documents and dates at the same priority.' With priority 5 or non-overlapping dates it activates |
| Run conformance (local fixtures) | Any profile; user with configure | Open SA-ZATCA-STD v1; press Run conformance; open the Conformance card; repeat for AE-PINT-B2B | Card shows 'passed' with one line per check and per fixture (invoice and credit note): profile rules, payload builds, required elements, totals carried exactly (payable 115.00 KSA / 105.00 UAE), and for ZATCA invoice hash recomputes, signature verifies, QR carries hash and signature. Result is stored against that exact version |
| Production profile activation gate | Production profile (Draft->Reviewed), production provider Active; approver B | B presses Activate with: certified off; certified with evidence 'ok'; evidence ok but no conformance run; conformance failed | Refused each time with: 'A production profile needs the authority's or provider's acceptance evidence.' or 'Run the conformance fixtures for this version first.'; passes only with Certified + evidence of 10+ characters + a passed conformance run for this version |
Retry and outage policies
| Action | When | What you do | What happens |
|---|---|---|---|
| Offline issue needs an official rule | User with configure | New policy: tick 'May issue while the provider is down' with contingency text 'later'; then with a 10+ character rule reference; review and activate with approver | First save: 'Name the official rule that allows issuing while the provider is down.'. Second saves as Draft and needs an approver who is not the author to Review and Activate. 'Between 1 and 20 attempts.', 'Jitter between 0 and 50%.', 'The longest wait is shorter than the first.' for bad numbers |
Code mappings
| Action | When | What you do | What happens |
|---|---|---|---|
| A code mapping changes the XML | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; invoice with a product whose unit is 'carton'; user with configure | New mapping: List Unit of measure, Our code carton, Their code CT; Activate (no second person); post a UAE invoice with that product; download the request payload | The line carries unitCode='CT' instead of the default C62 (unit lookup is lower-case; unknown units fall back to C62). A draft mapping is NOT used until Activate |
Partner endpoints
| Action | When | What you do | What happens |
|---|---|---|---|
| Endpoint format checks and verification | A business partner; sandbox provider active | New endpoint: scheme 0235, identifier 12345; then 100000000000011; save; press Verify endpoint; then another endpoint with scheme 9957 and identifier UNKNOWN-PARTICIPANT, Verify; GLN 4006381333931 (valid) and 4006381333932 (bad check digit) with scheme 0088 | '12345' -> 'A 0235 endpoint is the 15-digit UAE TIN/TRN.'. Valid: verification 'format valid'; Verify with the sandbox: 'verified - The sandbox directory lists 0235:100000000000011.'; UNKNOWN-PARTICIPANT: 'failed - The sandbox directory has no such participant.'. GLN with a wrong check digit: 'A 0088 endpoint is a 13-digit GLN with a valid check digit.' Real directory lookup is not built (ASP: 'Directory lookup goes through the provider's own portal; the format was checked.') |
| Endpoint address feeds a KSA buyer | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; business customer partner with a Saudi VAT 310000000000003 but no address detail | Post an invoice to that customer (blocked); add an endpoint with building 4321, street, district, postal 23434, city, country SA; then use Rebuild after repair / Validate again | The submission lists the missing buyer fields by path (building_number, street, district, postal, city); after the endpoint exists a rebuilt submission carries them. |
Retention policies
| Action | When | What you do | What happens |
|---|---|---|---|
| Retention policy review | Seeded Draft rows AE 5 years and SA 6 years; users A and B | As B Review and Activate the AE row; try Years 0 and 31 on a draft | Needs a reviewer who did not author/last edit the draft; 'Between 1 and 30 years.' for bad values; the Archive integrity report lists country, years, legal hold and status. No deletion job exists, the policy is a record only |
Submissions
| Action | When | What you do | What happens |
|---|---|---|---|
| Posting hands an invoice over (UAE business) | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; auto-submit on; business customer partner with a TRN, an endpoint 0235 and an address; a product at 50.00 AED | Create a customer invoice: 2 x 50.00 at 5% VAT; confirm and post; open the invoice smart button; open the submission | Within a minute (or press Process queue now) the submission is Accepted with legal state Issued; profile AE-PINT-B2B v1; totals Net 100.00, Tax 5.00, Payable 105.00; canonical lines equal the invoice; snapshot hash and payload hash shown; UUID shown; one attempt; sandbox reference starts 'SIM-' |
| Customer type picks the profile | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; one business partner (market 'business') and one consumer partner | Post an invoice to each; compare the Profile column | Business customer -> AE-PINT-B2B; consumer -> AE-PINT-B2C. If no active profile covers country, customer type, document type and date the invoice posts anyway and no submission is created (via manual hand-over: 'No active e-invoicing profile matches this invoice's country, customer type and date.') |
| Auto-submit off: Pending until Submit; Process queue now | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; 'Submit automatically' off | Post two invoices; open the first: press Submit; on the dashboard press Process queue now | Both start Pending (nothing sent, 0 attempts). Submit on the first queues it and sends it at once (Accepted). Process queue now works the outbox (up to 50 items) and the second is only sent if it was queued; a Pending one is not sent by Process queue |
| Blocked by validation and Validate again | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; a business customer WITHOUT an endpoint 0235 | Post an invoice to that customer; open the submission; read Issues; press Validate again; try Submit via API | Submission Pending and Blocked (tab Blocked, tile 'n blocked by validation'); Issue 'Buyer electronic address (endpoint) is required by UAE PINT AE - business.' with field path buyer.endpoint.id, owner master data; Validate again re-checks the SAME stored snapshot; Submit is not offered; API: 'Fix the validation issues first; nothing is sent while the submission is blocked.' |
| Validation messages by field path (UAE) | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; invoices with: seller TRN 12345; buyer UAE with no TRN; a zero-rated line with no exemption reason | Post each; read the Issues tab | 'Seller registration '12345' is not a 15-digit UAE TRN starting with 1.'; 'Buyer TRN is required by UAE PINT AE - business.'; 'Line 1 is zero without an exemption reason.' (owner tax). One message per field; codes like EIN-FMT-AE_TRN, EIN-REQ-BUYER-REGISTRATION-ID, EIN-TAX-REASON |
| Accept then time out: ask first, never send twice (EIN-A1, T005) | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; sandbox set to 'timeout_after_accept' | Post an invoice; wait/Process queue; open the submission (Attempts tab); then set the sandbox back to accept and wait for the first back-off (60 s) or press Ask the provider | Attempt 1 outcome 'timeout'; state Status unknown with yellow banner 'No confirmed answer.'; alert 'no answer from SANDBOX; it will be asked before anything is sent again.'; the next action is a QUERY attempt that finds the stored acceptance, so the state becomes Accepted with NO second send (attempt list: submit timeout, query accepted) |
| Confirmed absence resends the identical payload | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; sandbox set to 'unavailable' for the first send only | Set sandbox to unavailable; post an invoice (send fails); set it back to accept; press Retry; compare payload hashes of both attempts | The second send reuses the SAME payload bytes and UUID (request hash equal on both attempts); the invoice ends Accepted; only one request payload is stored |
| Back-off arithmetic and attempts exhausted | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; sandbox unavailable; default policy (6 attempts, 60 s first retry, 3600 s cap, 20% jitter) | Post an invoice; watch Next attempt after each failure (use the submission record and Attempts tab); stop the sandbox failure only after 6 attempts | Waits are about 60 s (48-72), 120 s (96-144), 240 s, 480 s, 960 s ... never above 3600 s (+-20%). After attempt 6 the outbox row is Dead and a red alert says '<EIN-no> (<invoice>) could not be delivered after 6 attempts.'; Retry puts it back in the queue |
| Rejection is recorded with its reasons | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; sandbox set to 'reject'; seeded rejection code SIM-ADDR-001 | Post an invoice; open the submission: Overview, Issues, Attempts & answers, Payloads; Alerts; Event log | State Rejected (red), legal state stays Issued for the UAE profile; issue row origin 'provider' code SIM-ADDR-001, field path buyer.address.building_number, owner master data, remediation text; response payload kept; acknowledgement applied; alert 'was rejected: ...'; event einvoice.rejected.v1; rejected bytes are never deleted |
| Rebuild after repair: KSA clearance rejection (EIN-A2) | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; sandbox once ['reject']; a KSA business customer with incomplete address | Post the invoice (sandbox rejects); add the endpoint address on Partner endpoints; open the Rejected submission; press Rebuild after repair; type 'Address fixed' | The old submission shows legal state 'Not cleared' and becomes Superseded; a NEW submission in its lineage is Accepted with legal state Cleared; old issues become Resolved pointing at the new submission; both payload sets are kept; if amounts or lines changed meanwhile: 'The invoice's amounts or lines differ from what was submitted; that is a correction for Billing.' |
| Correct an issued rejected invoice by credit note | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; a UAE invoice Rejected (sandbox reject) | Open the submission; press Correct by credit note; reason 'Wrong address'; open the credit note from the 'Credit note' smart button; confirm and post it; check Submissions | Rebuild is NOT offered (legally issued). A DRAFT credit note is created linking the invoice (same lines, quantities, prices, taxes; note = the reason); open issues get remediation 'Corrected by credit note <no>; post it to e-invoice the correction.'; after posting, the credit note gets its own submission, type 381 with a BillingReference to the original number; the original submission stays Rejected; Correct is not offered again and not offered on a credit note |
| Debit note carries its original | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; a posted UAE invoice INV-A; a second invoice with meta debit_of = INV-A and correction_reason | Post the second invoice; download its payload; remove the correction_reason on another debit invoice and post | Canonical type is 'debit_note', XML type code 383 with BillingReference to INV-A (ZATCA: reason in the payment means note). A debit note without the original or reason is blocked: 'The invoice this debit note corrects is required by ...' / 'The reason for the debit note is required by ...' (reason rule applies to ZATCA profiles) |
| Asynchronous provider answer by signed callback | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; sandbox 'async'; a callback secret YOU entered (Bind credential: Callback secret, secret 'cb-secret-123', not generated) | Post an invoice (state Submitted, provider says 'Received; validation in progress.'); compute HMAC-SHA256 of the exact JSON body {ack_id:'A1', document_uuid:'<uuid>', status:'accepted', code:'OK'} with cb-secret-123; POST to /api/v1/einvoicing/callbacks/<company>/<provider> with header X-Ein-Signature | Reply {ok:true, duplicate:false, applied:true, state:'accepted'}; submission becomes Accepted; the body is stored as a 'callback' payload; delivery receipts ({type:'delivery'}) are stored on their own track and never change the state |
| Duplicate, late and refused callbacks | Submission accepted by the callback above | Send the same callback again; send a pending callback with an older authority_timestamp; send with bad signature, empty signature, invalid JSON, a list body, unknown document_uuid, no ack_id; send for an inactive provider | Repeat: {duplicate:true} nothing changes (T007). Late pending: kept as evidence, applied false, note 'Accepted is final; this acknowledgement is kept as evidence and not applied.' (T018). Errors: 403 'Signature check failed.', 400 'Not JSON.', 400 'Not an acknowledgement.', 404 'No such document.', 400 'An acknowledgement needs its id.', 404 'Not found.' for unknown/inactive provider or other company, 413 'Too large.' over 1 MB |
| Idempotency key on commands (T006) | A Pending submission; browser developer tools or an API client | POST .../submit with header Idempotency-Key 'abcd1234' twice with the same body; again with a different body; and with no key | Second identical call answers the first result with repeated:true and sends nothing more; different body -> 409 'This idempotency key was already used for a different request.'; no key -> 'Send an idempotency key with the command.'; the screen buttons send a fresh key each click (a double click is one command) |
| Payload download with hash check (T004) | An accepted submission; user with operate or audit | Payloads tab: download each row; compute SHA-256 of the file and compare with the screen; open the XML | Download is named '<kind>-<id8>.xml'; its SHA-256 equals the stored value and header X-Content-SHA256; an altered database row (not testable by UI) would answer 409 'The stored payload no longer matches its hash.'; a view-only user sees the table but no Download button and the API says 'Downloading e-invoice evidence needs the auditor or operator role.' |
| Issued rendering and PDF/A-3 | An Accepted/Issued submission; and a Pending-clearance KSA one | Payloads tab: press 'Issued rendering with QR'; call .../pdf for the same submission; try both on the pending-clearance one | Rendering is an HTML page with the seller, buyer, lines, totals, a QR picture, e-invoice number, legal state, UUID and payload hash, made once and reused (same hash next time). PDF is an A-3 PDF with the e-invoice XML inside (open the attachments panel of a PDF reader). Pending clearance: 'Only an invoice that has been legally issued has an issued rendering.' |
| Manual hand-over of an older invoice (API only) | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; an invoice posted BEFORE e-invoicing was switched on; user with operate | POST /einvoicing/submissions {document_id:<id>} with an Idempotency-Key; repeat; try a draft invoice; try a vendor bill id | Creates one submission (source manual) and sends it at once; a repeat with the same key returns the same result; the same invoice again returns the existing submission, not a second; draft: 'An invoice is e-invoiced once it is posted.'; bill: 'Only customer invoices, credit notes and self-billing sales are e-invoiced.'; no matching profile: 'No active e-invoicing profile matches this invoice's country, customer type and date.' |
| ZATCA invoice: counter, hash chain, signature and QR (local) | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; sandbox; three KSA standard invoices posted in order | Open each submission Overview (Counter / previous hash); download request payloads; compare | Invoices carry ICV 1, 2, 3; the first PIH is the fixed seed (base64 of the SHA-256 of '0': NWZlY2Vi...); each later PIH equals the previous invoice's hash; XML has InvoiceTypeCode 388 with name 0100000 (standard) or 0200000 (simplified), ICV, PIH, QR and signature blocks; the QR is Base64 TLV tags 1-9 (seller name, VAT number, date-time, total with VAT, VAT amount, hash, signature, public key, certificate signature); the counter never repeats or skips even when two invoices are processed together |
| KSA standard invoice: clearance legal states | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; business customer with full Saudi address and VAT 310000000000003 | Post an invoice with the sandbox unavailable; then let it be accepted; open the submission | While unsent: legal state 'Pending clearance' (not issued), dashboard 'Pending clearance' counts it, issued rendering refused; after acceptance: legal state 'Cleared'; the printed invoice (PDF) now carries the statutory QR; sandbox rejection: legal state 'Not cleared' |
| KSA simplified invoice: issued at once, reported within 24 hours | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; consumer (B2C) customer; policy deadline 24 h | Post an invoice with the sandbox accepting; repeat with the sandbox unavailable; compare legal state and deadline | Legal state 'Issued' immediately and 'Reported' after acceptance; deadline = creation + 24 h; while unavailable it stays queued and escalates (see deadline arithmetic); offline-allowed policy is on by default for this profile (contingency note shown) |
| KSA validation messages | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; invoices with: seller CRN 'AB123'; seller building '12'; buyer VAT 300000000000001 (does not end in 3); missing buyer postal code | Post each; read the Issues tab | 'Seller CRN 'AB123' is not a 10-digit commercial registration number.'; 'Seller building number '12' is not a 4-digit building number.'; 'Buyer VAT number '300000000000001' is not a 15-digit Saudi VAT number that starts and ends with 3.'; 'Buyer postal code is required by KSA ZATCA standard tax invoice (clearance).'; credit notes also need 'The reason for the credit note is required by ...' |
| POS till receipt as a simplified invoice | A test company whose country is Saudi Arabia (SA) with a 15-digit VAT number starting and ending with 3 (e.g. 300000000000003), seller CRN 1010000001, building 1234, district Al Olaya, postal 12211, e-invoicing on via the sandbox; POS configured with fiscal adapter a2n-einvoicing; B2C profile active | Sell and pay a ticket at the till; refund part of it; open Submissions | Each sale becomes a simplified invoice (document kind pos_receipt) signed and numbered at once so the receipt prints the QR; the refund is a simplified credit note naming the sold ticket; reporting runs from the queue; the same ticket twice returns the first submission; with e-invoicing off the till gets 'E-invoicing is switched off.'; with no B2C profile 'No active B2C e-invoicing profile covers this receipt.' |
| ZATCA clearance against the real portal [Blocked if no sandbox] | Blocked if no sandbox: needs a real authority / provider sandbox account and credentials. KSA company on the ZATCA developer portal, compliance + production-test CSID bound | Post a standard invoice; Process queue now; open the submission | ZATCA answers CLEARED with a stamped invoice (QR replaced by ZATCA's); legal state Cleared; warnings listed on the record; a NOT_CLEARED answer gives Rejected with the portal's codes and messages in Issues |
| ZATCA reporting of a simplified invoice [Blocked if no sandbox] | Blocked if no sandbox: needs a real authority / provider sandbox account and credentials. As above; B2C profile on the ZATCA provider | Post a consumer invoice; Process queue now | ZATCA answers REPORTED; legal state Reported. After a timeout the 'Ask the provider' step finds no status query ('ZATCA does not publish a status query; reconcile by resending the identical signed invoice.') so the identical signed bytes are resent and ZATCA must treat them as the same invoice |
| UAE accredited service provider exchange [Blocked if no sandbox] | Blocked if no sandbox: needs a real authority / provider sandbox account and credentials. A UAE ASP test tenant with its API contract, provider and bearer token entered; allowlisted host | Post a business invoice; Process queue; check Attempts; query the document | The PINT AE XML is accepted (or rejected with the ASP's errors); delivery receipts appear under 'Delivered to the buyer'; status query by UUID works; the generic REST adapter paths may need fitting to the chosen ASP |
Provider outages
| Action | When | What you do | What happens |
|---|---|---|---|
| Three failures open an outage case; first answer closes it | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; sandbox unavailable | Post three invoices (or let one fail three times) so three submit attempts in a row are 'unavailable'; open Provider outages and Dashboard; set sandbox to accept and let the queue run | A case with origin 'detected' opens once (not again while open) and a red alert 'SANDBOX is not answering; an outage case was opened.' appears; Dashboard 'Provider outages' card lists it; waiting documents count = queued + unknown items; the first accepted submission closes a detected outage by itself (manual ones need Close) |
| Report an outage, approve a contingency, close it | Two users: operator A (operate) and approver B (activate) | A: Report an outage on SANDBOX; A tries Approve contingency; B approves with text 'Hold clearance invoices pending; report within 24 h'; B closes it; report a second while one is open | Case origin 'manual', red alert; A is refused (needs activate and another person); B's text is stored with approver and time; contingency changes NO document's legal state; Close sets Closed with an end time; second open case: 'An outage is already open for this provider.'; 'The outage is already closed.' on a second close |
Invoices
| Action | When | What you do | What happens |
|---|---|---|---|
| A sent invoice cannot be reversed; an unsent one is closed | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; 'Refuse to reverse' on; one invoice sent (attempts > 0), one with auto-submit off | Reverse/cancel the sent invoice; reverse the unsent one; switch 'Refuse to reverse' off and retry the first | Sent: refused with '<no> was sent for e-invoicing as EIN-0000xx; it cannot be reversed. Issue a credit note to correct it.'. Unsent: reverses and its Pending submission becomes Superseded with 'The invoice was reversed before it was sent.'. Switch off: the reversal is allowed |
E-invoice smart button
| Action | When | What you do | What happens |
|---|---|---|---|
| Smart button on invoice and credit note | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; posted invoices in states Accepted, Rejected, Blocked, Status unknown; one draft invoice | Open each posted invoice in Sales > Invoices; click the chip; open a draft invoice | Chip shows the state (green accepted, amber rejected/blocked/unknown; 'Pending clearance' for KSA standard waiting); click opens the submission; the draft shows no chip; with e-invoicing off or no permission it shows nothing |
Received e-invoices
| Action | When | What you do | What happens |
|---|---|---|---|
| Upload a valid supplier e-invoice | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; a supplier partner with tax id equal to the invoice's supplier TRN; a UBL file addressed to the company TRN with one line (qty 2, price 50.00, tax 5%) | Received e-invoices > Upload e-invoice; open the new row | Row INB-000001 State Valid; supplier matched; Total 105.00 AED, tax 5.00; lines listed; event einvoice.inbound_validated.v1; the file can be downloaded back with the same SHA-256 |
| Duplicates: same bytes and same number with other content | The valid document received above | Upload the identical file; then edit one amount (same invoice number) and upload | Identical: State Duplicate 'Already received as INB-000001.' no second bill possible. Changed content: State Needs review (invalid) '...has the same invoice number with different content; review both before any bill is made.'; neither is merged |
| Safety checks before parsing (T017) | User with inbound | Upload: a file with <!DOCTYPE ...>; a file with <!ENTITY ...>; a file over 5 MB; a text file; XML nested more than 40 levels | Each is stored as evidence and shown Rejected with 'The document declares a DOCTYPE or entities, which is never accepted.', 'The document is larger than 5 MB.', 'The document is not well-formed XML: ...', 'The document is nested too deeply or is too large.'; nothing is parsed or billed |
| Content checks | User with inbound | Upload files: addressed to another TRN; lines adding to 100.00 but line total 90.00; net 100 + tax 5 but total 104.50; no invoice number; an Order (not UBL invoice) | Needs review with: 'The document is not addressed to this company's tax number.'; 'The lines do not add up to the document's line total.'; 'Net plus tax is not the document's total.' (tolerance 0.01); 'The invoice number is missing.'; 'Not a UBL invoice or credit note.' |
| Draft the bill | A Valid received invoice; supplier matched; one line whose seller item id equals a product code, one that matches nothing | Press Draft the bill without a fallback product; set 'Product for unmatched received lines' in Settings; press again; open the bill | First: 'Choose a product for line(s) 2, or set the fallback product in settings.' After the fallback: State Bill drafted; Billing gets a DRAFT supplier bill (never posted) dated with the e-invoice's issue date, reference = supplier's invoice number, quantities/prices/tax rates from the file; unmatched supplier -> pick one in the Supplier selector first ('Choose the supplier this document is from.') |
| Reject a received document; received credit notes | A Valid invoice and a Valid credit note | Press Reject with reason 'Not our order'; open the credit note and look for Draft the bill | State Rejected with 'Rejected: Not our order'; Reject refused for settled ones ('This document is already settled.'); credit note shows no Draft the bill; via API 'A received credit note is matched to its bill by hand.' (not built: no automatic credit) |
Submission monitor (R040)
| Action | When | What you do | What happens |
|---|---|---|---|
| Monitor totals reconcile | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; submissions created this month, one superseded | Open the monitor for this month; change From/To; compare with the Submissions list; Export CSV | One row per submission with its latest state; totals: semantic documents (superseded excluded), attempts, and one count per state label; period defaults to the 1st of the month to today; CSV has the same rows and column headings |
Reject analysis
| Action | When | What you do | What happens |
|---|---|---|---|
| Rejections grouped by code and field | At least two rejections of SIM-ADDR-001 and one validation block this month | Open Reject analysis; read Count, Open, Oldest open (h); repair one and rebuild; reopen | Rows grouped by origin, code, field and profile version; open ones first; Open falls and Resolved ones stop counting as open after the rebuild; totals issues/open agree |
Invoice-to-provider bridge
| Action | When | What you do | What happens |
|---|---|---|---|
| One invoice, one semantic submission | A test company whose country is UAE (AE) with a 15-digit TRN starting with 1 (e.g. 100000000000003), e-invoicing on via the sandbox; invoices accepted on the first try, one with three attempts, one reversed before sending, one posted before e-invoicing was on | Open the bridge for the month | Each posted/reversed invoice and credit note appears once with Total and attempts; 'Submissions' = live ones (superseded counted apart); flag 'missing' for the posted invoice with no submission; 'duplicate identity' only if two live submissions share an invoice and profile (should be zero); totals invoice value equals the sum of Totals |
Archive integrity
| Action | When | What you do | What happens |
|---|---|---|---|
| Every payload hash verifies | Several submissions and a received document | Open Archive integrity; read totals by kind; open a row with a submission; read the retention card | Every row Hash verified; totals payloads, mismatched 0 and a count per kind (request, response, callback, inbound, rendering); any mismatch would turn red (cannot be produced from the UI) |
Event log
| Action | When | What you do | What happens |
|---|---|---|---|
| Events are written with the change and published after | An accepted and a rejected submission; user with audit | Open Event log; compare the Occurred and Published columns; open a submission's Lineage & events tab | einvoice.accepted.v1 / rejected.v1 / status_unknown.v1 / inbound_validated.v1 with the submission and revision; Published shows a time within about a minute of Occurred; events carry hashes and ids, never a payload or secret; user without audit does not see the menu item |
Feature switches
| Action | When | What you do | What happens |
|---|---|---|---|
| Turn off 'Received supplier e-invoices' | Company admin able to open Applications > E-invoicing > Features | Switch off 'Received supplier e-invoices'; open Received e-invoices; try to upload and to draft/reject; switch on again | Menu entry disappears; changes through its routes are refused (capability_disabled) while already recorded rows stay readable; 'Submission, status and repair' is always on and has no switch; Settings fields 'Provider account', 'Solution unit serial (EGS)', 'Seller commercial registration' and 'Seller additional address number' can be made Required or Hidden under field settings, and a hidden one makes an input refused |