Users
Users represent individuals registered in the ZB ID system. Each user has a profile, a KYC verification tier, and an account status. A user can hold an email, a phone number, or both, and either one serves as a login channel. Authenticated users can view and update their own profiles, while administrators can look up and manage any user account.
The user model
The profile response contains the information associated with a registered account, including its login channels, verification stamps, KYC tier, status, and assigned roles.
Properties
- Name
id- Type
- string (UUID)
- Description
Unique identifier for the user. This is the value carried in the
subclaim of the user's tokens.
- Name
phone- Type
- string | null
- Description
The user's phone number (for example,
+263771234567). May benullif the account has only an email.
- Name
email- Type
- string | null
- Description
The user's email address. May be
nullif the account has only a phone.
- Name
firstName- Type
- string | null
- Description
The user's first name.
- Name
lastName- Type
- string | null
- Description
The user's last name.
- Name
kycTier- Type
- string
- Description
The user's KYC verification level. One of
NONE,BASIC,STANDARD, orENHANCED.
- Name
status- Type
- string
- Description
The current account status. One of
ACTIVE,SUSPENDED,LOCKED, orDEACTIVATED.
- Name
roles- Type
- array
- Description
Roles assigned to the user, each with an id, name, description, and optional subsidiary scope.
- Name
createdAt- Type
- string (ISO 8601)
- Description
Timestamp of when the account was created.
- Name
emailVerifiedAt- Type
- string (ISO 8601) | null
- Description
When the current email was verified, or
nullif unverified. Changing the email resets this tonull.
- Name
phoneVerifiedAt- Type
- string (ISO 8601) | null
- Description
When the current phone was verified, or
nullif unverified. Changing the phone resets this tonull.
User profile object
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"phone": "+263771234567",
"email": "[email protected]",
"firstName": "Tendai",
"lastName": "Moyo",
"kycTier": "BASIC",
"status": "ACTIVE",
"roles": [
{
"id": "a0000000-0000-0000-0000-000000000001",
"name": "customer",
"description": "Standard retail customer",
"subsidiaryScope": null
}
],
"createdAt": "2026-05-15T08:30:00Z",
"emailVerifiedAt": "2026-05-16T09:00:00Z",
"phoneVerifiedAt": null
}
KYC tiers:
NONE- No verification completedBASIC- National ID validated against the e-Gov registrySTANDARD- Intermediate verificationENHANCED- Full verification
Get current user
Retrieve the profile of the currently authenticated user. Requires a valid Bearer token.
Request
curl https://id.zb.co.zw/users/me \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"phone": "+263771234567",
"email": "[email protected]",
"firstName": "Tendai",
"lastName": "Moyo",
"kycTier": "BASIC",
"status": "ACTIVE",
"roles": [
{
"id": "a0000000-0000-0000-0000-000000000001",
"name": "customer",
"description": "Standard retail customer",
"subsidiaryScope": null
}
],
"createdAt": "2026-05-15T08:30:00Z",
"emailVerifiedAt": "2026-05-16T09:00:00Z",
"phoneVerifiedAt": null
}
Read your own profile
Uses the token from your last sign-in on the Authentication page. Returns the profile of the signed-in identity. With no token it returns 401.
Runs against the ZB ID STAGING sandbox (id-staging.zb.co.zw). Register a throwaway test account; never use real credentials.
Update current user
Update the profile of the currently authenticated user. Only the fields you include are changed. This endpoint can also add, change, or remove login channels.
Optional attributes
- Name
firstName- Type
- string
- Description
Updated first name.
- Name
lastName- Type
- string
- Description
Updated last name.
- Name
email- Type
- string
- Description
Set or change the email. Must be a valid email address. Stored lowercased and trimmed.
- Name
phone- Type
- string
- Description
Set or change the phone. Must match
^\+?[0-9]{10,15}$.
- Name
removeEmail- Type
- boolean
- Description
When
true, removes the email from the account. Defaults tofalse.
- Name
removePhone- Type
- boolean
- Description
When
true, removes the phone from the account. Defaults tofalse.
Channel semantics
- Setting an identifier that already belongs to another user returns
409 CONFLICT. - Changing an identifier to a new value resets its verified stamp (
emailVerifiedAtorphoneVerifiedAt) tonull. Submitting the identifier's current value is a no-op and leaves the stamp untouched. - Setting and removing the same channel in one request (for example,
emailplusremoveEmail: true) returns400 BAD_REQUESTwithCannot set and remove the same identifier. - Removing your last remaining login identifier returns
400 BAD_REQUESTwithCannot remove your only login identifier. A user must always keep at least one of email or phone.
Request
curl -X PATCH https://id.zb.co.zw/users/me \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"lastName": "Moyo-Ncube",
"email": "[email protected]"
}'
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"phone": "+263771234567",
"email": "[email protected]",
"firstName": "Tendai",
"lastName": "Moyo-Ncube",
"kycTier": "BASIC",
"status": "ACTIVE",
"roles": [
{
"id": "a0000000-0000-0000-0000-000000000001",
"name": "customer",
"description": "Standard retail customer",
"subsidiaryScope": null
}
],
"createdAt": "2026-05-15T08:30:00Z",
"emailVerifiedAt": null,
"phoneVerifiedAt": null
}
Conflict (409)
{
"error": "CONFLICT",
"message": "Email already registered to another account, log in with that email instead",
"status": 409,
"timestamp": "2026-07-10T10:21:00.321Z"
}
Removing your only identifier (400)
{
"error": "BAD_REQUEST",
"message": "Cannot remove your only login identifier",
"status": 400,
"timestamp": "2026-07-10T10:22:00.111Z"
}
To remove a channel, send { "removePhone": true } or { "removeEmail": true }. Changing the email in the example above cleared emailVerifiedAt.
Get user by ID
Retrieve a user by their unique ID. This endpoint requires the admin:users scope.
Request
curl https://id.zb.co.zw/users/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"phone": "+263771234567",
"email": "[email protected]",
"firstName": "Tendai",
"lastName": "Moyo",
"kycTier": "BASIC",
"status": "ACTIVE",
"roles": [
{
"id": "a0000000-0000-0000-0000-000000000001",
"name": "customer",
"description": "Standard retail customer",
"subsidiaryScope": null
}
],
"createdAt": "2026-05-15T08:30:00Z",
"emailVerifiedAt": "2026-05-16T09:00:00Z",
"phoneVerifiedAt": null
}
Look up user by phone
Look up a user by their phone number. The phone number must be URL-encoded (for example, %2B263771234567 for +263771234567). This endpoint requires the admin:users scope.
Request
curl https://id.zb.co.zw/users/phone/%2B263771234567 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"phone": "+263771234567",
"email": "[email protected]",
"firstName": "Tendai",
"lastName": "Moyo",
"kycTier": "BASIC",
"status": "ACTIVE",
"roles": [
{
"id": "a0000000-0000-0000-0000-000000000001",
"name": "customer",
"description": "Standard retail customer",
"subsidiaryScope": null
}
],
"createdAt": "2026-05-15T08:30:00Z",
"emailVerifiedAt": "2026-05-16T09:00:00Z",
"phoneVerifiedAt": null
}
Update user status
Update the account status of a user. This endpoint requires the admin:users scope. Use it to suspend, lock, reactivate, or deactivate accounts.
Required attributes
- Name
status- Type
- string
- Description
The new account status. One of
ACTIVE,SUSPENDED,LOCKED, orDEACTIVATED.
- Name
reason- Type
- string
- Description
Optional. A description of why the status is changing, stored for audit purposes.
Setting the status to SUSPENDED or DEACTIVATED revokes all of the user's active sessions. Setting it back to ACTIVE clears the failed-attempt counter and any lock. The response is a confirmation message, not the full user object.
Request
curl -X PATCH https://id.zb.co.zw/users/550e8400-e29b-41d4-a716-446655440000/status \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"status": "SUSPENDED",
"reason": "Suspicious activity detected on account"
}'
Response
{
"message": "User status updated to SUSPENDED"
}
Suspending or deactivating an account immediately revokes its sessions. Reactivating an account (ACTIVE) resets its failed-login counter and clears any lock.