Management API contracts
These Huma routes cover the current management API inventory. They register in both the runtime server and offline OpenAPI generator.
The five /admin/verifications operations and PATCH /doctors/profile are now implemented; see Doctor administration for authorization, persistence, response envelopes and related doctor management routes. The remaining operations are contract-only: valid requests return 501 Not Implemented as application/problem+json, malformed JSON returns 400, and request-local validation failures return 422. Bearer permissions, provider orchestration, persistence, audit recording and state-dependent rules are documented only. Those remaining contract-only operations do not change stored data.
Route inventory
All paths below are prefixed with /api/v1. Success codes are intended future responses except for the implemented /admin/verifications routes and doctor profile PATCH.
| Method | Path | Intended success | Request example |
|---|---|---|---|
| PATCH | /doctors/profile | 200 | {"speciality_id":"20000000-0000-4000-8000-000000000001","specialization_ids":[]} |
| GET | /doctors/me/verifications | 200 | — |
| PATCH | /organizations/{organizationId}/doctors/{doctorId} | 200 | {"status":"inactive"} |
| GET | /organizations/active-context | 200 | — |
| GET | /organizations/{organizationId}/teams/{teamId} | 200 | — |
| PATCH | /organizations/{organizationId}/teams/{teamId} | 200 | {"name":"Outpatient"} |
| DELETE | /organizations/{organizationId}/teams/{teamId} | 204 | — |
| PUT | /organizations/{organizationId}/members/{memberId}/team | 200 | {"team_id":"team_123"} |
| DELETE | /admin/users/{adminUserId} | 204 | — |
| GET | /admin/accounts | 200 | — |
| GET | /admin/accounts/{userId} | 200 | — |
| PATCH | /admin/accounts/{userId} | 200 | {"status":"suspended"} |
| POST | /admin/verifications | 201 | {"documents":["https://example.com/license.pdf"]} |
| GET | /admin/verifications/pending | 200 | — |
| GET | /admin/verifications/{verificationId} | 200 | — |
| POST | /admin/verifications/{verificationId}/approve | 200 | {"notes":"Credentials checked"} |
| POST | /admin/verifications/{verificationId}/reject | 200 | {"reason":"Document unreadable"} |
Doctor self-service
Public POST /doctors/register creates the Identity account and professional profile. Profile retrieval and editing use /doctors/profile.
PATCH /doctors/profile persistently edits professional fields only. Omitted fields are preserved; empty patches, blank values and null are rejected. License changes require a new credential review rather than retaining verification of an old license. See Doctor profile updates for the implemented authentication, validation, transaction and response behavior. GET /doctors/me/verifications lists only the authenticated doctor's Admin-owned submissions and review outcomes through a future curated capability.
Organization and teams
Organization admins may edit their organization's contact details and doctor affiliation status. Affiliation status is independent from ordinary membership; reactivation must eventually validate organization state and doctor capacity. Organization ID, slug and lifecycle status cannot be changed through the portal PATCH. Omitted fields are preserved; empty strings clear optional contact fields. Contact email must be a valid email or empty; null and empty patches are rejected.
Active-context lookup returns the selected organization and the caller's membership or doctor affiliation. The future implementation returns 404 when no valid selection exists. Existing legacy activation routes retain their current behavior; these contracts add no active-context storage or authentication.
Authorized organization members may view team details; organization admins may edit/delete teams and assign members. Team IDs and membership IDs must be scoped to the organization in the future implementation. Team PATCH preserves omissions, rejects null/empty patches and permits an empty description. Team deletion is intended to clear assignments while preserving memberships and accounts. Member team assignment requires team_id; explicit null clears it. Member views now include optional team_id. Existing legacy team create/list operations remain available.
Platform administration and Identity
Admin memberships no longer carry roles, and the admin-user role-update route has been removed. Authorization checks will be added separately in use cases. Grant revocation and Identity account status changes remain TODO workflows.
An admin grant ID is distinct from an Identity account ID. Revoking a grant does not delete the Identity account. /admin/accounts reads all safe Identity accounts through future provider capabilities; existing /admin/users continues to expose platform administrators. Accounts never expose password hashes or tokens.
Account listing accepts search and status=active|inactive|suspended. The status PATCH accepts only those states and cannot change credentials, email or roles.
Credential review
Admin owns verification records; Doctor owns professional profiles and Identity owns accounts. Submitting at POST /admin/verifications requires an authenticated doctor rather than a platform-admin grant. The request contains 1–20 absolute HTTP(S) document URLs and optional notes. Doctor/account identity and professional snapshots are server-owned; supplied doctor IDs are rejected. URL validation does not fetch documents. Upload/storage is outside these contracts.
Active platform admins with the corresponding explicit permissions may list the pending queue, inspect evidence and approve/reject pending submissions. States are pending, verified and rejected. Approval accepts optional notes ({} is valid); rejection requires a nonblank reason. Review retains evidence, actor, time and rejection reason, and rejects repeated or concurrent decisions with 409.
The doctor-facing list uses Admin-owned public verification DTOs and optional status=pending|verified|rejected. It does not read Admin repositories. Verification persistence is implemented. Document delivery and prescription eligibility enforcement remain outside this implementation.
Pagination and validation
Contract-only lists use items and optional next_cursor, default limit=20, maximum 100, newest first. Cursors are intended to bind to filters. Unknown query/body fields are rejected. The remaining contract-only routes declare bearer security without enforcing it. Implemented doctor management routes enforce authentication and admin permissions and return the organization-style envelope.
Verification
Composition-root tests cover the management routes, static-path routing for active context and the pending queue, validation/clearing boundaries, bearer declarations, intended success schemas, bodyless 204 responses, and 501 responses with no provider dependencies. Existing generated/runtime OpenAPI parity tests cover the new operations too.
go run ./tools/cli generate openapi
go test -race -short ./services/doctor/... ./services/organization/... ./services/admin/... ./services/api/...
test -z "$(gofmt -l -s pkg services tools)"Organization creation/update use admin routes. The former non-admin organization PATCH contract is retired; see Organization management API.