Facility Registry (HFR)
Search and de-duplicate facilities, run the four-stage HFR onboarding wizard, link HIP/HIU bridges, and verify facility contacts.
The Health Facility Registry (HFR) is where you onboard the clinic,
hospital, lab or pharmacy. Onboarding is a four-stage wizard driven by a
trackingId that carries state between calls, performed by a facility
manager who holds an HPR ID. The final
facilityId it returns is also your HIP ID for consent and data-flow.
Search before you onboard
Many Indian facilities are already seeded in HFR. Always search and de-duplicate first — creating a duplicate is the most common onboarding mistake.
flowchart TD
S["Search / de-duplicate"] --> B["1. basic-information<br/>(x-hprid-auth) → trackingId"]
B --> Q{"operational<br/>status = Functional?"}
Q -- "yes" --> AD["2. additional-information"]
AD --> DT["3. detailed-information"]
DT --> SUB["4. submit-facility<br/>(x-hprid-auth) → facilityId"]
Q -- "no" --> SUB
SUB --> BR["link bridges (HIP/HIU)"]
SUB --> OTP["verify facility contact (OTP)"]
Headers
All calls send Authorization: Bearer $SYSTEM_TOKEN. Only
basic-information and submit-facility
additionally require the facility manager's
x-hprid-auth token.
Search & de-duplicate
Search facility
Search by facilityId or by the trio ownershipCode + stateLGDCode +
facilityName. When a facilityId is supplied, the other criteria are
ignored. Fuzzy match on name, exact match on everything else; paginated
(default 10 per page).
/FacilityManagement/v1.5/facility/searchReturns basic facility details.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/FacilityManagement/v1.5/facility/search" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"facilityId": "IN33XXXXXX45",
"ownershipCode": "",
"stateLGDCode": "",
"districtLGDCode": "",
"subDistrictLGDCode": "",
"pincode": "",
"facilityName": "",
"page": 1,
"resultsPerPage": 10
}'{
"facilities": [
{
"facilityId": "IN33XXXXXX45",
"facilityName": "ABC Hospital",
"facilityStatus": "Submitted",
"ownership": "PRIVATE",
"ownershipCode": "P",
"systemOfMedicine": "Modern Medicine(Allopathy),Dentistry",
"facilityType": "Dental College",
"stateName": "Tamil Nadu", "stateLGDCode": "33",
"districtName": "Chennai", "districtLGDCode": "568",
"subDistrictName": "Ambattur", "subDistrictLGDCode": "5700",
"address": "No 510 south street koyambedu, ",
"pincode": "600107",
"latitude": "27.90728", "longitude": "78.32990"
}
]
}Search field rules
From the HFR workbook: facilityId is a 12-character
alphanumeric value starting with IN (when supplied,
other filters are ignored). ownershipCode is a value from
get-master-data?type=OWNER; stateLGDCode /
districtLGDCode / subDistrictLGDCode come from the
lgd/* APIs; pincode is max 6 digits.
page defaults to 1 and resultsPerPage
to 10 — both are system-set, not end-user input.
De-duplicate
A stricter address-based duplicate check that also returns distance to each match — the best pre-flight before creating a facility.
/search/address/filter/deduplicatename, district and subDistrict are
required; address, village,
geolocation and facilityId are optional.
district/subDistrict are LGD codes; results are
sorted nearest-first by distances (km).
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/search/address/filter/deduplicate" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Sunrise Clinic",
"address": "alampur",
"district": "499",
"subDistrict": "3997",
"village": "530905",
"geolocation": "20.615650,77.502489",
"facilityId": ""
}'[
{
"facility_name": "tsst1",
"alternate_id": "INXXXXXXXX93",
"sub_district": "Karanja",
"district": "Washim",
"state": "Maharashtra",
"distances": "0"
}
]Nearby geo search
Fetch facilities within a radius of a point, with optional filters for ownership, speciality, system of medicine, ABDM-software status and even doctor attributes. Path and field names are taken from the HFR Swagger (ground truth).
/FacilityManagement/v1.5/facility/bygeoLocation/searchFacilityAndInfrastructureWithinRadiusWithFiltercenterLat, centerLon, radiusInKm,
from (≥ 0) and size (≥ 1) drive the search; the rest
are optional filters. Latitude −90…+90, longitude −180…+180, 1–6 decimals.
abdmSoftware: "0" or "1"; facilityOwnership: "G", "P"
or "PP". som is a system-of-medicine code; speciality
and hospitalSpecialityType take comma-separated lists.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/FacilityManagement/v1.5/facility/bygeoLocation/searchFacilityAndInfrastructureWithinRadiusWithFilter" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"centerLat": "12.911411",
"centerLon": "77.676313",
"radiusInKm": "50",
"from": "0",
"size": "2000",
"abdmSoftware": "1",
"facilityOwnership": "G",
"facilityStatus": "Functional",
"facilityName": "",
"hospitalSpecialityType": "22,57",
"speciality": "Leeching,Dalak,Exercise",
"som": "UN",
"gender": "",
"doctorName": "",
"doctorSystemOfMedicine": "",
"languages": ""
}'{
"searchCountTotal": 1,
"recordList": [
{
"fac_unique_id": "71600",
"alternate_id": "<Facility ID>",
"facility_name": "<Facility Name>",
"facility_ownership": "G",
"facility_type": "22",
"system_of_medicine": "UN",
"geolocation": "12.911411,77.676313",
"district": "525", "state": "29", "pincode": "560035",
"abdm_software": "1",
"distances": "0",
"speciality": ["dalak", "exercise", "leeching"]
}
]
}Master & LGD lookups
Never hardcode codes — every wizard dropdown has a masters API. Codes may carry
trailing padding spaces (e.g. "G "); trim before comparing.
| API | Method | Returns |
|---|---|---|
/v1.5/facility/get-master-types | GET | List of master types |
/v1.5/facility/get-master-data?type=OWNER | GET | Values for a type (OWNER, MEDICINE, FAC-STATUS, IMAGING, DIAGNOSTIC…) |
/v1.5/facility/lgd/states | GET | States + their districts |
/v1.5/facility/lgd/districts?stateCode=34 | GET | Districts for a state |
/v1.5/facility/lgd/subdistricts?districtCode=4 | GET | Sub-districts for a district |
/v1.5/facility/fetch-facility-type | GET | Facility types for an ownership + medicine system |
/v1.5/facility/get-owner-subtype | GET | Ownership sub-types (incl. Central-Govt ministries) |
/v1.5/facility/get-specialities | GET | Specialities per system of medicine |
/getPsuDetailsByMinistry?ministry=MOD | GET | PSUs for a ministry |
/v1.5/facility/get-master-data?type=OWNERThe pattern for every master list — a type and a
code/value array.
curl "https://apihspsbx.abdm.gov.in/v4/int/v1.5/facility/get-master-data?type=OWNER" \
-H "Authorization: Bearer $SYSTEM_TOKEN"{
"type": "OWNER",
"data": [
{ "code": "G", "value": "Government" },
{ "code": "P", "value": "Private" },
{ "code": "PP", "value": "Public-Private-Partnership" }
]
}PSU details (Central Government facilities)
When a facility is a Central-Government PSU (ownershipCode: "G",
ownershipSubTypeCode: "C", workingInPsu: true), the facPsuName in
basic-information must be a PSU id from this list.
/getPsuDetailsByMinistry?ministry=MODministry codes (MOD, MOR, MOSteel, MOHF…) come from
get-owner-subtype for Central-Government entities.
curl "https://apihspsbx.abdm.gov.in/v4/int/getPsuDetailsByMinistry?ministry=MOD" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Accept: application/json"{
"data": [
{ "id": "HAL", "value": "HAL(Hindustan Aeronautics Limited)" },
{ "id": "BEL", "value": "BEL(Bharat Electronics Limited)" }
]
}Onboarding — the four stages
Stage 1 — Basic information
Creates the draft facility and returns the trackingId. The whole facility
payload is nested under facilityInformation, with trackingId as a
sibling (empty on first create). Requires x-hprid-auth.
/v1.5/facility/basic-informationSave the returned trackingId — every later stage needs it.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/v1.5/facility/basic-information" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "x-hprid-auth: $HPR_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trackingId": "",
"facilityInformation": {
"facilityName": "Test Hospital 102",
"ownershipCode": "G",
"ownershipSubTypeCode": "C",
"ownershipSubTypeCode2": "MOSteel",
"workingInPsu": true,
"facPsuName": "SAIL(Steel Authority of India Limited)",
"facilityAddressDetails": {
"country": "India",
"stateLGDCode": "18",
"districtLGDCode": "288",
"subDistrictLGDCode": "2087",
"villageCityTownLGDCode": "",
"addressLine1": "testaddadd,3testing",
"addressLine2": "",
"pincode": "781005",
"latitude": "70.15394",
"longitude": "72.87281"
},
"facilityContactInformation": {
"facilityContactNumber": "8989042241",
"facilityEmailId": "clinic@example.com",
"facilityLandlineNumber": "",
"facilityStdCode": "",
"websiteLink": ""
},
"systemOfMedicineCode": "M,D",
"facilityTypeCode": "9",
"facilitySubType": "30",
"specialityTypeCode": "",
"typeOfServiceCode": "",
"facilityOperationalStatus": "F",
"facilityUploads": {
"facilityBuildingPhoto": { "name": "building.pdf", "value": "<base64>" },
"facilityBoardPhoto": { "name": "board.png", "value": "<base64>" }
},
"facilityAddressProof": [
{ "addressProofType": null, "addressProofAttachment": { "name": "", "value": "" } }
],
"timingsOfFacility": [
{ "workingDays": "Mon", "openingHours": "9:00 AM - 5:00 PM" },
{ "workingDays": "Tue", "openingHours": "9:00 AM - 5:00 PM" }
],
"abdmCompliantSoftware": [
{ "existingSoftwares": [], "anyOther": "abdm.gov.in" }
]
}
}'{
"trackingId": "7993",
"status": "Created",
"message": "Facility created successfully. Please save the Facility Id returned",
"errorStatus": null
}Nested payload & coded status
Two things older integrations get wrong: (1) the facility payload is
nested under facilityInformation, not flat; and
(2) facilityOperationalStatus is a master code
(e.g. "F" for Functional from FAC-STATUS), not the
word "Functional". Uploads, address proof, timings and
abdmCompliantSoftware all belong inside basic
information. Building/board photos: max 5 MB each; jpg/jpeg/png/pdf, with the
filename extension matching the bytes.
Basic-information field rules
Validations the HFR portal enforces on stage 1 (from the HFR test-case workbook). Backend uses codes from the masters API, not display labels.
| Field | Rule |
|---|---|
facilityName | Alphanumeric, must start with a letter, > 4 characters, no special characters |
latitude | Real number −90.000000…+90.000000, 1–6 decimals |
longitude | Real number −180.000000…+180.000000, 1–6 decimals |
country | Defaults to India, non-editable |
stateLGDCode / districtLGDCode / subDistrictLGDCode | LGD codes from the lgd/* APIs |
addressLine1 (mandatory) / addressLine2 | Alphanumeric; only these specials allowed: . - , / ( ) _ |
pincode | Max 6 digits |
workingDays | Codes from get-master-data?type=WORKING-DAYS; multiple; required if operational status is Functional |
timingsOfFacility | 10:00 AM - 2:00 PM or 24*7; only for selected working days |
facilityOperationalStatus | Code from FAC-STATUS (e.g. F = Functional) |
facilityLandlineNumber | 10 digits, no alphabets/specials |
facilityContactNumber (mobile, public) | 6–8 digits |
facilityEmailId / websiteLink | Valid email / valid URL |
| Building & Board photos | ≤ 5 MB each; PNG/JPEG/JPG; single file |
facilityAddressProof | Type codes from ADDRESS-PROOF (multiple); each attachment ≤ 5 MB |
ownershipCode | One value from OWNER master |
ownershipSubTypeCode | Required only when ownership is Government; from get-owner-subtype |
ownershipSubTypeCode2 | Required only when subtype is Central; from CENTRAL-GOVERNMENT |
systemOfMedicineCode | Codes from MEDICINE (multiple) |
facilityTypeCode / facilitySubType | Codes from fetch-facility-type / fetch-facility-Sub-type |
typeOfServiceCode | From SPECIALITY-TYPE; not required for Pharmacy, Blood bank, Diagnostic Lab, Imaging Center, Cath lab, Dialysis Center |
specialityTypeCode | From get-specialities per system of medicine; required for all types except Pharmacy, Blood bank, Cath lab, Dialysis Center |
Stage 2 — Additional information
Only when facilityOperationalStatus is Functional. Captures which
sub-services exist and any linked programme IDs.
/v1.5/facility/additional-informationThe has* flags accept Y/N. Fields that
don't apply to the facility type must be null or N,
or the API returns per-field errorStatus entries.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/v1.5/facility/additional-information" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trackingId": "820",
"generalInformation": {
"hasDialysisCenter": "N",
"hasPharmacy": "N",
"hasBloodBank": "N",
"hasCathLab": "N",
"hasDiagnosticLab": "N",
"hasImagingCenter": "N",
"servicesByImagingCenter": [ { "service": "", "count": 0 } ]
},
"linkedProgramIds": {
"nhrrId": "",
"nin": "",
"abpmjayId": "",
"rohiniId": "",
"echsId": "",
"cghsId": "",
"ceaRegistration": "",
"stateInsuranceSchemeId": ""
}
}'Stage 3 — Detailed information
Only when Functional. Send only the sections that apply to the facility type —
sending an inapplicable section is rejected with HIS-1070 ("not required for
this facility type").
/v1.5/facility/detailed-informationSection applicability by type: specialities & medicalInfrastructure for hospital/clinic/IPD/day-care/dentistry; pharmacyDetails for pharmacies; bloodBankDetails for blood banks; imagingServices for imaging centres; diagnosticServices for diagnostic labs.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/v1.5/facility/detailed-information" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trackingId": "80454",
"specialities": [
{ "systemOfMedicineCode": "M", "isSpecializationAvalaible": "Yes", "specialities": ["s6", "s13"] }
],
"medicalInfrastructure": {
"countIPDBedsWithoutOxygen": 0,
"countIPDBedsWithOxygen": 0,
"countICUBedsWithVentilators": 0,
"countICUBedsWithoutVentilators": 0,
"countHDUBedsWithVentilators": 0,
"countHDUBedsWithoutVentilators": 0,
"totalNumberOfVentilators": 0,
"countDayCareBedsWithoutOxygen": 0,
"countDayCareBedsWithOxygen": 0,
"countDentalChairs": 0,
"totalNumberOfBeds": 0
},
"pharmacyDetails": {
"isJanAushadhiKendra": "N",
"janAushadhiKendraId": "",
"drugLicenseNumber": "",
"pharmacyGstinNumber": "",
"pharmacistRegistrationNumber": ""
},
"bloodBankDetails": {
"isFacilityRegisteredInERaktkosh": "N",
"eRaktoshId": "",
"bloodBankLicenseNumber": "",
"bloodStorageCenters": "",
"storageCentersCount": 0,
"bloodCollectedPerAnnum": "",
"bloodRequiredPerAnnum": ""
},
"imagingServices": [ { "service": "", "count": 0 } ],
"diagnosticServices": []
}'{
"trackingId": "80454",
"status": "Saved",
"message": "Facility details have been saved successfully. Please login at https://hspsbx.abdm.gov.in/ and submit your facility details for approval.",
"errorStatus": null
}Stage 4 — Submit facility
Final submission. Without it the facility stays in Draft. Requires
x-hprid-auth. Returns the permanent facilityId.
/v1.5/facility/submit-facilityLeave sourceOfInformation empty to submit as your own entity, or
set it to a valid HFR data source with the matching
sourceUniqueID. The facilityId starts with
IN and is 12 characters.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/v1.5/facility/submit-facility" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "x-hprid-auth: $HPR_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trackingId": "820",
"sourceOfInformation": "",
"sourceUniqueID": "",
"facilitySuperUser": ""
}'{
"facilityId": "INAN000167",
"status": "Created",
"message": "Facility created successfully. Please save the Facility Id returned.",
"errorStatus": null
}Submit body per Swagger
Per the HFR Swagger, the submit body is
{ trackingId*, sourceOfInformation, sourceUniqueID, facilitySuperUser }— only trackingId is required and facilitySuperUser
is an optional string. Leave sourceOfInformation /
sourceUniqueID empty to submit as your own entity. The older
x-hprid-auth-verifier header is not used.
Your facilityId is your HIP ID
The returned facilityId is the facility's HFR ID,
which doubles as your HIP ID for consent and data-flow APIs.
Link your bridges to it next.
Update a facility
There is no separate update endpoint. To edit an existing facility you
re-run the same onboarding stages carrying the facility's existing
trackingId, then submit again (a "resubmit"). Field rules are identical to
onboarding.
Edit the stage(s) you need
Call basic-information, additional-information and/or detailed-information
again with the facility's existing trackingId and the changed values — send
only the stages that change. basic-information still requires x-hprid-auth.
Resubmit
Call submit-facility again with the same trackingId to push the edits for
approval.
Edits are keyed by trackingId
The Swagger models every onboarding/edit stage by trackingId —
the handle returned by the first basic-information call — so keep
it from the original onboarding. If you only hold the facilityId,
search for the facility first, and confirm the
edit-keying against the sandbox before relying on it in production.
Link bridges (HIP / HIU)
Associate your HIP/HIU bridges with the facility so data-flow requests
resolve to it. Each bridge needs a unique hipName.
/v1/bridges/MutipleHRPAddUpdateServicesLinks one or more bridges (each HRP[] entry) to the facility.
All HRP[] fields are required.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/v1/bridges/MutipleHRPAddUpdateServices" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"facilityId": "IN28XXXXXX08",
"facilityName": "Test Hospital 104",
"HRP": [
{
"bridgeId": "SBX_000135",
"hipName": "Test Hospital 104",
"type": "HIP",
"active": true
}
]
}'[
{
"servicesLinked": {
"id": "SBX_000135",
"name": "Testing",
"types": ["HIP"],
"active": true
}
}
]Bridge field rules
From the HFR workbook: facilityId must already exist in HFR
(starts IN, 12 characters) and facilityName is
auto-fetched from it. bridgeId is alphanumeric and its validity is
checked by HIECM; it must not repeat an already-linked bridge on the facility.
type is HIP/HIU (validated by HIECM) and
active is a boolean.
hipName & duplicate rules
hipName is what patients see when searching for the hospital in
the ABHA/PHR app. Rules: max 15 characters, no special
characters (%$*#@(~&!), and unique per bridge per
facility. A common convention is hospital name + bridge suffix (e.g.
XYZ + BRIDGE TEST → XYZ BRIDGE).
Re-linking a bridgeId already associated with the facility fails
with error code 2500 (or 2506).
Verify facility contact (OTP)
Send OTP to contact
/v1.5/facility/sendOtpToContactSends a 6-digit OTP to the facility's registered mobile and returns a
transactionId.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/v1.5/facility/sendOtpToContact" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "facilityId": "IN28XXXXXX14" }'[
{
"facilityId": "IN28XXXXXX14",
"status": "Success",
"message": "Otp sent successfully! Please keep transaction id for future reference",
"transactionId": "efcd063c-7c4a-421f-8c2d-62de95ca82d6",
"errorStatus": null
}
]Validate OTP
/v1.5/facility/validateOtpValidates the OTP against the transactionId from the send step
and links the source hospital ID to HFR. source must be one of:
UWIN, PMNDP, AB-PMJAY,
NHRR, HMIS-CDAC, NIN,
eHospital, STHMISID, STINSID,
COWIN.
curl -X POST "https://apihspsbx.abdm.gov.in/v4/int/v1.5/facility/validateOtp" \
-H "Authorization: Bearer $SYSTEM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"otp": "091729",
"source": "COWIN",
"transactionId": "c22f9549-6d0f-436a-bc62-de05d57e7083"
}'Validation gotchas
Save yourself a support ticket
The rules the HFR sandbox enforces most often.
| Rule | Detail |
|---|---|
| Facility uniqueness | name + address + state + district + sub-district + pincode must be unique |
| Status branching | A non-Functional facilityOperationalStatus skips stages 2 & 3 and goes straight to submit |
| Ownership constraints | G ⇒ ownerSubTypeCode must be C; P/PP ⇒ P or NP |
| PSU fields | facPsuName only when ownershipCode:"G" + ownershipSubTypeCode:"C" + workingInPsu:true |
| Medical infrastructure | Required for IPD/day-care/dentistry; not for imaging/diagnostic/blood-bank/pharmacy/cath-lab |
| Specialities | Required for hospital/clinic types; not for diagnostic/imaging/blood-bank/pharmacy/dialysis/cath-lab |
facilityId format | Starts with IN, exactly 12 characters |
facilityName | Starts with a letter, > 4 chars, alphanumeric, no specials |
| Address line specials | Only . - , / ( ) _ allowed beyond alphanumerics |
| Public phone numbers | Landline 10 digits; mobile 6–8 digits |
| Working days & timings | workingDays required when Functional; timings HH:MM AM - HH:MM PM or 24*7 |
| Bed/chair counts | Numeric; per-field ≤ 2 digits; totalNumberOfBeds / totalNumberOfVentilators ≤ 4 digits |
| Update flow | Re-run stages with the existing trackingId, then resubmit — no dedicated update endpoint |
| Geolocation | "lat,long", 1–6 decimals; lat −90…+90, long −180…+180 |
| Master codes | May carry trailing padding spaces — trim before comparing |
Sources
- HSP Swagger — HFR OpenAPI spec (ground truth)
- ABDM HFR — Facility Onboarding Documentation (updated 08-04-2026)
- ABDM HFR M4 Test Cases workbook (16-03-2024) — field validations
