How to request access
Submit the API access request form with your organization, requested data scope, geographic scope, and purpose. MOH admins review requests before issuing an API key. Approved keys are emailed to the address on your request. Keep your API key private and check your spam folder if the email does not appear in your inbox. The online form lets you request any combination of the five permissions below and select Federal, region, zone or woreda coverage. Facility read access is selected initially; exports require an explicit selection and separate approval. API-based requests use a requestedScopes list. Contact support to change an existing key’s permissions.
Authentication
Send one X-Api-Key header with your approved key on every keyed request over HTTPS.
X-Api-Key: <your-api-key># Set these on your integration server.
export MFR_API="https://mfr-be-dev.dh.moh.gov.et"
export MFR_API_KEY="<your-api-key>"Keep the key in your integration’s server configuration. Do not embed it in browser code, URLs or shared files. Request only the permissions your integration needs and contact support to replace a key that is no longer secure.
Available scopes
Permissions are granted individually. Existing keys retain their current permissions; new scopes are not added automatically. A standard access request defaults to facilities:read.
| Scope | Use |
|---|---|
| facilities:read | Search facilities, view profiles, and retrieve facility lists and counts. |
| lookups:read | Retrieve facility types, ownership categories, qualifications and other reference values. |
| locations:read | Retrieve region, zone and woreda lists for filters and location selections. |
| reports:read | Retrieve dashboard summaries, counts, recent facilities and geographic reports. |
| facilities:export | Download facility data in XLSX, CSV or JSON. Export permission is approved separately from read access. |
Facility search
This route requires facilities:read and returns paginated facility rows. pageNumber is at least 1 and showPerPage is limited to 1–100. Approved geographic restrictions apply automatically; conflicting location filters return 403.
POST /api/public/v1/facilities/search
X-Api-Key: <your-api-key>
Content-Type: application/jsontype FacilityParameters = {
name?: string;
pageNumber?: number;
showPerPage?: number;
statusId?: number[];
ownershipId?: number[];
regionId?: number[];
zoneId?: number[];
woredaId?: number[];
facilityTypeId?: number[];
operationalStatusId?: number[];
constructionStatusId?: number[];
clinicalServiceId?: number[];
diagnosticAndImagingServiceId?: number[];
twentyFourHourServiceOfferId?: number[];
supportServiceId?: number[];
};type FacilitySearchRow = {
id: number;
name?: string | null;
status?: string | null;
operationalStatus?: string | null;
facilityType?: string | null;
parentFacilityType?: string | null;
ownership?: string | null;
region?: string | null;
zone?: string | null;
woreda?: string | null;
totalCount: number;
pageCount: number;
};curl -X POST "$MFR_API/api/public/v1/facilities/search" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $MFR_API_KEY" \
-d '{"pageNumber":1,"showPerPage":25,"name":"clinic"}'Facility detail
These profile routes require facilities:read and return identifiers, location, coordinates, classification labels, the technical manager, facility contact information and service names. A claimed Facility Licensing facility uses the Technical Leader professional; otherwise the technical manager is the head of facility. Use a numeric ID or the /facilities/dhis2/{dhis2id} route for a DHIS2 identifier. Requests outside an approved geographic restriction return 403.
GET /api/public/v1/facilities/{id}
X-Api-Key: <your-api-key>type FacilityDetail = {
id: number;
name?: string | null;
otherName?: string | null;
hmisCode?: string | null;
ethiopianNationalFacilityId?: string | null;
facilityId?: string | null;
status?: string | null;
operationalStatus?: string | null;
facilityType?: string | null;
parentFacilityType?: string | null;
ownership?: string | null;
region?: string | null;
zone?: string | null;
woreda?: string | null;
city?: string | null;
kebele?: string | null;
latitude?: number | null;
longitude?: number | null;
phoneNumber?: string | null;
email?: string | null;
website?: string | null;
pocName?: string | null;
pocQualification?: string | null;
pocRegistrationNumber?: string | null;
pocPhoneNumber?: string | null;
pocEmail?: string | null;
clinicalServices: string[];
diagnosticAndImagingServices: string[];
supportServices: string[];
twentyFourHourServiceOffers: string[];
};curl "$MFR_API/api/public/v1/facilities/123" \
-H "X-Api-Key: $MFR_API_KEY"Endpoint directory
The v1 surface contains 28 retrieval operations. Add the prefix /api/public/v1 to each path below. POST operations in this directory retrieve data using a JSON request body. Expand a group for its routes; consult the API reference for all parameters and response fields.
Facility search and profiles · 3 operationsfacilities:read
| Method | Path and purpose |
|---|---|
| POST | /facilities/searchPaginated search with a compact response |
| GET | /facilities/{id}Profile by numeric facility ID |
| GET | /facilities/dhis2/{dhis2id}Profile by DHIS2 ID |
Facility compatibility routes · 8 operationsfacilities:read
| Method | Path and purpose |
|---|---|
| GET | /Facility?id={id}Detail using the established facility response format |
| GET | /Facility/{dhis2id}Established detail format by DHIS2 ID |
| POST | /Facility/GetFacilitiesSearch with existing filters and list format |
| POST | /Facility/GetFacilitiesZenFacility list with coordinates and paging fields |
| POST | /Facility/GetArchivedFacilitiesArchived facility list |
| GET | /Facility/GetFacilitiesCountCount with optional geographic filters |
| GET | /Facility/GetLookupsUsageCount?name={name}&id={id}Facility usage count for a lookup value |
| GET | /Facility/AllFacility collection with existing query filters |
Lookups and facility types · 5 operationslookups:read
| Method | Path and purpose |
|---|---|
| GET | /Lookup?name={name}&id={id}Lookup values; id is optional |
| GET | /Lookup/GetFacilityTypeTop-level facility types |
| GET | /Lookup/GetFacilityTypeByParent?ParentFacilityTypeId={id}Children of a facility type |
| GET | /Lookup/GetOwnershipOwnership values |
| POST | /Lookup/QualificationsByFacilityTypeQualifications for a type and optional subtypes |
Geographic reference data · 5 operationslocations:read
| Method | Path and purpose |
|---|---|
| GET | /Location/RegionsRegions |
| GET | /Location/ZonesZones |
| GET | /Location/GetZoneByRegion?RegionId={id}Zones within a region |
| GET | /Location/WoredasWoredas |
| GET | /Location/GetWoredaByZone?ZoneId={id}Woredas within a zone |
Reports · 4 operationsreports:read
| Method | Path and purpose |
|---|---|
| GET | /Report/DashboardSummary rows with type, name and count |
| POST | /Report/CountsCounts for the supplied facility filters |
| GET | /Report/RecentFacilitiesRecent facility records |
| GET | /Report/GeoLocations/{type}Region, Zone, Woreda or Facility point rows |
Facility exports · 3 operationsfacilities:export
| Method | Path and purpose |
|---|---|
| POST | /Facility/ExportXLSXExcel workbook download |
| POST | /Facility/ExportCSVCSV download |
| POST | /Facility/ExportJSONJSON download |
Reference data and reports
Lookup and location lists provide reference values for filters and selections. Geographic reference lists are available across the register with locations:read; facility and report requests remain subject to your approved geography. To build a facility-type hierarchy, fetch the top-level types, then request the children of each selected parent.
GET /api/public/v1/Location/Regions
GET /api/public/v1/Location/GetZoneByRegion?RegionId=1
GET /api/public/v1/Lookup?name=Ownership
GET /api/public/v1/Lookup/GetFacilityTypeByParent?ParentFacilityTypeId=1POST /api/public/v1/Lookup/QualificationsByFacilityType
Content-Type: application/json
{"facilityTypeId":1,"facilitySubTypeIds":[]}GET /api/public/v1/Report/Dashboard?regionId=1
GET /api/public/v1/Report/GeoLocations/Region?regionId=1
POST /api/public/v1/Report/Counts
Content-Type: application/json
{"regionId":[1]}Include your API-key header on each request. Replace example IDs with reference values appropriate to your integration. Geographic report types are Region, Zone, Woreda and Facility, supplied in the path. Use geographic filters to focus results. These report lists do not include pagination metadata; coordinate data can be converted to your application’s preferred map format.
Migration and exports
For an existing integration, keep the HTTP method and replace /api/ with /api/public/v1/ for the corresponding compatibility route. Preserve its query parameters or JSON body and add the API-key header. Compatibility routes retain established response formats.
GET /api/Facility?id=123
→ GET /api/public/v1/Facility?id=123
POST /api/Facility/GetFacilities
→ POST /api/public/v1/Facility/GetFacilities
GET /api/Location/Regions
→ GET /api/public/v1/Location/RegionsThe singular /Facility detail and /Facility/All routes retain the established facility response. The plural /facilities/search and /facilities/… profile routes offer compact responses with classification and location labels. Choose the documented contract that matches your integration; the two formats are not interchangeable.
Exports require the separate facilities:export permission and accept a JSON filter body with optional columns. Successful responses contain the XLSX, CSV or JSON download, rather than the standard retrieval envelope. Follow the selected export’s schema and content type. Requesting read access does not automatically grant export access.
Access-request onboarding stays at POST /api/ApiAccess/Requests and does not require an API key. Contact support for migration timing and any permission changes your integration needs. A fresh MoH Cap CAPTCHA token is required in the X-Cap-Token header.
Response envelope
JSON retrieval routes return the standard MFR envelope. result: 0 means success. Check both the HTTP status and result: some reference-data requests can return a nonzero result with HTTP 200. Treat that as a failed request, rather than an empty result. Facility search rows carry totalCount and pageCount; other lists may have different structures. Export successes return file content directly.
type MfrResponse<T> = {
result: number;
message?: string | null;
model?: T | null;
};Error codes
| Status | Meaning |
|---|---|
| 400 | Missing or invalid request body |
| 401 | Missing, invalid, inactive, or expired API key |
| 403 | Required permission is missing or the request is outside the approved geography |
| 404 | Facility not found for the detail endpoint |
| 429 | The API key has reached a configured request limit; pause requests and use backoff |
| 500 | The service could not complete the request |
Correct credentials or permissions before retrying 401 or 403 responses. For 429, pause requests and use backoff within the limits agreed for your key; a retry time may not be included in the response. Contact support if a limit or repeated error prevents normal use.
Data freshness and acceptable use
Data reflects registry updates and each endpoint’s refresh cycle. Report results may be cached, so a response is not a guarantee of an immediate change in the register. Respect response cache headers and the usage terms agreed for your integration. Keep source attribution to the Ethiopian Ministry of Health, record when you retrieved data, and use or share it only within your approved purpose and geography. A registry count should be described according to its selected filters.