API reference
Members
Members (patients) the partner shares with the clinic, keyed by the partner's own id. 5 operations under /public/v1, with parameters, request bodies and example responses.
Paths are relative to the API host: https://sandbox-api.clivehealth.app for the sandbox, https://api.clivehealth.app for production. Send Authorization: Bearer <token> on every request (Getting started).
Operations
- GET
/public/v1/membersList members - POST
/public/v1/membersCreate or update a member by external id - GET
/public/v1/members/{id}Get a member - PATCH
/public/v1/members/{id}Update a member - GET
/public/v1/members/by-membership/{membership_no}Find a member by membership number
List members
/public/v1/membersScope members:readOperation listMembers
Active and inactive members, ordered by updated_at then id.
Requires scope members:read.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
limit | query | integer | Page size, 1 to 200. Default 50. |
cursor | query | string | Opaque cursor from the previous page's next_cursor. |
updated_since | query | string (date-time) | ISO 8601 timestamp: only records updated at or after it. Lists are ordered by updated_at then id, so this plus cursor is a change feed. |
membership_no | query | string | Exact membership number. |
status | query | "active" | "inactive" |
Responses
200A page of members.Returns MemberPage.
| Field | Type | Description |
|---|---|---|
datarequired | array of Member | |
idrequired | string (uuid) | Clive member id. |
statusrequired | "active" | "inactive" | |
full_namerequired | string or null | |
phonerequired | string or null | |
emailrequired | string or null | |
date_of_birthrequired | string or null | YYYY-MM-DD. |
identity_typerequired | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | null | What identity_number is: MyKad, passport, ... |
identity_numberrequired | string or null | IC or passport number. |
membershipsrequired | array of Membership | |
providerrequired | string | Partner system the id belongs to, e.g. partner_v1. |
external_idrequired | string | The member's id in that system. |
membership_norequired | string or null | Membership or card number, when the partner has one. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
next_cursorrequired | string or null | Pass as cursor to fetch the next page; null on the last page. |
has_morerequired | boolean |
{
"data": [
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"status": "active",
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678",
"memberships": [
{
"provider": "partner_v1",
"external_id": "MEM-0012345",
"membership_no": "PM00012345"
}
],
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}
],
"next_cursor": null,
"has_more": false
}| Status | Meaning |
|---|---|
| 400 | Malformed request or invalid cursor. |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 422 | Validation failed (VALIDATION_ERROR). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.
Create or update a member by external id
/public/v1/membersScope members:writeOperation upsertMember
Keyed on (provider, external_id): creates the member the first time and updates it afterwards. Returns the Clive member id. PII is encrypted at rest.
Requires scope members:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Keyrequired | header | string | Unique key for this operation (a UUID is a good choice). Retrying with the same key and request replays the first response for 24 hours. |
Request body MemberUpsert
| Field | Type | Description |
|---|---|---|
providerrequired | string | Your system's provider code, e.g. partner_v1. |
external_idrequired | string | The member's id in your system; the upsert key with provider. |
membership_no | string or null | Membership or card number. Omit to keep the current one; null clears it. |
full_namerequired | string | |
phone | string or null | |
email | string (email) or null | |
date_of_birth | string or null | |
identity_type | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | Inferred for a 12-digit MyKad when omitted. |
identity_number | string or null |
{
"provider": "partner_v1",
"external_id": "MEM-0012345",
"membership_no": "PM00012345",
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678"
}Responses
200An existing member was updated.Returns Member.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | Clive member id. |
statusrequired | "active" | "inactive" | |
full_namerequired | string or null | |
phonerequired | string or null | |
emailrequired | string or null | |
date_of_birthrequired | string or null | YYYY-MM-DD. |
identity_typerequired | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | null | What identity_number is: MyKad, passport, ... |
identity_numberrequired | string or null | IC or passport number. |
membershipsrequired | array of Membership | |
providerrequired | string | Partner system the id belongs to, e.g. partner_v1. |
external_idrequired | string | The member's id in that system. |
membership_norequired | string or null | Membership or card number, when the partner has one. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"status": "active",
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678",
"memberships": [
{
"provider": "partner_v1",
"external_id": "MEM-0012345",
"membership_no": "PM00012345"
}
],
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}201A new member was created.Returns Member.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | Clive member id. |
statusrequired | "active" | "inactive" | |
full_namerequired | string or null | |
phonerequired | string or null | |
emailrequired | string or null | |
date_of_birthrequired | string or null | YYYY-MM-DD. |
identity_typerequired | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | null | What identity_number is: MyKad, passport, ... |
identity_numberrequired | string or null | IC or passport number. |
membershipsrequired | array of Membership | |
providerrequired | string | Partner system the id belongs to, e.g. partner_v1. |
external_idrequired | string | The member's id in that system. |
membership_norequired | string or null | Membership or card number, when the partner has one. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"status": "active",
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678",
"memberships": [
{
"provider": "partner_v1",
"external_id": "MEM-0012345",
"membership_no": "PM00012345"
}
],
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}| Status | Meaning |
|---|---|
| 400 | Malformed request, invalid cursor, or missing Idempotency-Key (IDEMPOTENCY_KEY_REQUIRED). |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 409 | Conflict, or a request with the same Idempotency-Key is still in flight (IDEMPOTENCY_IN_PROGRESS). |
| 422 | Validation failed (VALIDATION_ERROR), or the Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.
Get a member
/public/v1/members/{id}Scope members:readOperation getMember
Requires scope members:read.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string (uuid) | Clive member id. |
Responses
200The member.Returns Member.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | Clive member id. |
statusrequired | "active" | "inactive" | |
full_namerequired | string or null | |
phonerequired | string or null | |
emailrequired | string or null | |
date_of_birthrequired | string or null | YYYY-MM-DD. |
identity_typerequired | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | null | What identity_number is: MyKad, passport, ... |
identity_numberrequired | string or null | IC or passport number. |
membershipsrequired | array of Membership | |
providerrequired | string | Partner system the id belongs to, e.g. partner_v1. |
external_idrequired | string | The member's id in that system. |
membership_norequired | string or null | Membership or card number, when the partner has one. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"status": "active",
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678",
"memberships": [
{
"provider": "partner_v1",
"external_id": "MEM-0012345",
"membership_no": "PM00012345"
}
],
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}| Status | Meaning |
|---|---|
| 400 | Malformed request or invalid cursor. |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 404 | No such record in this clinic (NOT_FOUND). |
| 422 | Validation failed (VALIDATION_ERROR). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.
Update a member
/public/v1/members/{id}Scope members:writeOperation updateMember
Requires scope members:write.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string (uuid) | Clive member id. |
Idempotency-Key | header | string | Unique key for this operation (a UUID is a good choice). Retrying with the same key and request replays the first response for 24 hours. |
Request body MemberPatch
Only the fields sent are changed; null clears an optional field.
| Field | Type | Description |
|---|---|---|
full_name | string | |
phone | string or null | |
email | string (email) or null | |
date_of_birth | string or null | |
identity_type | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | Inferred for a 12-digit MyKad when omitted. |
identity_number | string or null | |
status | "active" | "inactive" |
{
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678",
"status": "active"
}Responses
200The updated member.Returns Member.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | Clive member id. |
statusrequired | "active" | "inactive" | |
full_namerequired | string or null | |
phonerequired | string or null | |
emailrequired | string or null | |
date_of_birthrequired | string or null | YYYY-MM-DD. |
identity_typerequired | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | null | What identity_number is: MyKad, passport, ... |
identity_numberrequired | string or null | IC or passport number. |
membershipsrequired | array of Membership | |
providerrequired | string | Partner system the id belongs to, e.g. partner_v1. |
external_idrequired | string | The member's id in that system. |
membership_norequired | string or null | Membership or card number, when the partner has one. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"status": "active",
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678",
"memberships": [
{
"provider": "partner_v1",
"external_id": "MEM-0012345",
"membership_no": "PM00012345"
}
],
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}| Status | Meaning |
|---|---|
| 400 | Malformed request or invalid cursor. |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 404 | No such record in this clinic (NOT_FOUND). |
| 409 | Conflict, or a request with the same Idempotency-Key is still in flight (IDEMPOTENCY_IN_PROGRESS). |
| 422 | Validation failed (VALIDATION_ERROR), or the Idempotency-Key was used for a different request (IDEMPOTENCY_KEY_REUSED). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.
Find a member by membership number
/public/v1/members/by-membership/{membership_no}Scope members:readOperation getMemberByMembership
Exact match. When the number is held under several providers, pass provider; an ambiguous match answers 409 MEMBERSHIP_AMBIGUOUS.
Requires scope members:read.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
membership_norequired | path | string | |
provider | query | string |
Responses
200The member.Returns Member.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | Clive member id. |
statusrequired | "active" | "inactive" | |
full_namerequired | string or null | |
phonerequired | string or null | |
emailrequired | string or null | |
date_of_birthrequired | string or null | YYYY-MM-DD. |
identity_typerequired | "mykad" | "mypr" | "mykas" | "mytentera" | "passport" | "other" | null | What identity_number is: MyKad, passport, ... |
identity_numberrequired | string or null | IC or passport number. |
membershipsrequired | array of Membership | |
providerrequired | string | Partner system the id belongs to, e.g. partner_v1. |
external_idrequired | string | The member's id in that system. |
membership_norequired | string or null | Membership or card number, when the partner has one. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
{
"id": "c41f7a52-8d1e-4b2a-9f3c-6e5d4c3b2a10",
"status": "active",
"full_name": "Siti Aminah binti Ahmad",
"phone": "+60123456789",
"email": "siti@example.com",
"date_of_birth": "1990-01-01",
"identity_type": "mykad",
"identity_number": "900101-14-5678",
"memberships": [
{
"provider": "partner_v1",
"external_id": "MEM-0012345",
"membership_no": "PM00012345"
}
],
"created_at": "2026-10-01T00:00:00.000Z",
"updated_at": "2026-10-24T02:15:09.123Z"
}| Status | Meaning |
|---|---|
| 400 | Malformed request or invalid cursor. |
| 401 | Missing, invalid or expired access token, or the API client was revoked (INVALID_TOKEN). |
| 403 | The token lacks the scope this operation needs (INSUFFICIENT_SCOPE). |
| 404 | No such record in this clinic (NOT_FOUND). |
| 422 | Validation failed (VALIDATION_ERROR). |
| 429 | Per-client rate limit exceeded (RATE_LIMITED). |
| 500 | Unexpected error (INTERNAL_ERROR). |
Every error body is the error envelope; branch on its code.