An official developer portal of the Government of the Republic of Zambia · Test environmentVerify a certificate
Pamodzi Developer HubBuild, integrate and learn the e-Services framework
On this page

Registers and data sharing

The National Data Registers (NDR) are the platform's reference data: businesses, societies, vehicles, land parcels, permits and licences, places and code lists. Services use them to check answers on a form, officers search them, and other systems read them through the Partner API.

This guide explains how a register describes its data, who may see which field, and how another organisation gets access: always through a data-sharing agreement issued by the MDA that owns the register.

Registers and custodians

Each register belongs to a ministry, its custodian. Custodians are staff of that ministry who hold the register custodian role. They decide who may read the register, review agreements and see its usage.

Each register also has a search policy, the minimum kind of caller who may search it:

Search policyWho may search
publicAnyone, including people who are not signed in
authenticatedAny signed-in person
officerStaff
restrictedOnly holders of an active access grant and the register's custodians

Register reads are rate-limited per caller and per address, more tightly on registers that are not public.

Register packs

A register pack is a JSON file that types a register: what a record looks like and how sensitive each field is. Core packs live in zcm-backend/data/ndr/packs/ (business-entity, society, vehicle, land-parcel, person, civil-event, authorisation, code-list, geography). A module can contribute its own packs through the registers.packs extension point.

A shortened, synthetic example:

{
  "id": "business-entity",
  "version": "1.0.0",
  "kind": "entity",
  "policy": { "default": "public", "minimum": "public" },
  "entry": { "key": "entityNumber", "label": "name" },
  "fields": {
    "entityNumber": { "label": "Entity number", "sensitivity": "public", "identifierType": "entity-number" },
    "name": { "label": "Name", "sensitivity": "public" },
    "founders[].name": { "label": "Founder", "sensitivity": "internal" },
    "founders[].nrc": { "label": "Founder NRC", "sensitivity": "personal", "maskAs": "nrc" }
  }
}

The pack rules:

  • Every field of the record has exactly one entry with a sensitivity: public, internal, personal or

    sensitive. A field the pack does not describe is never returned from a typed register.

  • policy.minimum is the lowest search policy the register may have. Setting a lower one is refused (409 PACK_POLICY).
  • Only searchFields can be searched, and searching a field above your clearance is refused (`403

    FIELD_NOT_SEARCHABLE`).

  • Identifiers (NRC, TPIN, passport, entity number, plate and others) feed a party index that links records across

    registers. The index stores a keyed hash of each identifier, never the identifier itself.

  • A new major version of a pack never rewrites existing records: each record keeps the version it was validated

    against.

Clearance and masks

Who sees a field depends on the caller's clearance for that register:

ClearanceWho has it
publicAnyone who is not staff: citizens and anonymous callers
internalStaff who may read the register
personalStaff of the register's ministry, administrators and Support staff, a partner client whose scope includes the register
sensitiveNobody by default. Only through a grant that names the field, or a recorded reveal

A field is shown in full when its sensitivity is at or below the caller's clearance. Otherwise a staff or partner caller sees it masked, and a public caller does not receive the key at all. Every answer lists the masked and withheld paths.

MaskExample (synthetic)
nrc******/**/0
phoneonly the last 3 digits
emailj***@example.com
partialfirst and last character
hiddennull

A member of staff who needs to see a masked field in full for one record asks for a reveal, with a reason. The reveal is audited.

Data-sharing agreements

A data-sharing agreement is the only way the platform gives another organisation access to a register. It records why a consumer reads a register, which fields, under which legal basis and for how long. The consumer can be:

  • partner: an outside organisation's system, which gets a Partner API client;
  • mda: another ministry's staff;
  • node: another installation in the federation.

The flow

StepWhoResult
RequestAny signed-in person (or staff for their ministry)draft: consumer, registers and fields, purpose, legal basis, contacts, wanted period
ReviewThe register's custodian; never the requesterunder-review: the custodian sets the terms. Fields and period may only be narrowed, never widened. Retention days are required; onward sharing is off unless allowed
ApproveThe Data Protection Officer; never the requester or the reviewersigned: the agreement PDF is generated (parties, purpose, legal basis, fields with their sensitivity, conditions, contacts, approvals) and sealed when signing is configured. Its SHA-256 is recorded either way
ActivateThe custodian, on or after the start dateactive: access grants are issued per register, limited to the agreed fields, ending on the agreement's end date. For a partner, an API client is created and its secret shown once to the person activating
TerminateCustodian, DPO or administrator, with a reasonterminated: grants and client revoked at once
ExpireDaily jobexpired: grants expired and client revoked. A read after the end date is refused at once anyway, because the grants and the client carry the same end

A request can also be declined (with a reason) before activation, or withdrawn by the requester before signing. A renewal is a new agreement with a new client, never a silent extension. By default an agreement lasts 365 days, at most 1,095, and both parties are reminded 30 days before the end.

Field minimisation

A reader who is let in only by an agreement sees only the agreed fields, on every read path: search, single record, lookup and change feed. A record's label is shown only when it is made of agreed fields. Party-link searches skip registers the caller can read only partly.

Per-agreement API specification

Each agreement has its own OpenAPI file and PDF, listing only the routes of its registers and only its agreed fields:

GET /api/data-sharing/agreements/{id}/openapi.json
GET /api/data-sharing/agreements/{id}/openapi.pdf

Each register also publishes its partner routes and record schema, with each field labelled by its sensitivity (x-gsb-sensitivity):

GET /api/data-registers/catalog/{code}/openapi.json

A partner system gets a token with the client credentials grant at POST /api/v1/oauth/token and calls the register routes with the registers:read scope. Older register API keys have been folded into partner clients and answer with Deprecation and Sunset headers.

Across the federation

A node can read a register held elsewhere with the federation operations registers.list and registers.lookup. The register's home installation decides: a node gets access only through an agreement whose consumer type is node, and sees only the agreed fields. Both sides audit the read. A relay between two nodes through the hub is documented but not built.

Open data

Custodians may propose datasets for open publication. The Data Protection Officer decides, and never on their own proposal. Published datasets are listed in a DCAT-AP catalogue:

GET /api/open-data/catalog
GET /api/open-data/datasets/{slug}.csv
KindAllowed when
register-rowsThe register may be searched by anyone and every one of its fields is public
register-countsCounts by one or two public, non-identifying fields, or a date cut to year or month. Cells below 10 are suppressed, with complementary suppression so they cannot be worked out
service-statisticsApplications received and decided per service and month, with the same suppression

Rows of registers about people are never published. The default licence (CC-BY 4.0) is an assumption awaiting a decision.

Consented prefill

A citizen can fill an application from their own register records, for example their company's details. This is off unless the installation sets REGISTER_PREFILL=on. When on:

  • only the applicant of their own draft application can use it;
  • their NRC must have been verified by the identity provider (a typed-in NRC is refused);
  • they must give explicit consent, which is kept with the application together with its wording and time;
  • only public and internal fields are copied, never anyone's identifier, contact details or address (a company record

    also holds other people's details);

  • every use is audited.

The back-office endpoint is built; the form's "fill from register" button is not yet.

The hub's access requests

The Developer Hub's access request page is the intake for register data, Partner API clients and federation nodes. It does not issue access:

  1. You describe the register, purpose, legal basis, data items, volume, retention and safeguards. A request for

    register data needs the Pamodzi Certified Data Steward certificate (course).

  2. A hub reviewer recommends a decision, and a data steward who is not the reviewer decides.
  3. The owning MDA then creates the data-sharing agreement (or API client) on the platform, through the flow above,

    with its own custodian and DPO approvals.

  4. The steward records the agreement or client reference on your hub request.

Access exists only while the platform's agreement does. Ending the agreement on the platform ends the access, whatever the hub shows.

Next steps