OAuth2 Clients
OAuth2 clients enable machine-to-machine authentication using the client credentials grant type. Create clients, manage their scopes and lifecycle, and generate access tokens for server-to-server integrations.
All /admin/clients endpoints require the admin:clients scope. The /oauth/token endpoint is publicly accessible with valid client credentials.
Get access token
Exchange client credentials for an access token. The request body must be form-encoded (application/x-www-form-urlencoded).
You can provide credentials in the request body or via a Basic Authorization header (base64-encoded client_id:client_secret).
Required attributes
- Name
grant_type- Type
- string
- Description
Must be
client_credentials.
- Name
client_id- Type
- string
- Description
The client ID (not required if using Basic auth header).
- Name
client_secret- Type
- string
- Description
The client secret (not required if using Basic auth header).
Optional attributes
- Name
scope- Type
- string
- Description
Space-separated list of scopes to request. Defaults to all scopes granted to the client.
Request
# Using form body
curl -X POST https://id.zb.co.zw/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=zbid_client_a1b2c3d4e5f6" \
-d "client_secret=your_client_secret" \
-d "scope=kyc:validate kyc:screen"
# Using Basic auth
curl -X POST https://id.zb.co.zw/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic BASE64_ENCODED_CLIENT_ID:CLIENT_SECRET" \
-d "grant_type=client_credentials"
Response
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 900,
"scope": "kyc:validate kyc:screen"
}
Create a client
Create a new OAuth2 client. The response includes a clientSecret that is only shown once. Store it securely immediately.
Required attributes
- Name
name- Type
- string
- Description
A human-readable name for the client (e.g., "Payment Gateway Service").
- Name
scopes- Type
- array
- Description
List of permission scopes granted to this client (e.g.,
["kyc:validate", "kyc:screen"]).
New clients are created with the client_credentials grant type.
Request
curl -X POST https://id.zb.co.zw/admin/clients \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "Central KYC Service",
"scopes": ["kyc:validate", "kyc:screen"]
}'
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"clientId": "zbid_client_a1b2c3d4e5f6",
"clientSecret": "zbid_secret_x9y8z7w6v5u4t3s2r1q0",
"name": "Central KYC Service",
"scopes": ["kyc:validate", "kyc:screen"],
"grantTypes": ["client_credentials"],
"status": "ACTIVE",
"rateLimitPerMinute": 60,
"createdAt": "2026-07-10T10:00:00Z"
}
The clientSecret is only returned when the client is first created. Store it in a secure location such as a secrets manager. If you lose it, you will need to rotate the secret.
List all clients
Retrieve a list of all OAuth2 clients. Client secrets are never included in list responses.
Request
curl https://id.zb.co.zw/admin/clients \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Payment Gateway Service",
"clientId": "zbid_client_a1b2c3d4e5f6",
"scopes": ["users:read", "users:write"],
"status": "ACTIVE",
"rateLimitPerMinute": 60,
"createdAt": "2026-05-31T10:00:00Z"
},
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Mobile Banking App",
"clientId": "zbid_client_g7h8i9j0k1l2",
"scopes": ["users:read"],
"status": "ACTIVE",
"rateLimitPerMinute": 120,
"createdAt": "2026-05-30T14:30:00Z"
}
]
Get a client
Retrieve a single OAuth2 client by its ID. The client secret is not included in the response.
Request
curl https://id.zb.co.zw/admin/clients/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Payment Gateway Service",
"clientId": "zbid_client_a1b2c3d4e5f6",
"scopes": ["users:read", "users:write"],
"status": "ACTIVE",
"rateLimitPerMinute": 60,
"createdAt": "2026-05-31T10:00:00Z"
}
Update a client
Update an existing OAuth2 client. You can modify the name, scopes, status, or rate limit. All fields are optional; only include the fields you want to change.
Optional attributes
- Name
name- Type
- string
- Description
Updated human-readable name for the client.
- Name
scopes- Type
- array
- Description
Updated list of permission scopes.
- Name
status- Type
- string
- Description
Client status. One of
ACTIVE,SUSPENDED, orREVOKED.
- Name
rateLimitPerMinute- Type
- integer
- Description
Per-client rate-limit value stored on the client record. Note: the client-credentials endpoint is currently enforced at a fixed 60 requests per minute per
client_id, so this value is recorded but does not yet change the enforced limit.
Request
curl -X PATCH https://id.zb.co.zw/admin/clients/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "Payment Gateway v2",
"scopes": ["users:read", "users:write", "kyc:read"],
"rateLimitPerMinute": 120
}'
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Payment Gateway v2",
"clientId": "zbid_client_a1b2c3d4e5f6",
"scopes": ["users:read", "users:write", "kyc:read"],
"status": "ACTIVE",
"rateLimitPerMinute": 120,
"createdAt": "2026-05-31T10:00:00Z"
}
Rotate client secret
Generate a new secret for an OAuth2 client. The previous secret is immediately invalidated. Store the new secret securely; it is only returned once.
This endpoint accepts no request body.
Request
curl -X POST https://id.zb.co.zw/admin/clients/550e8400-e29b-41d4-a716-446655440000/rotate-secret \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Payment Gateway Service",
"clientId": "zbid_client_a1b2c3d4e5f6",
"clientSecret": "zbid_secret_new_p0o9i8u7y6t5r4e3w2q1",
"scopes": ["users:read", "users:write"],
"status": "ACTIVE",
"rateLimitPerMinute": 60,
"createdAt": "2026-05-31T10:00:00Z"
}
After rotating a secret, all existing tokens issued with the old secret remain valid until they expire. Only new token requests require the updated secret.
Revoke a client
Revoke an OAuth2 client by setting its status to REVOKED. Revoked clients cannot request new tokens. Existing tokens issued to the client remain valid until they expire.
This endpoint accepts no request body.
Request
curl -X DELETE https://id.zb.co.zw/admin/clients/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Payment Gateway Service",
"clientId": "zbid_client_a1b2c3d4e5f6",
"scopes": ["users:read", "users:write"],
"status": "REVOKED",
"rateLimitPerMinute": 60,
"createdAt": "2026-05-31T10:00:00Z"
}