> ## Documentation Index
> Fetch the complete documentation index at: https://developer.eka.care/llms.txt
> Use this file to discover all available pages before exploring further.

# Book a physical consultation over UHI

> Search doctors on the Unified Health Interface, pick a slot, initiate and confirm the booking, then track, reschedule or cancel it.

## In short

* Book an in-person visit in four calls: search doctors, search slots, Init, Confirm.
* Each `POST` returns at once; its result arrives on a webhook or the matching `GET`.
* Show the patient the `pin` from Confirm; they present it to the doctor.
* Check, reschedule or cancel the booking later with its `order_id`.

## When to use this

Your user wants to see a doctor in person and you book the visit for them over the Unified Health Interface (UHI). The workflow covers the whole booking: doctor search, slot search, initiate, confirm, then status, reschedule and cancel.

Every step is asynchronous. A `POST` starts the request and returns identifiers at once. The result arrives on a webhook, and you can also read it with the matching `GET`.

## Before you start

* A Bearer token. Every UHI operation uses the `authApiKey` scheme. See [Authorization](https://developer.eka.care/api-sdk/auth/getting-started.md).
* The patient logged in on your app, with their Eka user id (`oid`) in hand to send as `X-Pt-Id`. See [Log in to an existing ABHA](https://developer.eka.care/docs/hie-cm/workflows/login-abha.md).&#x20;
* A webhook endpoint registered with Eka that verifies `Eka-Webhook-Signature`. See [Webhook signature](https://developer.eka.care/docs/webhooks/webhook-signature.md).
* The patient's search criteria and the time window they are free, and their billing name, phone and address for the booking.

## Sequence

```mermaid theme={null}
sequenceDiagram
  participant App as Your app
  participant Eka
  App->>Eka: POST /abdm/uhi/v1/physical-consultation/search/doctors
  Eka-->>App: webhook doctor.search.results
  App->>Eka: GET /abdm/uhi/v1/physical-consultation/search/doctors
  App->>Eka: POST /abdm/uhi/v1/physical-consultation/search/doctors/slots
  Eka-->>App: webhook doctor.slot.search.results
  App->>Eka: GET /abdm/uhi/v1/physical-consultation/search/doctors/slots
  App->>Eka: POST /abdm/uhi/v1/physical-consultation/booking/init
  Eka-->>App: webhook booking.init
  App->>Eka: GET /abdm/uhi/v1/physical-consultation/booking/init
  App->>Eka: POST /abdm/uhi/v1/physical-consultation/booking/confirm
  Eka-->>App: webhook booking.confirm
  App->>Eka: GET /abdm/uhi/v1/physical-consultation/booking/confirm
  App->>Eka: POST /abdm/uhi/v1/physical-consultation/booking/order-status
  Eka-->>App: webhook booking.status
  App->>Eka: GET /abdm/uhi/v1/physical-consultation/booking/order-status
  App->>Eka: POST /abdm/uhi/v1/physical-consultation/booking/update
  App->>Eka: POST /abdm/uhi/v1/physical-consultation/booking/cancel
  Eka-->>App: webhook booking.cancel
  App->>Eka: GET /abdm/uhi/v1/physical-consultation/booking/cancel
```

## Steps

Every `POST` in this workflow returns `txn_id`, `provider_id` and `order_id`. The spec describes `txn_id` and `provider_id` as the values for the next call. Every `GET` except Get Doctors takes the same three as query parameters; the spec gives Get Doctors none.

**1. Search for doctors**

Send the patient's criteria to [Search Doctors](https://developer.eka.care/api-sdk/uhi/phys-cons/search-doctors.md). `start_time` and `end_time` set the availability window. The reference page lists the optional filters, such as speciality, doctor, facility and location. Keep `txn_id` and `provider_id` from the response.

**2. Read the doctor results**

The `doctor.search.results` webhook carries the list. You can also read it from [Get Doctors](https://developer.eka.care/api-sdk/uhi/phys-cons/get-doctors.md). If `data` is empty, widen the search and repeat step 1. The patient picks one doctor; keep that result's `hpr_id`, `facility_id` and `transaction_id`.

**3. Search the doctor's slots**

Send `hpr_id`, `facility_id`, `transaction_id`, `provider_id`, `start_time` and `end_time` to [Search Slots](https://developer.eka.care/api-sdk/uhi/phys-cons/search-slots.md). All six are required. Keep `txn_id`, `provider_id` and `order_id` from the response.

**4. Read the slots**

The `doctor.slot.search.results` webhook carries `doctor`, `provider_info` and `slots`. You can also read them from [Get Slots](https://developer.eka.care/api-sdk/uhi/phys-cons/get-slots.md). Each slot has `id`, `date`, `start_time`, `end_time`, `price` and `currency`. If `slots` is empty, pick another window or doctor. The patient picks one slot.

**5. Initiate the booking**

Send [Init](https://developer.eka.care/api-sdk/uhi/phys-cons/init.md) these fields:

* From the chosen slot: its `id` as `slot_id`, its `start_time` and `end_time`, and its price as `price.value` and `price.currency`.
* The doctor's `doctor.id` as `doctor_id`.
* From the chosen doctor: `facility_id`.
* `provider_id`, `transaction_id`, and the patient's `billing`.

The spec describes `transaction_id` only as received in the previous API response. Keep `txn_id`, `provider_id` and `order_id` from the response.

**6. Show the quote and terms**

The `booking.init` webhook carries `quote` with `total` and `breakup`, `terms`, `payment` with `status` and `type`, and the `order_id`. You can also read them from [Get Init](https://developer.eka.care/api-sdk/uhi/phys-cons/get-init.md). Show the total and the terms. The patient must accept the terms before you confirm.

**7. Confirm the booking**

Send `provider_id` and `transaction_id` from Init to [Confirm](https://developer.eka.care/api-sdk/uhi/phys-cons/confirm.md). Keep `txn_id`, `provider_id` and `order_id` from the response.

**8. Read the confirmation and PIN**

The `booking.confirm` webhook carries `order_id`, `pin`, `slot`, `doctor_info` and `state`. You can also read them from [Get Confirm](https://developer.eka.care/api-sdk/uhi/phys-cons/get-confirm.md). Show `pin` to the patient; they present it to the doctor before the consultation. Store `order_id` on the booking.

**9. Check the booking status**

Send `order_id`, `provider_id` and `transaction_id` to [Order Status](https://developer.eka.care/api-sdk/uhi/phys-cons/order-status.md). The `booking.status` webhook carries the booking. You can also read it from [Get Order Status](https://developer.eka.care/api-sdk/uhi/phys-cons/get-order-status.md).

**10. Reschedule, if the patient asks**

Send `order_id`, `provider_id`, `transaction_id`, `facility_id` and the new `slot_id`, `start_time` and `end_time` to [Update](https://developer.eka.care/api-sdk/uhi/phys-cons/update.md). Get a new slot, for example by repeating steps 3 and 4.

**11. Cancel, if the patient asks**

Send `order_id`, `provider_id` and `transaction_id` to [Cancel](https://developer.eka.care/api-sdk/uhi/phys-cons/cancel.md). The `booking.cancel` webhook carries `status`. You can also read it from [Get Cancel](https://developer.eka.care/api-sdk/uhi/phys-cons/get-cancel.md). The spec gives `SUCCESS`, `FAILED` and `PENDING` as examples. Mark the booking cancelled only on `SUCCESS`.

## State you must persist

| Field | From | Keep | For |
| - | - | - | - |
| `oid` | ABHA login | On the patient record | `X-Pt-Id` header on every call |
| `txn_id` | Each `POST` response | Until the next step's `POST` returns | The `GET` poll and the next `POST` as `transaction_id` |
| `provider_id` | Each `POST` response | With the booking, until the visit or cancellation | Every later call for this booking |
| `hpr_id`, `transaction_id` | Chosen doctor result | Until slot search returns | Search Slots |
| `facility_id` | Chosen doctor result | With the booking, until the visit or cancellation | Search Slots, Init, Update |
| `slot_id`, `start_time`, `end_time`, price | Chosen slot | Until Init returns | Init |
| `order_id` | Init, then Confirm | With the booking, until the visit or cancellation | Order Status, Update, Cancel |
| `pin` | Confirm | Until the visit | The patient shows it to the doctor |

## When it fails

> [!WARNING]
>
> Which of these codes each call returns is not yet confirmed. The codes come from the [errors page](https://developer.eka.care/docs/hie-cm/errors.md), matched by meaning. Log the code you actually receive.

Every UHI operation returns `GenericError` with `code`, `error` and `source_error` on a 4XX or 5XX. The spec lists no UHI-specific codes. See [Errors](https://developer.eka.care/docs/hie-cm/errors.md).

| Situation | Code | Do |
| - | - | - |
| Missing or malformed field | 4XX | Fix the request; check the required fields on the reference page |
| Search returns no doctors or no slots | Empty `data` or `slots` | Widen the criteria or the time window |
| Expired or unknown transaction | | Restart from the step that issued it |
| Webhook never arrives | None | Poll the matching `GET` |
| Provider or network unavailable | 5XX | |
| Rate limit | | |
| Cancel returns `FAILED` or `PENDING` | `status` | Keep the booking active; check again with Get Cancel |

## Test it

The [testing page](https://developer.eka.care/docs/hie-cm/testing.md) has the sandbox base URL, credentials and the happy path for every journey.

* [ ] Search doctors with a speciality and a seven-day window; receive `doctor.search.results`
* [ ] Search slots for one result; receive `doctor.slot.search.results` with at least one slot
* [ ] Init with that slot; receive `booking.init` with a quote and terms
* [ ] Confirm; receive `booking.confirm` with a `pin` and `order_id`
* [ ] Order Status; receive `booking.status` with the same `order_id`
* [ ] Update to another slot, then check Order Status shows the new slot
* [ ] Cancel; receive `booking.cancel` with `SUCCESS`
* [ ] Failure: a search that matches nothing returns empty `data`
* [ ] Failure: Search Slots without `hpr_id` returns a 4XX


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.