The PRO services office around the corner charges SAR 250–450 to renew your commercial license on Balady. What it actually does: log in, click six buttons, upload a PDF you already have, and pay. For a single establishment this fee is a nuisance. For a chain managing 40 branches or an ERP platform serving 3,000 merchants, it is a recurring manual process that should not exist.
Saudi Arabia issued and renewed more than 274,000 commercial licenses in the first half of 2026 alone — 97,000 new issuances and 177,000 renewals. That renewal volume (roughly 30,000 per month) is the automation opportunity. The challenge is that Balady license operations are not a single API call. They are a prerequisite cascade, and most automation attempts fail at one of four checkpoints before the first request is even sent.
What the Balady Platform Manages
Balady (منصة بلدي) is the Ministry of Municipalities and Housing's unified digital platform for all municipal services. For businesses, the relevant license types are:
- Commercial activity license (رخصة النشاط التجاري) — required to operate any retail, food, consulting, or industrial activity
- Craft license (رخصة الحرفة) — for skilled trade activities
- Building permit (رخصة البناء) — construction activities
- Temporary mobile store license — for seasonal or event-based operations
The commercial activity license generates the most integration demand. It links to Civil Defense, the Commercial Register, the National Address system, and — for specific activity categories — Qiwa.
Balady publishes its open data through a dedicated endpoint:
GET apiservices.balady.gov.sa/v1/momrah-services/open-data
The integration requirements and data schema are documented on balady.gov.sa/ar/e_participation/11520. For license submission and status queries, access flows through Balady Aamal (business.balady.sa), which handles multi-establishment service providers and authorized integration partners. The integration pack — including exact endpoints, authentication flows, and schema definitions — is provided after Nafath-authenticated account approval, following the same access model as Etimad, Muqeem, and SIMAH.
The 4 Prerequisites That Silently Block Automation
Every failed Balady license application traces back to one of these four dependency states. The platform does not return a clear error message — it simply tells you the request cannot proceed.
1. Commercial Registration Must Be Active
The most common silent blocker. Balady cross-checks the CR against the Wathq/Maroof registry on every submission. If the CR has expired — even by a single day — the application cannot be submitted. The error is a generic "لا يمكن تقديم الطلب" with no expiry date surfaced in the response.
The fix: pull CR status from the Wathq API (developer.wathq.sa) and check expiryDate before touching Balady. Wathq returns CR status, owner, activity codes, and expiry in a single call. CR renewal via the Saudi Business Center (business.sa) takes 1–5 days — buffer accordingly.
2. Civil Defense Permit Must Be Current
Balady generates two separate invoices for most commercial license operations: a Civil Defense (NCDD) fee invoice and a municipal fee invoice. The sequence is enforced: the municipal invoice only appears after the Civil Defense invoice has been paid and cleared.
Systems that submit a license request and immediately expect a single payment link will stall here. The correct integration pattern is: submit → poll for CD invoice → pay CD invoice → wait for clearance → poll for municipal invoice → pay municipal invoice. Skipping this sequence produces a status of "في انتظار الدفع" that never resolves.
Civil Defense clearance timing varies by activity type. Low-risk retail typically clears within hours; food, medical, and industrial activities may trigger an on-site inspection, adding 2–7 days.
3. National Address Must Match
Every license request requires a verified National Address tied to the establishment's physical location. Balady validates the address against the Subul registry. Three mismatches that silently block applications:
- Building or unit number changed after a municipality re-survey (common in Riyadh's expanding districts)
- PO box submitted instead of a street address — Balady requires a geocoordinate-linked address, not a postal reference
- Compound address without individual unit designation — chains with multiple outlets in one compound need separate address entries per outlet
Run address verification against the Subul API before the license call, not as a fallback after the submission fails.
4. Qiwa Professional Exam (Activity-Dependent)
For regulated activity categories — medical, legal, consulting, food preparation — Balady checks that the license holder or responsible manager has passed the relevant professional competency exam via Qiwa. This is a live registry lookup, not a document upload.
A common failure: a branch manager changes, the new manager has not yet completed the Qiwa exam, and every renewal attempt for that branch silently fails. The fix is to check the responsible manager's Qiwa exam status before triggering renewal.
Pre-Submission Validator Pattern
Run the prerequisite checks as a batch before any Balady call.
interface LicensePrereqs {
crStatus: 'ACTIVE' | 'EXPIRED' | 'SUSPENDED';
crExpiryDate: string;
addressVerified: boolean;
cdPermitStatus: 'CURRENT' | 'EXPIRED' | 'PENDING_INSPECTION';
qiwaExamPassed: boolean | null; // null for non-regulated activities
}
async function validateLicensePrereqs(
crNumber: string,
nationalAddressCode: string,
activityCode: string,
responsibleManagerId: string
): Promise<LicensePrereqs> {
const [cr, address, qiwa] = await Promise.all([
wathqClient.getCR(crNumber),
subulClient.verifyAddress(nationalAddressCode),
isRegulatedActivity(activityCode)
? qiwaClient.getExamStatus(responsibleManagerId, activityCode)
: Promise.resolve(null),
]);
return {
crStatus: cr.status,
crExpiryDate: cr.expiryDate,
addressVerified: address.verified,
cdPermitStatus: await getCDPermitStatus(crNumber),
qiwaExamPassed: qiwa?.passed ?? null,
};
}
async function triggerLicenseRenewal(
crNumber: string,
nationalAddressCode: string,
activityCode: string,
responsibleManagerId: string
): Promise<void> {
const prereqs = await validateLicensePrereqs(
crNumber, nationalAddressCode, activityCode, responsibleManagerId
);
if (prereqs.crStatus !== 'ACTIVE') {
throw new Error(`CR ${crNumber} is ${prereqs.crStatus} — renew via business.sa first`);
}
if (!prereqs.addressVerified) {
throw new Error(`Address ${nationalAddressCode} failed Subul verification`);
}
if (prereqs.qiwaExamPassed === false) {
throw new Error(`Manager ${responsibleManagerId} has not passed Qiwa exam for activity ${activityCode}`);
}
if (prereqs.cdPermitStatus === 'EXPIRED') {
throw new Error(`Civil Defense permit expired — update via NCDD before Balady submission`);
}
// All prerequisites pass — submit renewal to Balady Aamal
const renewal = await baladyAamalClient.submitRenewal({ crNumber, nationalAddressCode });
// Poll for Civil Defense invoice first — do not skip to the municipal invoice
await pollForCDInvoice(renewal.requestId);
}4 Failure Modes
CR expired while your system shows it as active. Balady checks the live Wathq state; your ERP's cached CR record is stale. Sync CR status from Wathq on a weekly schedule, not only at renewal time.
Civil Defense invoice never appears. A medium-risk activity triggered an on-site inspection. The inspection appointment must be scheduled manually through the NCDD portal — there is no API hook for this. Build a human-escalation path for this status rather than an infinite polling loop.
Address mismatch after municipality re-survey. The establishment's coordinates shifted in the municipality's GIS layer after a district expansion. The fix requires a National Address update via Subul — a separate workflow from license renewal. Detect this early by running address verification on a quarterly schedule, not only at renewal time.
Qiwa exam status not propagated after completion. Qiwa exam results take up to 48 hours to appear in the registry after passing. A renewal triggered immediately after the manager completes the exam will fail. Add a 48-hour delay after exam completion before re-triggering the renewal workflow.
Violation and Objection
Operating without a valid commercial license exposes the establishment to:
- Initial warning with a correction period
- After the correction period: SAR 1,000–5,000 fine per violation
- Possible site closure for high-risk activity categories
If Balady suspends or cancels a license, an objection can be filed within 60 days from the suspension date. Automate the objection window tracking: store the suspensionDate field from the Balady status response and generate an alert at day 45, not day 59.
What This Means for Multi-Branch Operations
A chain with 40 branches in Saudi Arabia renews approximately 480 commercial licenses per year. At SAR 300 per PRO office renewal, that is SAR 144,000 annually in manual processing fees, plus the compliance risk from delayed renewals. The prerequisite validation layer, once built, also surfaces the compliance gaps that generate violations before they become fines — expired CRs, lapsing Civil Defense permits, manager changes that break Qiwa checks.
The integration is not a product we sell you. It is the compliance middleware between your ERP and the municipal registry that makes the data you already have actionable.
If you are building or inheriting a system that needs to manage Saudi commercial licenses at scale, we can audit the integration points and identify where the current setup will break. Contact us to start with a diagnostic review.