GSB e-Services partner API
Version 1.0.0 25 operations Download the OpenAPI file
Authenticate with OAuth 2.0 client credentials: POST /oauth/token with your client ID and secret (HTTP Basic or form fields) to get a 15-minute bearer token, then call the API with Authorization: Bearer <token>. Each client has its own scopes, MDA and register scope, address allow-list, per-minute rate limit and daily quota; 429 answers carry Retry-After. Errors are RFC 7807 problem documents with a stable code and a requestId. Webhooks are signed: X-GSB-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>. Reject a message whose t is more than 5 minutes old; during a secret rotation two v1 values are sent and either may match. Deliveries are at least once: drop duplicates by the event id.
Base address: /api/v1
Authentication
POST /oauth/token
Get an access token (client credentials)
No authentication.
Request body (required)
application/x-www-form-urlencoded:TokenRequestapplication/json:TokenRequest
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json TokenResponse |
400 | Unsupported grant type. | application/json OAuthError |
401 | Unknown client, wrong secret, or the client is not active. | application/json OAuthError |
403 | The address is not on the client's allow-list. | application/json OAuthError |
429 | Too many failed attempts from this address. | application/json OAuthError |
500 | Server error. | application/json OAuthError |
GET /me
The calling client, its scopes and limits
Authentication: clientCredentials
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json Me |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Catalogue
GET /services
Published services
Authentication: clientCredentials: services:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
mdaId | query | string (uuid) | Only this MDA's services |
limit | query | integer | 1-500 (100) |
offset | query | integer | Skip this many |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json ServiceList |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /services/{serviceId}
One published service: passport, fees, required documents, steps
Authentication: clientCredentials: services:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
serviceId required | path | string (uuid) | Service id |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json ServiceDetail |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Permits
GET /permits/verify/{code}
Verify a permit, licence or certificate by its verification code or number
Authentication: clientCredentials: permits:verify
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code required | path | string | Verification code (QR) or permit number |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json PermitVerification |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /verify/{documentNumber}
Verify any document: this platform, a peer node, or a legacy ministry (issuer=<code>) - one answer
Answers 404 with reason not_found only when no source knows the document, 503 when a source could not be asked (never a false not_found), 409 with reason ambiguous when two nodes hold the number (give issuer), 429 (Retry-After) over the federated-check ceilings. On the national hub a document of a node is asked of that node (lib/federation/verifyLookup).
Authentication: clientCredentials: permits:verify
Parameters
| Name | In | Type | Description |
|---|---|---|---|
documentNumber required | path | string | Issued number or verification code |
issuer | query | string | The issuing ministry (short name) or node key: on the hub only that node is asked; a legacy ministry (VERIFY_HUB_ZAMPOINTS) is asked through its ZamPoint, e.g. ZEMA |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json HubVerification |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
POST /verify/documents
Bulk verification: codes and PDFs, each answered like the "verify a document" page of the portal
Codes need the permits:verify scope, PDFs documents:validate; an item the client may not check gets its own 403. PDFs are validated (seal, time-stamp, changes, issued record, lifecycle) and not kept.
Authentication: clientCredentials: permits:verify; clientCredentials: documents:validate
Request body (required)
application/json:BulkVerifyRequest
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json BulkVerifyResponse |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /permits/{code}/uses
Whether a certificate can be used now, what is left of its quantity, and its uses
Only certificates of the ministries in the MDA scope of the client; anything else answers 404 like an unknown code.
Authentication: clientCredentials: permits:consume
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code required | path | string | Verification code or certificate number |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json CertificateUses |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
POST /permits/{code}/uses
Record a use of a certificate (quantity drawn down, place, consignment)
Send Idempotency-Key. A certificate that is not in force, is used up, or has less left than asked is refused (409, nothing recorded). Every use is audited and shown to the holder.
Authentication: clientCredentials: permits:consume
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code required | path | string | Verification code or certificate number |
Idempotency-Key required | header | string | 8 to 80 letters, digits or . _ : - (a UUID is ideal); keep it when you retry. |
Request body (required)
application/json:CertificateUseRequest
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json CertificateUseRecorded |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Registers
GET /registers
Registers this client may read
Authentication: clientCredentials: registers:read
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json RegisterList |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /registers/{code}/lookup
Search a register by label or key prefix (at most 50)
Authentication: clientCredentials: registers:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code required | path | string | Register code; write / as __ |
q required | query | string | At least 2 characters |
limit | query | integer | 1-50 (20) |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json RegisterLookup |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /registers/{code}/entries/{key}
One register entry by key
A key containing / (an NRC) cannot travel in the path through the gateway: use /registers/{code}/entries?key= instead.
Authentication: clientCredentials: registers:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code required | path | string | Register code; write / as __ |
key required | path | string | Entry key |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json RegisterEntry |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /registers/{code}/entries
One register entry by key, the key in the query string (keys with /, such as an NRC)
Authentication: clientCredentials: registers:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code required | path | string | Register code; write / as __ |
key required | query | string | Entry key, URL-encoded |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json RegisterEntry |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /registers/{code}/changes
What changed in a register since a cursor, deletions included (replay from the beginning with no cursor)
Oldest first. Each change carries the entry as it stands now, projected for the client like /entries; deleted and tombstoned entries come as state "removed". Keep nextCursor and send it next time; while more is true, ask again. The answer is signed (X-GSB-JWS, ES256, detached, over the body bytes; keys in /.well-known/jwks.json). Every call is audited.
Authentication: clientCredentials: registers:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code required | path | string | Register code; write / as __ |
cursor | query | string | nextCursor of the previous answer; empty = from the beginning |
limit | query | integer | 1-1000 (100) |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json RegisterChanges |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /parties/{type}/{value}/links
The register entries an identifier appears in (companies directed, vehicles owned, parcels held), in the register scope of the client
type: nrc, tpin, passport, entity-number, plate, property-no, title-no, permit-no, zampass-id or any. An identifier containing / (an NRC) cannot travel in the path through the gateway: use /parties/{type}/links?value= instead. Every lookup is audited.
Authentication: clientCredentials: registers:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
type required | path | string | Identifier type |
value required | path | string | The identifier |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json PartyLinks |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /parties/{type}/links
The register entries an identifier appears in, the identifier in the query string (an NRC)
Authentication: clientCredentials: registers:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
type required | path | string | Identifier type |
value required | query | string | The identifier, URL-encoded |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json PartyLinks |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Applications
GET /cases/{caseNumber}/status
Where an application stands (cases of the client's MDAs only)
No personal data is returned.
Authentication: clientCredentials: cases:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
caseNumber required | path | string | The application number |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json CaseStatus |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Events
GET /events
The event catalogue
Authentication: clientCredentials: events:subscribe
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json EventCatalogue |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /webhooks
This client's webhook subscriptions (administrators create them)
Authentication: clientCredentials: events:subscribe
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json SubscriptionList |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Audit
GET /audit/events
Audit events about applications of the client's MDAs, oldest first, from a sequence number on
Replay: pass the last sequence you stored as after. Events carry identifiers, roles at the time and the marking - never names, addresses or before / after values. Applications whose marking may not be exposed to partner systems are left out.
Authentication: clientCredentials: audit:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
after | query | integer | Only events with a higher sequence (0: from the start) |
limit | query | integer | 1-500 (100) |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json AuditEventPage |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Geodata
GET /geo/feeds
The GeoJSON feeds this platform publishes
Authentication: clientCredentials: geo:read
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json GeoFeedList |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
GET /geo/feeds/{key}
One feed as a GeoJSON FeatureCollection, paged
Answers application/geo+json with an ETag: poll with If-None-Match. Follow links[rel=next] for the next page.
Authentication: clientCredentials: geo:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
key required | path | string | Feed key, e.g. forestry.licensed-areas |
limit | query | integer | 1-2000 (1000) |
offset | query | integer | Skip this many |
bbox | query | string | minLon,minLat,maxLon,maxLat (WGS 84) |
updatedSince | query | string (date-time) | Only features changed since (ISO 8601) |
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/geo+json GeoFeatureCollection |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Legacy consumers
POST /parties/associated-entities
Organisations a person (by NRC) represents
Replaces ZIGS GET /Corporate/GetAssociatedEntities?nrc= (ZamPass portal). Active, approved mandates only.
Authentication: clientCredentials: parties:read
Request body (required)
application/json:NrcQuery
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json AssociatedEntities |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
POST /fines/search
Verify a fine, or list the fines of a person
Replaces ZIGS /Fines/VerifyById, /Fines/Search and /Fines/GetFinesHistoryByNRC (ZamMobile), read-only. Needs the fines register (FINES_REGISTER_CODE) in the register scope of the client; 404 when it is not.
Authentication: clientCredentials: fines:read
Request body (required)
application/json:FineQuery
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json FineList |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
POST /ussd/cases/lookup
Status and invoice of an application, for the phone of its applicant
Replaces ZIGS /USSD/GetCase and the read half of /USSD/CasePayment (Zamtel USSD gateway). Cases of the MDAs of the client only; a phone number that is not on the application answers 404. The service directory is the public GET /api/ussd/departments.
Authentication: clientCredentials: ussd:gateway
Request body (required)
application/json:UssdCaseQuery
Responses
| Status | Description | Body |
|---|---|---|
200 | OK | application/json UssdCase |
400 | The request is not valid (code VALIDATION_FAILED). | application/json Problem |
401 | No token, an invalid or expired token, or the client is suspended / revoked / expired (TOKEN_REQUIRED, INVALID_TOKEN, CLIENT_INACTIVE, CLIENT_EXPIRED). | application/json Problem |
403 | The token lacks the scope (INSUFFICIENT_SCOPE), the address is not on the client's allow-list (IP_NOT_ALLOWED), or the client has no MDA scope (MDA_SCOPE_REQUIRED). | application/json Problem |
404 | Not found, or outside the client's scope (the two are not distinguished). | application/json Problem |
429 | The client's per-minute limit or daily quota is used up (RATE_LIMITED, QUOTA_EXCEEDED). Wait Retry-After seconds. | application/json Problem |
500 | Something failed on our side; quote requestId. | application/json Problem |
Webhooks
The platform sends these events to your subscribed address.
EVENT case.submitted
An application was submitted to the office.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT case.status_changed
An application moved to a new stage the applicant can see.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT case.returned
An application was returned to the applicant for action.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT case.decided
An application was approved or rejected.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT case.completed
EVENT payment.invoiced
A fee was requested for an application.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT payment.confirmed
A payment for an application was confirmed.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT permit.issued
A permit, licence or certificate was issued.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT permit.status_changed
A permit was suspended, reinstated, cancelled or revoked.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT service.published
A new version of a service was published to the catalogue.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT webhook.test
A test message sent from the back office.
Request body (required)
application/cloudevents+json:CloudEvent
EVENT platform.module-changed
An optional module was switched on or off, or assigned to other ministries (MOD-02).
Request body (required)
application/cloudevents+json:CloudEvent
EVENT forestry.licence.issued
EVENT forestry.licence.expired
EVENT forestry.licence.suspended
EVENT forestry.licence.revoked
EVENT forestry.licence.reinstated
EVENT forestry.checkpoint.scanned
Schemas
Problem
RFC 7807 problem details, plus the platform's message / code / requestId. Act on code, never on the text.
| Field | Type | Description |
|---|---|---|
type | string (uri) | |
title | string | |
status required | integer | |
code required | string | |
detail | string | |
message required | string | |
requestId | string | Quote this to support. |
instance | string | The path of the request this answers (never its query string). |
OAuthError
| Field | Type | Description |
|---|---|---|
error required | string: invalid_client, unsupported_grant_type, access_denied, slow_down, server_error | |
error_description | string | |
requestId | string |
TokenRequest
| Field | Type | Description |
|---|---|---|
grant_type required | any | |
client_id | string | |
client_secret | string | |
scope | string | Space-separated subset of the client's scopes; omit for all of them. |
TokenResponse
| Field | Type | Description |
|---|---|---|
access_token required | string | |
token_type required | any | |
expires_in required | integer | |
scope | string | |
warning | string |
Me
| Field | Type | Description |
|---|---|---|
clientId | string | |
name | string | |
environment | string: sandbox, production | |
scopes | array of string: services:read, permits:verify, documents:validate, registers:read, cases:read, events:subscribe, audit:read, geo:read, legacy:documents, legacy:data-exchange, legacy:payment-callback, legacy:notify, parties:read, fines:read, ussd:gateway, permits:consume | |
mdaScope | array of string (uuid) | |
registerScope | array of string | |
rateLimitPerMin | integer | |
dailyQuota | integer | null |
Mda
| Field | Type | Description |
|---|---|---|
id | string (uuid) | |
name | string | |
shortName | string | null |
Service
| Field | Type | Description |
|---|---|---|
id required | string (uuid) | |
name required | string | |
description | string | null | |
type | string | null | |
mdaId | string | null (uuid) | |
mda | Mda | |
fee | string | null | |
processingTime | string | null | |
validity | string | null | |
version | integer | null | The published version number. |
updatedAt | string (date-time) |
ServiceList
| Field | Type | Description |
|---|---|---|
total | integer | |
limit | integer | |
offset | integer | |
services | array of Service |
ServiceDetail
Type: Service & object
PermitVerification
| Field | Type | Description |
|---|---|---|
valid required | boolean | true only when the permit exists, is active and within its validity. |
permitNumber | string | |
title | string | null | |
status | string | |
caseType | string | null | |
issuedAt | string | null (date-time) | |
validFrom | string | null (date-time) | |
validUntil | string | null (date-time) | |
holder | string | null | Initials and surname only. |
holderIdentifier | string | null | Masked. |
issuer | string | null | |
service | string | null | |
verifiedAt | string (date-time) | |
backCaptured | boolean | A historical paper permit recorded by the office (LP-ZIGS-14). Until a second officer validates it, its status is pending-validation and valid is false. |
CertificateUseRequest
Send an Idempotency-Key header: the same key with the same body is recorded once (a repeat answers 200 with replayed: true); the same key with another body is refused (422 IDEMPOTENCY_KEY_REUSED).
| Field | Type | Description |
|---|---|---|
quantity | number | Required when the certificate was granted for a quantity (authorised is not null); at most three decimals. |
unit | string | Optional; when given it must be the unit of the certificate. |
reference required | string | What it was used for: the consignment, declaration or entry number. |
place required | string | The border post, port or checkpoint. |
officerRef | string | The service number of your officer (never shown to the holder). |
usedAt | string (date-time) | When it was used (default: now; never in the future). |
note | string |
CertificateUse
| Field | Type | Description |
|---|---|---|
id | string (uuid) | |
quantity | number | null | |
unit | string | null | |
reference | string | |
place | string | |
usedAt | string (date-time) | |
recordedBy | string | The agency that recorded it. |
channel | string: api, office | |
status | string: recorded, reversed | |
officerRef | string | null |
CertificateUses
Whether the certificate can be used now, how much of its authorised quantity is left, and its uses (newest first).
| Field | Type | Description |
|---|---|---|
permit | PermitVerification | |
usable | boolean | |
reason | string | null | |
authorised | number | null | null: the certificate has no quantity; uses are recorded as a log. |
unit | string | null | |
used | number | null | |
remaining | number | null | |
singleUse | boolean | |
usedUp | boolean | |
count | integer | |
uses | array of CertificateUse |
CertificateUseRecorded
201 on a new use, 200 with replayed: true on a repeat with the same Idempotency-Key. 409 CERTIFICATE_NOT_VALID / CERTIFICATE_NOT_YET_VALID / CERTIFICATE_USED_UP / QUANTITY_EXCEEDED (remaining, requested, unit) when it cannot be used.
| Field | Type | Description |
|---|---|---|
use | CertificateUse | |
authorised | number | null | |
used | number | null | |
remaining | number | null | |
unit | string | null | |
usedUp | boolean | |
replayed | boolean |
HubVerification
The national verification hub (LP-INT-06): the same answer for a document of this platform, of a peer node or of a legacy ministry ZamPoint.
| Field | Type | Description |
|---|---|---|
found required | boolean | |
valid required | boolean | true only when the document exists and is valid now. |
status | string | null | |
reason required | string,null: null, expired, revoked, suspended, cancelled, not_valid, not_found, ambiguous | ambiguous (409): two nodes hold a document with this number - give issuer. |
documentNumber | string | |
title | string | null | |
issuer | object | null | |
issuedAt | string | null | |
validUntil | string | null | |
holderMasked | string | null | Initials and surname only; null for a legacy ministry. |
source | string,null: null, local, federation, zampoint | |
checkedAt | string (date-time) | |
node | object | source federation: the node that answered (lane verifyhub). |
BulkVerifyRequest
| Field | Type | Description |
|---|---|---|
items required | array of object | At most VERIFY_BULK_MAX_ITEMS (20). A code needs permits:verify, a PDF documents:validate. |
VerificationResult
One verification answer (lib/verification/result.js): seal validity and document status side by side.
| Field | Type | Description |
|---|---|---|
outcome | string: valid, warning, invalid, unknown, not-signed | |
headline | string | |
points | array of object | |
seal | object | null | |
changed | boolean | null | |
record | object | null | The issued record the file matches - never holder data. |
signatures | array of object | |
technical | object |
BulkVerifyResponse
| Field | Type | Description |
|---|---|---|
results | array of object | |
checkedAt | string (date-time) | |
id | string |
RegisterList
| Field | Type | Description |
|---|---|---|
registers | array of object |
RegisterEntry
| Field | Type | Description |
|---|---|---|
register | string | |
key | string | |
label | string | |
context | string | null | |
data | object | null | On a typed register: the record as the register pack describes it, only the fields the scope of the client clears. |
masked | array of string | Typed registers: pack paths shown masked. |
withheld | array of string | Typed registers: pack paths left out. |
schema | object | |
updatedAt | string (date-time) |
PartyLinks
| Field | Type | Description |
|---|---|---|
type | string | |
links | array of object |
RegisterChanges
Sent as canonical JSON (keys sorted, no white space) and signed: the X-GSB-JWS header is a detached compact JWS (ES256) over those exact bytes; the key is in /.well-known/jwks.json (by kid).
| Field | Type | Description |
|---|---|---|
register | string | |
cursor | string | The cursor asked with. |
nextCursor | string | Send it as ?cursor= next time; it never goes back. |
more | boolean | true: ask again at once, there is more. |
changes | array of object |
RegisterLookup
| Field | Type | Description |
|---|---|---|
register | string | |
results | array of object |
CaseStatus
| Field | Type | Description |
|---|---|---|
caseNumber required | string | |
status required | string | The internal status code. |
statusLabel | string | The words the applicant sees. |
decision | string,null: approved, rejected, null | |
service | object | |
submittedAt | string (date-time) | |
dueAt | string | null (date-time) | |
updatedAt | string (date-time) |
GeoFeedList
| Field | Type | Description |
|---|---|---|
feeds required | array of object |
GeoFeatureCollection
GeoJSON (RFC 7946), WGS 84 longitude / latitude. Paged like OGC API - Features: follow the link with rel "next".
| Field | Type | Description |
|---|---|---|
type required | any | |
name | string | |
crs | object | |
numberMatched | integer | null | |
numberReturned required | integer | |
features required | array of object | |
links required | array of object |
AuditEventPage
| Field | Type | Description |
|---|---|---|
events required | array of object | |
nextAfter required | integer | Pass as |
more | boolean |
EventType
| Field | Type | Description |
|---|---|---|
type | string | |
description | string | |
fields | array of string |
EventCatalogue
| Field | Type | Description |
|---|---|---|
events | array of EventType |
SubscriptionList
| Field | Type | Description |
|---|---|---|
subscriptions | array of object |
CloudEvent
CloudEvents 1.0, structured JSON mode. Identifiers and statuses only - fetch details with your own token.
| Field | Type | Description |
|---|---|---|
specversion required | any | |
id required | string (uuid) | The same on every retry and replay: use it to drop duplicates. |
source required | string | |
type required | string | |
subject | string | |
time required | string (date-time) | |
datacontenttype | any | |
data required | object |
NrcQuery
The NRC travels in the body, never the URL.
| Field | Type | Description |
|---|---|---|
nrc required | string |
AssociatedEntities
Organisations the person is an active, approved representative of. Field names follow the legacy ZIGS Corporate/GetAssociatedEntities answer.
| Field | Type | Description |
|---|---|---|
entities | array of object | |
source | any |
FineQuery
Either fineId or nrc. Personal identifiers travel in the body, never the URL.
| Field | Type | Description |
|---|---|---|
fineId | string | |
nrc | string |
FineList
Fines from the fines register (no names, NRCs or officer identities).
| Field | Type | Description |
|---|---|---|
register | string | |
fines | array of object |
UssdCaseQuery
| Field | Type | Description |
|---|---|---|
caseNumber required | string | |
msisdn required | string | The number the citizen dials from (260...); must be the one on the application. |
UssdCase
| Field | Type | Description |
|---|---|---|
caseNumber | string | |
status | string | |
statusLabel | string | |
service | object | |
invoice | object | null | |
updatedAt | string (date-time) |