Overview
A CSID (Cryptographic Stamp Identifier) is the certificate that authorises your invoicing system to talk to the ZATCA Fatoora platform. It is the moment your sandbox prototype becomes a real connected system. CSIDs are device-specific, not company-wide; a chain store with 200 POS terminals needs 200 CSIDs (or one production CSID per device class). This guide walks you through the full onboarding flow, secret storage, rotation and revocation.
Who this applies to
- Every VAT-registered taxpayer whose ERP / POS / billing system needs to clear or report invoices.
Step 0: Prerequisites
- VAT registration number issued by ZATCA.
- ZATCA portal account.
- Production system that successfully passes ALL sandbox test cases.
- One-time password generated from the ZATCA portal per device.
Step 1: Generate device keypair
# Generate ECDSA secp256k1 keypair (curve required by ZATCA)
openssl ecparam -name secp256k1 -genkey -noout -out device.key
openssl ec -in device.key -pubout -out device.pub
# Generate Certificate Signing Request with the mandatory SAN fields
cat > csr.conf <<'EOF'
[req]
default_bits = 2048
prompt = no
distinguished_name = dn
req_extensions = v3_req
[dn]
CN = Skyline POS Device 0001
SerialNumber = 1-Skyline|2-RIYADH-BR-01|3-DEV-0001
OU = IT Department
O = Skyline Limited Company
C = SA
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = SN=DEV0001|EGS=Skyline-POS|SOL=POS|VAT=300000000000003
EOF
openssl req -new -key device.key -out device.csr -config csr.conf
Step 2: Submit CSR to sandbox compliance API
OTP="123456" # from ZATCA portal
curl -X POST 'https://gw-fatoora.zatca.gov.sa/e-invoicing/developer-portal/compliance' \
-H "OTP: $OTP" \
-H 'Accept-Version: V2' \
-H 'Content-Type: application/json' \
--data "{\"csr\": \"$(base64 -w0 device.csr)\"}"
Response contains:
binarySecurityToken— your sandbox CSID.secret— paired secret.requestID— for log/audit.
Step 3: Compliance test campaign
ZATCA requires you to submit, from the sandbox CSID, a representative scenario set:
- Standard invoice (B2B).
- Standard credit note.
- Standard debit note.
- Simplified invoice (B2C).
- Simplified credit note.
- Simplified debit note.
- At least one of each with 0% VAT, 5% VAT, 15% VAT.
Each submission must pass clearance/reporting validation. Maintain a test log.
Step 4: Production CSID issuance
After successful compliance campaign, request the production CSID:
curl -X POST 'https://gw-fatoora.zatca.gov.sa/e-invoicing/core/production/csids' \
-H "Authorization: Basic <BASE64(sandboxCsid:sandboxSecret)>" \
-H 'Accept-Version: V2' \
-H 'Content-Type: application/json' \
--data "{\"compliance_request_id\": \"$REQUEST_ID\"}"
You receive the production binarySecurityToken + secret. Store these as the most sensitive secrets in your system — they speak for the device to the tax authority.
Step 5: Secret storage
Acceptable:
- HashiCorp Vault with strict ACL.
- AWS Secrets Manager / Azure Key Vault with customer-managed keys in KSA region.
- HSM-backed key storage for highest-value setups.
Unacceptable:
- Application config file.
- Environment variable in a shared
.env. - Git repository (even private).
Per-device segregation: even if you keep them in Vault, use a separate path per device so a credential leak from one device does not compromise the rest.
Step 6: Rotation and renewal
- CSID is valid 1 year by default.
- Build the renewal endpoint into your application so a CSID rotates 30 days before expiry.
- Maintain ICV/PIH continuity across rotation — the new CSID continues the same invoice counter chain.
curl -X POST 'https://gw-fatoora.zatca.gov.sa/e-invoicing/core/production/csids/renew' \
-H "Authorization: Basic <BASE64(currentCsid:secret)>" \
-H "OTP: $NEW_OTP"
Step 7: Revocation
If a device is lost, stolen, decommissioned or compromised:
- Immediately revoke via the ZATCA portal.
- Replace with a new CSID following the same flow.
- Forensic-analyse the gap to detect unauthorised invoices.
Common gotchas
- Generating ECDSA on the wrong curve (P-256 instead of secp256k1) — rejected.
- CSR SAN strings using wrong delimiter — must be
|and ordered. - Sharing a single CSID across multiple devices — breaks ICV chain.
- Storing CSID secret in a config file committed to git.
- Forgetting to set OTP header → 401 Unauthorized.
Verification
- CSID inventory: device ID, CSID expiry date, last renewal date.
- Secret-vault audit log showing all access events.
- Test-suite results from compliance campaign retained 6 years.
- ICV / PIH integrity continuous across renewals.
Conclusion
CSID onboarding is the point of no return between sandbox and production. Get the cryptography right once, the secret storage right once, and the operational rituals (renewal, rotation, revocation) right once — then it becomes background plumbing.
Comments
0 total · 0 threads