Data-sharing agreements
A data-sharing agreement is the record of why a consumer reads a register, which fields, under which legal basis and for how long. On the Pamodzi e-Services framework it is the only way another organisation gets access to a register. This lesson walks through the agreement's life, the separation of duties that protects it, and how the Developer Hub's access requests fit in.
Who can be a consumer
| Consumer type | Who | What activation gives them |
|---|---|---|
partner | An outside organisation's system (a bank, a regulator's system) | A Partner API client limited to the agreed registers and fields |
mda | Another ministry's staff | Access grants for that ministry, limited to the agreed fields |
node | Another installation in the federation | Grants for that node, read through the federation operations |
The life of an agreement
| Status | Reached by | Who acts | What happens |
|---|---|---|---|
draft | Request | Any signed-in person, or staff for their ministry | Consumer, registers and fields, purpose, legal basis, contacts and the wanted period are recorded |
under-review | Review | The register's custodian | The custodian sets the terms. Fields and period can be narrowed, never widened, and no register added. Retention days are required. Onward sharing is off unless explicitly allowed |
signed | Approve | The Data Protection Officer | The agreement PDF is generated: parties, purpose, legal basis, fields with their sensitivity, conditions, contacts, approvals. It is sealed when signing is configured; its SHA-256 is recorded either way |
active | Activate | The custodian (or an administrator, recorded as an override), on or after the start date | Grants are issued per register, limited to the agreed fields, ending on the end date. A partner gets an API client whose secret is shown once |
terminated | Terminate | Custodian, DPO or administrator, with a reason | Grants and client revoked at once |
expired | End date | Daily job | Grants expired, client revoked, audited |
declined | Decline | Custodian, DPO or administrator, with a reason, before activation | Nothing is issued |
withdrawn | Withdraw | The requester, before signing | Nothing is issued |
Defaults: an agreement lasts 365 days, at most 1,095 (three years). The requester and custodians are reminded 30 days before the end. A person may have at most 5 open requests. A renewal is a new agreement with a new client, never a silent extension.
Separation of duties
The flow is designed so no single person can give data away:
- The requester never reviews, approves or activates their own request.
- The custodian who reviews never approves.
- The DPO approves, and never their own request or one they reviewed.
- An administrator acting in a custodian's place is recorded as an override. There is no administrator override
for the DPO step.
These rules are in the code and covered by integration tests, not left to procedure.
Access ends with the agreement
Grants and the partner client carry the same end date as the agreement. A read after the end date is refused at once, even before the daily expiry job runs. Terminating an agreement revokes its grants and client immediately: the next call from the partner gets 401, and a ministry consumer gets 403.
Field minimisation on every read
A reader who is let in only by an agreement sees only the agreed fields, on every path: search, single record, lookup and change feed. In practice:
| Situation | Result |
|---|---|
| Agreed fields: company name and number | Founders, addresses and contacts are not returned at all |
| A record's label is made of agreed fields | The label is shown |
| A record's context uses a field outside the agreement | The context is not shown |
| A party-link search across registers | Registers the reader can read only partly are skipped |
A group field such as holder is agreed | Every field inside it is shared as clearance shows it; sensitive ones in full only when named |
The agreement's own API specification
Every agreement comes with its own OpenAPI file and a PDF of it, 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
A partner developer builds against that specification, gets a token with the client credentials grant, and calls the register routes with the registers:read scope. Each register also publishes its general specification with every field labelled by sensitivity (x-gsb-sensitivity).
Contacts are personal data
The agreement records contacts (manager, developer, DPO, signatory, technical contact). They are shown only to the parties and are never written to an audit row.
Across the federation
A node can read a register held on another installation with registers.list and registers.lookup. The register's home decides, and only under an agreement whose consumer type is node. The node sees only the agreed fields, and both sides audit the read without its text. A relay from one node to another through the hub is documented but not built.
Consented prefill: a citizen's own records
Separate from agreements, a citizen can fill an application from their own register records, when the installation switches it on (REGISTER_PREFILL=on; off by default). Only the applicant of their own draft can use it, their NRC must be verified by the identity provider, they tick an explicit consent (kept with its wording and time), and only public and internal fields are copied. Other people's identifiers in the same record (a co-founder's NRC, a previous owner) are never copied.
The Developer Hub is the intake, not the issuer
The Developer Hub's access request page collects requests for register data, Partner API clients and federation nodes. Its flow:
- The requester describes the register, organisation, purpose, legal basis, data items, volume, retention and
safeguards. A request for register data needs the Pamodzi Certified Data Steward certificate.
- A hub reviewer asks for more information or recommends approval or rejection, with a note.
- A hub data steward who is not the reviewer decides. Nobody handles their own request.
- The owning MDA then creates the actual agreement on the platform, through the flow above, with its own
custodian and DPO.
- The steward records the agreement or client reference on the hub request ("Access issued").
The hub never issues grants or credentials. If the hub says "approved" but no agreement is active on the platform, there is no access.
Example (synthetic)
Example Bank wants to check that a customer's company exists before opening an account.
- A developer at the bank requests register data on the Developer Hub: business register, fields "entity number,
name, status", legal basis "performance of a contract", retention 30 days.
- The hub reviewer recommends approval; a steward approves.
- The MDA's custodian creates the agreement on the platform, narrows the period to 12 months and sets retention to 30
days. The DPO approves; the agreement is signed and sealed.
- The custodian activates it. The client id is
DSA...with scoperegisters:read; the secret is shown once and thebank stores it in its secret store.
- The bank reads only those three fields. When the agreement ends, its next call is refused.
Check your understanding
- Which consumer types can an agreement have, and what does each receive on activation?
- Why can the custodian narrow but never widen a request?
- Who approves an agreement, and who may not approve it?
- What happens to a partner's calls the moment an agreement is terminated?
- What does the Developer Hub do with an approved access request, and what does it never do?
Sign in to record your progress.
Previous: Register packs, access levels and masks Next: Audit, access logs and usage