Product Setup

Civil Servant Product Setup Guide (Ndasenda payroll deduction)

This guide configures a loan product for civil servants repaid by payroll deduction through Ndasenda — Zimbabwe’s payroll-deduction platform. The workflow verifies the borrower’s national ID against Ndasenda during KYC and registers the repayment mandate automatically once loan terms are set.

Audience: tenant administrators and lending operations.


Overview of the flow

Application → documents → Ndasenda ID check → employer/credit → offer accepted
    → Ndasenda mandate registered → final approval → origination
    → disbursement (NetOne B2C intent or manual) → servicing
    → payroll deduction remits repayments (plus optional NetOne self-pay)

Two integration gates do the provider work inside origination; disbursement and repayments run as payment intents afterwards. Nothing provider-specific is hardcoded — the same Ndasenda connection serves every product that needs it.


Step 1: Ndasenda prerequisites

Before configuring anything in Hiana Loans, obtain from Ndasenda:

  • API credentials — username and password for the OAuth token endpoint.
  • Security token — the static securityToken sent in request bodies.
  • Deduction code — the employer/paymaster deduction code for your mandates.
  • Base URL (and the token URL only if Ndasenda mounts OAuth somewhere other than {base}/connect/token).

For each borrower, the mandate record needs:

  • National ID number — on the borrower’s individual record.
  • EC number and payroll number — on the borrower’s current employment record (fields added by migration 000268). Capture them at intake or on the borrower profile; application custom fields with the same keys override the record per application.
  • Linked employment — the borrower’s current employment must reference the employer, matching the employer-backed product prerequisites.

Step 2: Create the Ndasenda shared connection

Admin → Shared Integrations → New connection → adapter: Ndasenda direct

FieldValue
Base URLNdasenda API base URL
Token URLLeave blank unless Ndasenda gave you a different OAuth endpoint
Deduction codeThe deduction code issued for your mandates
Username / PasswordOAuth credentials
Security tokenStatic token from Ndasenda

Save once — the connection is tenant-wide and reusable across products. Credentials are encrypted and write-only.

Step 3: Create the product

Admin → Loan Products → Create Product — name, currency, amount/term ranges, monthly repayment frequency to match the payroll cycle. Then work through the standard configuration tabs (documents, guarantor/MOU, credit risk, affordability) as in the employer-backed guide.

Step 4: Workflow with Ndasenda integration gates

Product Configuration → Workflow. Two steps of type Integration carry the provider work; the rest is the standard origination sequence.

OrderStep keyStep typePurpose
…document_upload / document_review / kyc_verificationstandardas per the employer-backed baseline
4ndasenda_id_checkINTEGRATIONVerify the national ID against Ndasenda IDChecks
…fraud_screening, employer_approval, credit_check, underwriting, offer_proposalstandardas per the baseline
9offer_acceptanceOFFER_ACCEPTANCEterms agreed — the proposal’s installment now exists
10mandate_registrationINTEGRATIONRegister the payroll deduction mandate
11consent_capture, agreement_generationstandard—
12approvalAPPROVALfinal internal approval

Why the mandate sits after offer_acceptance: the default mandate record uses the active proposal’s installment as the deduction amount and the requested term as the mandate end date. Registering earlier would guess at an amount that underwriting may still change.

Step 5: Integration requirements

Product Configuration → Integrations — one requirement per gate step:

Workflow typeStep keyCapabilityProviderRequired
LOAN_APPLICATIONndasenda_id_checkIDENTITY_VERIFICATIONyour Ndasenda connection✓
LOAN_APPLICATIONmandate_registrationMANDATE_REGISTRATIONyour Ndasenda connection✓

Set Timeout (seconds) and Retry limit per gate (30s / 5 retries are sane starting points). Required gates block the step when the provider fails — leave required off only while piloting.

What the mandate submits

With no records override, the adapter builds one deduction record per mandate: type=NEW, idNumber (spaces/dashes stripped), ecNumber, payrollNumber, name/surname from the borrower record, reference = application number, startDate = today, endDate = start + requested term (yyyyMMdd), amount = proposal installment in cents. The batch also carries recordsCount and totalAmount (= Σ record amount), which Ndasenda validates — these are computed automatically. To submit a custom batch (multiple records, different amounts or dates), put a records array in the application’s custom fields — it passes through verbatim. Optional payload keys: total_amount/total_due (whole obligation, decimal-major → record totalAmount cents) and ignore_errors = true (submit with ?ignoreErrors=true so one bad record doesn’t fail the batch).

Registration is commit-then-poll: the batch is submitted, committed, then polled until Ndasenda’s response batch arrives. A declined record fails the gate; a batch with no response yet keeps the task pending rather than duplicating the mandate.

Step 6: Disbursement — NetOne (or traditional)

Once the application is approved and originated, fund the loan:

  • NetOne B2C to the borrower’s OneMoney wallet: create the disbursement (mobile-money method, wallet number), then Start provider transfer on the disbursement record — POST /servicing/disbursements/{id}/intent with the NetOne connection. The adapter resolves the recipient’s NetOne ID via the subscriber lookup, verifies the wallet is active and certified, then pays out. A confirmed provider result is what activates the loan.
  • Traditional: record a bank transfer/cash disbursement as usual — no provider intent needed.

Requires a NetOne shared connection (b2c_url, b2c_status_url, customer_lookup_url, and the NetOne credential set). notify_url is optional — status polling covers final results either way.

Step 7: Repayment channels

  • Payroll deduction (primary): the registered mandate deducts the installment each payroll cycle; remitted amounts are recorded against the loan through the normal repayment capture/import. The mandate amount equals the proposal installment.
  • NetOne self-pay (OneMoney C2B): for catch-up or ad-hoc payments — the loan’s payment rail form posts POST /servicing/payments/intents {loan_id, provider_id, amount, currency, mobile_number}. NetOne USSD-pushes that number; the payer approves by PIN. Any Zimbabwean NetOne number works — the payer need not be the registered borrower. Non-NetOne or inactive numbers are rejected before a request is sent (format check + subscriber lookup).
  • Traditional: cash, bank transfer, or POS recorded through normal payment capture — unaffected by whether integrations are configured.

Step 8: Mandate cancellation on closure

When the loan closes — full payoff, early settlement, or write-off — the closure service finds the application's succeeded mandate registration and queues a MANDATE_CANCELLATION payment intent against the same Ndasenda connection. The intent submits a DELETE record carrying the same borrower identifiers (national ID, EC/payroll numbers) the NEW record was registered with, then marks succeeded on provider acceptance.

  • Nothing to configure: the original registration's provider and payload are reused, and the idempotency key deduplicates re-closure attempts.
  • The cancellation is durable and retried like any payment intent — check its status at GET /servicing/payments/intents/{id} if needed.
  • Confirm Ndasenda has accepted the DELETE record before relying on deductions having stopped.

Pensioner loans (pension-scheme mandates)

The same Ndasenda integration covers pension-scheme borrowers — the adapter picks the deduction code by employment scheme:

  1. Borrower record — set employment_type = PENSIONER (or employment_status = RETIRED) and capture pension_number. Ndasenda carries the pension number in payrollNumber; the adapter falls back to pension_number automatically when no payroll number exists.
  2. Connection settings — add deduction_code_pensioner alongside deduction_code_ssb on the shared Ndasenda connection. Resolution order: explicit payload deduction_code → deduction_code_pensioner (pensioner/retired borrowers) → deduction_code_ssb (other schemes) → default deduction_code.
  3. Product — a pensioner product reuses this whole guide unchanged; only the borrower population differs. Pension income can feed affordability via the enable_pension_income credit-risk data source.

Signed mandate document (TY30)

Pensioner mandates require the signed TY30 mandate form; SSB mandates do not. The adapter attaches the document between batch creation and commit when the payload carries mandate_document_base64 (base64 file content) plus optional mandate_filename. The attach key is resolved from ec_number → pension_number → payroll_number → id_number.

A pensioner mandate submitted without the document is held as a draft batch (result status: AWAITING_ATTACHMENTS, batch id in the external reference) rather than committed — committing without the attachment parks it permanently. Re-running the registration with mandate_document_base64 in the payload attaches the file, commits the held batch, and resumes polling. SSB registrations skip the attachment entirely and commit immediately.

All servicing operations (waivers, top-up, delinquency pause, re-aging, maker-checker) apply equally — see the Loan Servicing Operations Guide.

Checklist

  • Migration 000268 applied; borrower employment record carries EC + payroll number
  • Ndasenda connection saved with deduction_code, OAuth credentials, security token
  • Workflow published with ndasenda_id_check and mandate_registration INTEGRATION steps
  • Integration requirements saved with matching step keys, capabilities, required flags
  • (If NetOne disbursement/self-pay) NetOne connection with b2c_url, b2c_status_url, c2b_url, c2b_status_url, customer_lookup_url
  • Rehearse end-to-end: application → ID check passes → offer accepted → mandate batch committed → disbursement intent confirms → deduction recorded on the loan