G2P Subsidy Sandbox API
The G2P Subsidy Sandbox API lets you build and test a government-to-person (G2P) cash-subsidy integration end to end — configuring a subsidy scheme, checking whether a citizen is eligible, and dispatching a disbursement — without touching a production payment rail or a real citizen registry.
Under the hood it fronts a real, self-hosted OpenG2P stack — PBMS (the program/eligibility registry), G2P Bridge, and example-bank (a mock digital-cash bank) — as an external upstream registered in the DIS API Catalogue, the same way Digi-Sign fronts its own signing backend. Eligibility checks resolve the citizen against SLUDI sandbox identities, so every beneficiary you work with is synthetic — no real citizen data is read or stored.
G2P Subsidy is onboarding onto the platform gateway. If it isn't yet visible in your API Catalog, ask the DIS platform team for early access — the flow and payloads below are the stable, final contract.
The journey at a glance
A scheme is configured once (typically by whoever plays the "government official" role in your integration) — this is what creates the underlying PBMS program along with its eligibility criteria and entitlement/benefit-code rows. Your application then drives the citizen-facing part of the flow: check eligibility (evaluated by the facade against the citizen's SLUDI attributes, not a live PBMS call), dispatch, poll for settlement, and read back the remaining quota.
Before you start
- A registered application in the Developer Portal, subscribed to the G2P Subsidy Sandbox API, with your
clientIdand API key. See My Applications if you haven't created one yet. - A SLUDI sandbox identity (a UIN) to check eligibility against. See the SLUDI integration guide if you need one.
Base URL & authentication
| Purpose | Value |
|---|---|
| Base URL | https://sgateway.dev.digieconcenter.gov.lk/g2p/v1.0.0 |
Every request needs the same two headers as any other sandbox API — see Gateway Errors if either is missing or rejected:
X-DIS-CLIENT-ID: YOUR_CLIENT_ID_HERE
X-DIS-API-KEY: YOUR_API_KEY_HERE
Content-Type: application/json
The examples below omit these headers for brevity — include them on every call.
Step 1 — Configure a scheme
A scheme is a synthetic subsidy program: a name, a currency and per-beneficiary benefit amount, a total quota, and an eligibilityCriteria object evaluated against each citizen's SLUDI attributes.
curl --location 'https://sgateway.dev.digieconcenter.gov.lk/g2p/v1.0.0/schemes' \
--header 'X-DIS-CLIENT-ID: YOUR_CLIENT_ID_HERE' \
--header 'X-DIS-API-KEY: YOUR_API_KEY_HERE' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Fertilizer Subsidy",
"description": "Per-season fertilizer subsidy for registered farmers",
"pbmsProgramId": "PROG-FERT-2026",
"currency": "LKR",
"benefitAmount": 20000.00,
"totalQuota": 2000000.00,
"eligibilityCriteria": {
"requiresLowIncomeFlag": true,
"minAge": 18
}
}'
{
"schemeId": "d5f1f0b0-402d-47b0-b9bd-94f9b01bf497",
"name": "Fertilizer Subsidy",
"pbmsProgramId": "PROG-FERT-2026",
"currency": "LKR",
"benefitAmount": 20000.00,
"totalQuota": 2000000.00,
"status": "ACTIVE",
"createdAt": "2026-09-17T09:12:04Z"
}
pbmsProgramId must be unique — reusing one from an existing scheme returns a 409 scheme_conflict. Fetch a scheme you've already created with GET /schemes/{schemeId}.
Step 2 — Check beneficiary eligibility
Pass a schemeId and a citizen's uin. The API resolves the citizen via SLUDI, links a beneficiary record on first sight, and evaluates the scheme's eligibilityCriteria against that citizen's attributes.
curl --location 'https://sgateway.dev.digieconcenter.gov.lk/g2p/v1.0.0/eligibility/check' \
--header 'X-DIS-CLIENT-ID: YOUR_CLIENT_ID_HERE' \
--header 'X-DIS-API-KEY: YOUR_API_KEY_HERE' \
--header 'Content-Type: application/json' \
--data-raw '{
"schemeId": "d5f1f0b0-402d-47b0-b9bd-94f9b01bf497",
"uin": "199012345678"
}'
{
"schemeId": "d5f1f0b0-402d-47b0-b9bd-94f9b01bf497",
"beneficiaryId": "60c00193-c3c9-4682-8506-273a03de4d38",
"eligible": true,
"entitlementAmount": 20000.00,
"currency": "LKR",
"reasons": []
}
{
"schemeId": "d5f1f0b0-402d-47b0-b9bd-94f9b01bf497",
"beneficiaryId": "60c00193-c3c9-4682-8506-273a03de4d38",
"eligible": false,
"reasons": ["not_low_income"]
}
An unrecognized UIN returns 404 with beneficiaryId_not_found — use it to test how your application handles an unknown citizen.
Step 3 — Dispatch a disbursement
Once a citizen is confirmed eligible, dispatch the disbursement with the beneficiaryId from Step 2. The API re-validates eligibility, reserves the amount against the scheme's quota, and hands off to G2P Bridge for settlement.
Pass an Idempotency-Key header so a retried request (e.g. after a timeout) doesn't reserve quota twice — replaying the same key with the same body returns the original disbursement instead of creating a new one.
curl --location 'https://sgateway.dev.digieconcenter.gov.lk/g2p/v1.0.0/disbursements' \
--header 'X-DIS-CLIENT-ID: YOUR_CLIENT_ID_HERE' \
--header 'X-DIS-API-KEY: YOUR_API_KEY_HERE' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: fert-disb-9876543210-2026s1' \
--data-raw '{
"schemeId": "d5f1f0b0-402d-47b0-b9bd-94f9b01bf497",
"beneficiaryId": "60c00193-c3c9-4682-8506-273a03de4d38",
"amount": 20000.00,
"currency": "LKR"
}'
{
"disbursementId": "a2e8d9e6-b12f-42e8-90ab-f516fe71efad",
"schemeId": "d5f1f0b0-402d-47b0-b9bd-94f9b01bf497",
"beneficiaryId": "60c00193-c3c9-4682-8506-273a03de4d38",
"amount": 20000.00,
"currency": "LKR",
"status": "PENDING"
}
Settlement is asynchronous and, for most financialAddress values, genuinely non-deterministic (it exercises a real mock bank pipeline). To reliably test your failure-handling logic, set financialAddress to any value ending in 0000 — that dispatch always settles FAILED, immediately, with failureReason: "SIMULATED_FAILURE: financial address ends in 0000". Any other value settles for real, typically within tens of seconds.
Step 4 — Poll for settlement
GET /disbursements/{disbursementId} is pull-through: while a disbursement is PENDING, each call checks live status with G2P Bridge and updates it in place. Poll until you see a terminal status.
curl --location 'https://sgateway.dev.digieconcenter.gov.lk/g2p/v1.0.0/disbursements/a2e8d9e6-b12f-42e8-90ab-f516fe71efad' \
--header 'X-DIS-CLIENT-ID: YOUR_CLIENT_ID_HERE' \
--header 'X-DIS-API-KEY: YOUR_API_KEY_HERE'
{
"disbursementId": "a2e8d9e6-b12f-42e8-90ab-f516fe71efad",
"status": "SUCCEEDED",
"failureReason": null,
"updatedAt": "2026-09-17T09:13:21Z"
}
| Status | Meaning |
|---|---|
PENDING | Reserved against quota, settlement in progress — poll again |
SUCCEEDED | Settled; the reserved amount is now committed against the scheme's quota |
FAILED | Settlement failed; the reserved amount is released back to the scheme's quota |
Step 5 — Read the remaining quota
curl --location 'https://sgateway.dev.digieconcenter.gov.lk/g2p/v1.0.0/schemes/d5f1f0b0-402d-47b0-b9bd-94f9b01bf497/quota' \
--header 'X-DIS-CLIENT-ID: YOUR_CLIENT_ID_HERE' \
--header 'X-DIS-API-KEY: YOUR_API_KEY_HERE'
{
"schemeId": "d5f1f0b0-402d-47b0-b9bd-94f9b01bf497",
"currency": "LKR",
"total": 2000000.00,
"reserved": 0.00,
"committed": 20000.00,
"used": 20000.00,
"remaining": 1980000.00
}
used = reserved (PENDING disbursements) + committed (SUCCEEDED disbursements); remaining = total - used.
Error scenarios
Every error follows the platform's standard [{ "errorCode", "httpStatus", "message" }] shape.
| HTTP Status | errorCode | When |
|---|---|---|
400 | bad_request | Malformed payload, or a required header/field is missing |
404 | scheme_not_found | The schemeId doesn't exist, or doesn't belong to your application |
404 | beneficiary_not_found | The uin has no matching SLUDI citizen |
409 | scheme_conflict | pbmsProgramId is already used by another scheme |
409 | quota_exhausted | The requested amount exceeds the scheme's remaining quota |
409 | ineligible_for_disbursement | The beneficiary fails eligibility on re-check at dispatch time |
Gateway-level errors (missing/invalid X-DIS-CLIENT-ID or X-DIS-API-KEY, rate limiting) follow the shared Gateway Errors reference.
Support
Contact the DIS platform team, or open an issue on the dis-g2p-subsidy-facade repository.