Skip to main content

Facility Service — API Contracts

Status: populated Owner: TBD Last updated: 2026-04-17 Companion: 05 API Design · API_PATH_CONVENTIONS

1. Conventions

  • Base path: /api/v1
  • Authentication: Bearer JWT (issued by identity-service). Required scopes per endpoint.
  • Tenant context: derived from tid claim; never from path/body.
  • Pagination: ?page={n}&limit={n} (default 20, max 200); response envelope { data, meta: { total, page, limit } }.
  • Idempotency: mutation endpoints accept Idempotency-Key header.
  • Optimistic lock: If-Match: "<version>" on PUT/PATCH.
  • Errors follow { error: { code, message, details? } }.

2. Hierarchy Nodes

MethodPathAuth ScopeDescription
POST/api/v1/hierarchy/nodesfacility:writeCreate node
GET/api/v1/hierarchy/nodesfacility:readList with filters
GET/api/v1/hierarchy/nodes/{id}facility:readGet by id
PATCH/api/v1/hierarchy/nodes/{id}facility:writeUpdate name/code/metadata
POST/api/v1/hierarchy/nodes/{id}/deactivatefacility:adminSoft delete
GET/api/v1/hierarchy/nodes/{id}/subtree?maxDepth=facility:readDescendants
GET/api/v1/hierarchy/nodes/{id}/ancestorsfacility:readRoot → node chain

Request — POST /hierarchy/nodes:

{ "type": "ward", "name": "Pediatric Ward 1", "code": "PW-01", "parentNodeId": "hnd_01H...", "metadata": {"capacity": 12, "timezone": "Asia/Kabul"} }

Response 201: HierarchyNode JSON + Location: /api/v1/hierarchy/nodes/hnd_01H...

Errors: 422 HIERARCHY_NODE_TYPE_NOT_ALLOWED, 409 HIERARCHY_MULTIPLE_ROOTS, 403 ACCESS_DENIED.

3. Hierarchy Edges

MethodPathAuth ScopeDescription
POST/api/v1/hierarchy/edgesfacility:writeCreate edge
DELETE/api/v1/hierarchy/edges/{id}facility:writeRemove edge
GET/api/v1/hierarchy/nodes/{id}/edgesfacility:readList edges for node

Errors: 409 HIERARCHY_CYCLE, 422 EDGE_RELATIONSHIP_NOT_ALLOWED.

4. Hierarchy Profiles

MethodPathAuth ScopeDescription
GET/api/v1/hierarchy/profilesfacility:readList (platform + tenant)
GET/api/v1/hierarchy/profiles/{id}facility:readGet
POST/api/v1/hierarchy/profilesplatform:adminCreate platform profile
POST/api/v1/hierarchy/profiles/{id}/clonefacility:adminTenant clone
PATCH/api/v1/hierarchy/profiles/{id}platform:admin/facility:adminUpdate (tenant-owned only)
POST/api/v1/hierarchy/profiles/{id}/defaultfacility:adminMark default

5. Locations

MethodPathAuth ScopeDescription
POST/api/v1/locationsfacility:writeCreate
GET/api/v1/locations?hierarchyNodeId=&type=&status=&serviceType=&q=facility:readSearch
GET/api/v1/locations/{id}facility:readGet
PUT/api/v1/locations/{id}facility:writeReplace
PUT/api/v1/locations/{id}/hoursfacility:writeSet 7-day hours
GET/api/v1/locations/{id}/hoursfacility:readGet hours
PUT/api/v1/locations/{id}/status?force={bool}facility:adminActivate/deactivate

Request — POST /locations:

{ "hierarchyNodeId": "hnd_01H...", "name": "Ibn Sina ER", "serviceType": "EMERGENCY", "timezone": "Asia/Kabul", "locale": "ps", "capacity": 40 }

Errors: 400 LOCATION_NODE_REQUIRED, 409 LOCATION_HAS_OCCUPIED_BEDS.

6. Beds

MethodPathAuth ScopeDescription
POST/api/v1/bedsfacility:writeCreate
GET/api/v1/beds?locationId=&status=&bedClass=&isolation=facility:readSearch
GET/api/v1/beds/{id}facility:readGet
PUT/api/v1/beds/{id}/statusfacility:writeTransition state
POST/api/v1/beds/{id}/housekeepingfacility:writeUpdate housekeeping

Errors: 409 BED_ALREADY_OCCUPIED, 409 BED_INVALID_TRANSITION.

7. Resource Catalog

MethodPathAuth ScopeDescription
POST/api/v1/resource-catalogfacility:writeCreate
GET/api/v1/resource-catalog?locationId=&type=&status=facility:readSearch
PATCH/api/v1/resource-catalog/{id}facility:writeUpdate
POST/api/v1/resource-catalog/{id}/deactivatefacility:writeDeactivate

8. Provider Memberships

MethodPathAuth ScopeDescription
POST/api/v1/internal/provider-membershipsinternal:provider-directoryAssign (service-to-service)
DELETE/api/v1/internal/provider-memberships/{id}internal:provider-directoryRevoke
GET/api/v1/internal/providers/{id}/contextinternal:any-serviceReturns active memberships + subtree — hot path (p99 ≤ 20ms)

9. Reporting / Import / Export

MethodPathAuth ScopeDescription
GET/api/v1/reporting/facility-dimensionsfacility:readService-line & bed-class aggregates
GET/api/v1/facility-definitions/exportfacility:adminFull snapshot artefact (JSON)
POST/api/v1/facility-definitions/import?dryRun={bool}facility:adminRestore / seed

10. FHIR Mapping

Internal resourceFHIR R4
HierarchyNode (org types: moph/region/district/hospital/clinic)Organization
HierarchyNode (ward/room/department) + LocationLocation (with partOf = parent Location)
Location operational hoursLocation.hoursOfOperation
ResourceCatalogItem (type=EQUIPMENT)Device (via interop-service projection)
MethodPathNotes
GET/POST/PUT/fhir/R4/Location[/{id}]Search by hierarchy-node (custom)
GET/POST/fhir/R4/Organization[/{id}]
GET/POST/fhir/R4/HealthcareService[/{id}]Derived from Location + ResourceCatalog

11. Pagination / Filtering / Sorting

Sorting: ?sort=name / -name. Multi-value filters: ?status=active,inactive.

12. Error Response Example

{ "error": { "code": "HIERARCHY_CYCLE", "message": "Adding this edge would create a cycle under relationship 'contains'", "details": { "parentNodeId": "hnd_01H...", "childNodeId": "hnd_01H..." } } }

13. Rate Limits

Endpoint classLimit
Reads1000 rps / tenant
Writes200 rps / tenant
Internal context lookup5000 rps / caller service