Integrations

Biller-Routed Provider Connections — Setup Guide

This guide explains how tenant provider connections work when they are routed through the Biller engine — collections, disbursements, and payroll-deduction feeds (Ndasenda, NetOne, and future providers) that execute on the billing service rather than inside Hiana.


The Two-Layer Model

Hiana product / feed worker
        │  references a provider connection by provider_id
        ▼
Hiana provider connection          ← routing only (Admin → Integrations)
        │  biller_provider_key points at…
        ▼
Biller provider connection         ← owns endpoints, settings, credentials
        │  adapter_key selects…
        ▼
Biller protocol adapter            ← executes the real provider calls
  • Hiana owns routing. Its connection is a pointer: "executions for this provider go to biller connection X using adapter Y." It stores no credentials and no provider settings of its own.
  • Biller owns protocol config. Base URL, deduction codes, feed intervals, and encrypted credentials live on the biller connection (/tenants/{id} → Money movement → Provider connections).
  • Products reference the hiana connection. Integration gates in a product's workflow pick the hiana provider; the execution is forwarded to biller.

Prerequisites

  1. The organization exists as a tenant in Biller with the same canonical UUID as the Auth Engine organization (provisioning is a platform-admin operation — POST /api/v1/tenants on biller, or the biller admin UI).
  2. The biller-routed connection is configured on Biller first — adapter, base URL, deduction/feed settings, credentials.

Step 1 — Configure the connection on Biller

In the Biller admin UI, open the tenant workspace → Provider connections → Add:

FieldExample
Provider keyndasenda
Display nameNdasenda SSB
Adapterndasenda
Base URLhttps://api.sandbox.deductions.ndasenda.co.zw
Deduction codeyour employer deduction code
Feed poll interval3600 (enables the repayment import feed)
Credentialsusername / password / security token

Credentials are write-only and encrypted at rest — they can be rotated by re-entering, never viewed again.

Running multiple schemes: Ndasenda issues separate deduction codes per paymaster (SSB civil servants vs pensioners). Create one biller connection per scheme — e.g. ndasenda (SSB code) and ndasenda-pension (pension code) — same base URL and credentials, different deduction code.


Step 2 — Create the routing provider on Hiana

Admin → Integrations → Provider connections → Add provider connection:

FieldWhat to enter
Provider keyA unique key for this routing entry — e.g. biller-ndasenda. It identifies the hiana-side provider.
Display namee.g. Ndasenda via Biller
Adapterbiller
Protocol adapterThe adapter on biller that executes this provider — ndasenda, netone, … (required)
Biller provider keyThe provider_key of the connection created in Step 1 — e.g. ndasenda. Leave blank to default to this connection's provider key.
Settings JSONLeave {} — settings live on the biller connection; an empty object preserves them.
SecretsNone — the biller adapter exposes no secret fields; credentials stay on biller.

Save. The handler synchronizes the connection to biller and stores biller_connection_id back on the hiana provider. For a pension scheme, repeat with biller-ndasenda-pension → biller provider key ndasenda-pension.

What each system owns

Hiana providerBiller connection
Purposerouting referenceprotocol execution
Provider keybiller-ndasendandasenda
Settings{}base_url, deduction codes, feed interval
Credentialsnoneusername/password/security token

Editing rules

  • provider_key is the identity. Saving with a key that already exists edits that connection — the form warns when a key is in use. Two different schemes need two different keys.
  • Saving the hiana provider never wipes biller config. An empty settings object is treated as "not managed here"; credentials are only replaced when secrets are explicitly provided.
  • Renaming: the sync writes hiana's display name onto the biller connection — cosmetic only.

Step 3 — Reference it from products

In a product's workflow configuration, add INTEGRATION steps (e.g. ndasenda_id_check, mandate_registration) and select the routing provider (biller-ndasenda for civil-servant products, biller-ndasenda-pension for pensioner products). See CIVIL_SERVANT_PRODUCT_SETUP_GUIDE.md for the workflow steps themselves.

Executions are enqueued as integration executions in hiana, forwarded to biller, and resolved by the normal pending/poll lifecycle.


Step 4 — Repayment feeds

When a biller connection has a feed poll interval configured, biller polls the provider and stores normalized feed items. Hiana's repayment feed consumer pulls them per tenant and posts repayments against loans (matching borrowers by EC / payroll / pension number).

  • The consumer only polls tenants with an enabled biller provider — enable/disable takes effect on the next sweep, no restart.
  • GET /api/v1/money-movement/feeds/REPAYMENT_IMPORT/items on biller returns 200 with an empty items array when the pipeline is healthy but idle.
  • Troubleshooting (401s, tenant-not-found, stuck cursors): docs/repayment-feed-troubleshooting.md.

NetOne notify URL

The notify_url field is optional — the adapter auto-fills the built-in callback endpoint ({APP_BASE_URL}/api/v1/webhooks/netone) when neither the execution payload nor the connection setting provides one. NetOne posts the final order result there and the pending execution resolves immediately; status polling remains the fallback. Only set notify_url to route callbacks elsewhere.