Keep the living API sheet aligned with demo personas, avatars, ID-card QR scan, list filters, and Admin/Ecom coordination. Co-authored-by: Cursor <cursoragent@cursor.com>
377 lines
7.0 KiB
Markdown
377 lines
7.0 KiB
Markdown
# Endpoints: Members
|
|
|
|
Member CRUD, quick import, invites, join flow, and dependants.
|
|
|
|
**Workspace:** `/Users/kirukib/Desktop/Yaltopia Project/Gishen-B2B`
|
|
|
|
**Entity:** [`../entities/member.md`](../entities/member.md)
|
|
|
|
---
|
|
|
|
## GET /v1/members
|
|
|
|
List members.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN, FINANCE (read metadata) |
|
|
|
|
### Query
|
|
|
|
`?page=1&status=active&department_id=dept_01H&package_id=pkg_01HGOLD&q=abel&member_type=primary&has_dependants=true`
|
|
|
|
| Param | Notes |
|
|
|-------|--------|
|
|
| `q` | Search name, email, phone, employee_id |
|
|
| `status` | `invited` \| `active` \| `inactive` \| `offboarded` |
|
|
| `department_id` | Filter by department |
|
|
| `package_id` | Filter by assigned package |
|
|
| `member_type` | `primary` \| `dependant` |
|
|
| `has_dependants` | `true` \| `false` — primaries with/without dependants |
|
|
|
|
Portal UI: when more than three filters are shown, they open in an Apply modal (client-only); API still accepts all query params above.
|
|
|
|
### Response 200
|
|
|
|
Paginated members. HR/Finance receive withhold-safe fields (no Rx detail).
|
|
|
|
### Clinical withhold
|
|
|
|
Response omits prescription arrays; includes `prescription_count` only.
|
|
|
|
---
|
|
|
|
## POST /v1/members
|
|
|
|
Create member.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN |
|
|
|
|
### Request
|
|
|
|
```json
|
|
{
|
|
"full_name": "Sara Hailu",
|
|
"phone": "+251933445566",
|
|
"email": "sara.h@acme.et",
|
|
"employee_id": "EMP-2001",
|
|
"department_id": "dept_01HABC",
|
|
"package_id": "pkg_01HGOLD",
|
|
"member_type": "primary",
|
|
"start_date": "2026-04-01",
|
|
"send_invite": true
|
|
}
|
|
```
|
|
|
|
### Response 201
|
|
|
|
Created [`Member`](../entities/member.md).
|
|
|
|
### Errors
|
|
|
|
| Code | HTTP | When |
|
|
|------|------|------|
|
|
| `ORG_PENDING` | 422 | Org not active |
|
|
| `DUPLICATE_MEMBER` | 409 | Phone/employee_id conflict |
|
|
| `NOT_FOUND` | 404 | Invalid department/package |
|
|
| `DEPENDANT_LIMIT_EXCEEDED` | 422 | For dependant create |
|
|
|
|
---
|
|
|
|
## GET /v1/members/:id
|
|
|
|
Member detail.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN, FINANCE (metadata); MEMBER (own only) |
|
|
|
|
### Errors
|
|
|
|
| Code | HTTP |
|
|
|------|------|
|
|
| `FORBIDDEN` | 403 — MEMBER accessing other member |
|
|
| `NOT_FOUND` | 404 |
|
|
|
|
### Clinical withhold
|
|
|
|
HR/Finance: no linked prescriptions. SUPER_USER: may include `prescriptions_summary`. MEMBER own: full allowance, order pointers.
|
|
|
|
Detail payload includes `avatar_url`, `card_id`, `verification_id` for pharmacy ID card (safe for HR).
|
|
|
|
---
|
|
|
|
## GET /v1/members/:id/id-card
|
|
|
|
Printable pharmacy verification card payload (B2B print UI + Admin/POS scan).
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN; MEMBER (own `member_id` only) |
|
|
|
|
### Response 200
|
|
|
|
```json
|
|
{
|
|
"data": {
|
|
"member_id": "mbr_01HMEM001",
|
|
"full_name": "Abel Mekonnen",
|
|
"employee_id": "EMP-1042",
|
|
"card_id": "GSH-1042",
|
|
"verification_id": "EMP-1042",
|
|
"avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=mbr_01HMEM001",
|
|
"org_name": "Acme Bank",
|
|
"org_join_code": "ACME-2026",
|
|
"package_name": "Gold Executive",
|
|
"status": "active",
|
|
"qr_payload": "gishen://member/mbr_01HMEM001?v=EMP-1042"
|
|
}
|
|
}
|
|
```
|
|
|
|
### QR / scan contract
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Format** | `gishen://member/{member_id}?v={verification_id}` |
|
|
| **Consumer** | Gishen-Admin POS / pharmacist checkout — resolve covered member |
|
|
| **Not included** | Prescription images, medicine lines, diagnosis |
|
|
|
|
### Errors
|
|
|
|
| Code | HTTP |
|
|
|------|------|
|
|
| `FORBIDDEN` | 403 |
|
|
| `NOT_FOUND` | 404 |
|
|
| `MEMBER_INACTIVE` | 422 — offboarded / inactive cards may still print with watermark (product TBD) |
|
|
|
|
### Clinical withhold
|
|
|
|
ID card is verification metadata only — allowed for HR. No clinical fields.
|
|
|
|
---
|
|
|
|
## PATCH /v1/members/:id
|
|
|
|
Update member.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN |
|
|
|
|
### Request (partial)
|
|
|
|
```json
|
|
{
|
|
"department_id": "dept_01HNEW",
|
|
"package_id": "pkg_01HSILVER",
|
|
"avatar_url": "https://cdn.gishen.../avatars/mbr_01H.png",
|
|
"overrides": { "copay_percent": 5 }
|
|
}
|
|
```
|
|
|
|
`avatar_url` may also be set via future `POST /v1/members/:id/avatar` (multipart). Mock phase uses deterministic portrait URLs.
|
|
|
|
---
|
|
|
|
## POST /v1/members/:id/offboard
|
|
|
|
Offboard member.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN |
|
|
|
|
### Request
|
|
|
|
```json
|
|
{
|
|
"end_date": "2026-03-31",
|
|
"reason": "resignation"
|
|
}
|
|
```
|
|
|
|
### Response 200
|
|
|
|
`status: "offboarded"`. Prescriptions remain on `customer_id`.
|
|
|
|
---
|
|
|
|
## POST /v1/members/import
|
|
|
|
Quick Excel/CSV import (simplified migration).
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN |
|
|
|
|
### Request
|
|
|
|
`multipart/form-data`: `file`, optional `send_invites=true`
|
|
|
|
### Response 202
|
|
|
|
```json
|
|
{
|
|
"data": {
|
|
"job_id": "mig_01HQUICK",
|
|
"status": "validating"
|
|
}
|
|
}
|
|
```
|
|
|
|
Delegates to migration engine — see [`migration.md`](migration.md).
|
|
|
|
---
|
|
|
|
## POST /v1/members/:id/invite
|
|
|
|
Resend or create invite.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN |
|
|
|
|
### Response 200
|
|
|
|
```json
|
|
{
|
|
"data": {
|
|
"invite_url": "https://b2b.gishen.../invite/tok_abc123",
|
|
"expires_at": "2026-03-20T00:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## GET /v1/invite/:token
|
|
|
|
Public invite preview.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Public |
|
|
|
|
### Response 200
|
|
|
|
```json
|
|
{
|
|
"data": {
|
|
"org_name": "Acme Bank",
|
|
"member_name": "Sara Hailu",
|
|
"expires_at": "2026-03-20T00:00:00Z",
|
|
"valid": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### Errors
|
|
|
|
| Code | HTTP |
|
|
|------|------|
|
|
| `INVITE_EXPIRED` | 422 |
|
|
| `NOT_FOUND` | 404 |
|
|
|
|
---
|
|
|
|
## POST /v1/invite/:token/accept
|
|
|
|
Accept invite and activate member account.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Public (creates session) |
|
|
|
|
### Request
|
|
|
|
```json
|
|
{
|
|
"password": "SecurePass1",
|
|
"locale": "en"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## POST /v1/join
|
|
|
|
Self-join via join code or email domain.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Public |
|
|
|
|
### Request
|
|
|
|
```json
|
|
{
|
|
"join_code": "ACME-2026",
|
|
"full_name": "New Employee",
|
|
"email": "new@acme.et",
|
|
"phone": "+251944556677"
|
|
}
|
|
```
|
|
|
|
Or domain-verified email flow.
|
|
|
|
### Response 201
|
|
|
|
Pending or active member + session depending on org verification settings.
|
|
|
|
### Errors
|
|
|
|
| Code | HTTP |
|
|
|------|------|
|
|
| `VALIDATION_FAILED` | 400 — bad code/domain |
|
|
| `ORG_PENDING` | 422 |
|
|
|
|
---
|
|
|
|
## POST /v1/members/:id/dependants
|
|
|
|
Add dependant.
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Auth** | Required |
|
|
| **Roles** | SUPER_USER, HR_ADMIN |
|
|
|
|
### Request
|
|
|
|
```json
|
|
{
|
|
"full_name": "Kidus Hailu",
|
|
"phone": "+251955667788",
|
|
"relationship": "child",
|
|
"start_date": "2026-04-01"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## UI routes
|
|
|
|
| Route | Endpoint(s) |
|
|
|-------|-------------|
|
|
| `/members` | GET `/v1/members` (search + filters; modal when >3) |
|
|
| `/members/new` | POST `/v1/members` |
|
|
| `/members/import` | POST `/v1/members/import` |
|
|
| `/members/[id]` | GET/PATCH + invite/offboard; **ID card** tab → GET `/v1/members/:id/id-card` |
|
|
| `/invite/[token]` | GET/POST invite |
|
|
| `/join` | POST `/v1/join` |
|
|
|
|
## Clinical withhold
|
|
|
|
Member endpoints never return prescription images or medicine lines to HR_ADMIN/FINANCE. Use prescription endpoints with role checks for SUPER_USER/MEMBER clinical access.
|