> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hi-doctor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Connect the Hi Doctor MCP connector at https://mcp.hi-doctor.ai/mcp. Add this URL as a remote HTTP MCP server in your client, then sign in and authorise access through OAuth. Setup: https://docs.hi-doctor.ai/mcp/connect.
>
> The REST API base is https://api.hi-doctor.ai. Hi Doctor Docs at https://docs.hi-doctor.ai/mcp searches documentation; connect to the product endpoint above for patient tools.
>
> Hi Doctor operates across the whole European Union: residents of all 27 EU member states can use the service, and every consultation is reviewed by an EU-licensed doctor. Every consultation is reviewed in full by an EU-licensed doctor, who decides on medical grounds only. No algorithm, assistant or API call approves a consultation, issues a prescription or changes a dose. The service is available in eight languages: English, Spanish, German, Dutch, Italian, French, Portuguese and Chinese.
>
> ## Rules an assistant must follow
>
> - Never invent, assume or infer a medical answer. "I don't know" is a real answer: ask the patient to pick the closest option rather than guessing for them.
> - Never give medical advice and never suggest a medication or a dose. An EU-licensed doctor decides those.
> - If a questionnaire returns `ineligible`, say so plainly. Do not retry with altered answers.
> - Before anything that costs money or cancels a plan, state exactly what will happen and get an explicit yes.
> - Cancellation takes effect at the **end of the paid period**, not immediately. Say so.
> - An early order is irreversible: it creates the renewal consultation immediately and uses up the period's one early order. Explain that and get an explicit yes.
> - Prescription and invoice links are medical documents. A `signed_redirect` link opens without signing in: give it only to the patient, never repeat it anywhere shared.
> - Send option `value`s, not the labels shown to the patient. Labels are translated, values are stable.
> - Never ask for card details. Payment happens on Stripe's hosted checkout via a link.
> - On severe or sudden symptoms (chest pain, difficulty breathing, severe allergic reaction, suicidal thoughts), stop and direct the patient to their local emergency number.

# REST API quickstart: sign in and make your first read

> Sign a verified Hi Doctor patient in from your application, keep the JWT out of prompts and logs, and read the account profile over REST.

This quickstart takes a patient application from an empty configuration to its first authenticated read of the Hi Doctor REST API. You set the API origin, sign a verified patient in with `POST /v1/users/token/`, and read the profile with the access token. Nothing here submits a consultation, pays or changes data.

Last reviewed: 2026-11-04

An AI assistant acting for a patient should not follow this page. It uses the [agent quickstart](https://docs.hi-doctor.ai/ai/quickstart.md), where sign-in happens on hi-doctor.ai through the [MCP connector](https://docs.hi-doctor.ai/mcp/connect.md).

## What do you need before the first call?

* A patient account that has completed [sign-up and email verification](https://docs.hi-doctor.ai/api-reference/signup.md), used with that patient's consent.
* A server-side application that can keep secrets. The patient types their password into your application, never into a chat or a model prompt.
* The API origin, `https://api.hi-doctor.ai`. To check that it is reachable, call `GET /v1/system/healthcheck/`; the root URL returns `404` by design.

## How do you make the first authenticated read?

**1. Set the API origin**

Configure `HD_BASE_URL=https://api.hi-doctor.ai` explicitly and refuse any other origin before you attach a token.

**2. Sign the patient in**

Send `POST /v1/users/token/` with `Content-Type: application/json`, `X-Brand-Slug: hi-doctor` and a JSON object containing `email` and `password`. Build the JSON with your client library, never by interpolating credentials into a shell command.

**3. Store the tokens securely**

A `200` response contains `access` and `refresh`. Keep them in secure server-side storage and supply the access token to your code as `HD_ACCESS_TOKEN`. Never log them.

**4. Read the profile**

Call `GET /v1/users/profile/me/` with `Authorization: Bearer` and the access token, plus `X-Brand-Slug: hi-doctor`. The examples below do exactly this.

A sign-in request body looks like this:

```json theme={null}
{ "email": "patient@example.com", "password": "<entered by the patient>" }
```

Wrong credentials return `401` with `code: "invalid_credentials"`. While the emailed verification code is still valid, sign-in with the registered password returns `401` with `code: "verification_required"`; once the code has expired the same request returns `invalid_credentials`. A Google-only account returns `401` with `code: "google_account"`. [Authentication](https://docs.hi-doctor.ai/api-reference/authentication.md) covers every sign-in failure and token refresh.

## Read your own profile

Send `X-Brand-Slug: hi-doctor` on every request. It grants no permissions. A REST access token is not an MCP token.

Each example is independent and performs one read. GET has no body; `Accept: application/json` requests JSON. For endpoints with a JSON body, also send `Content-Type: application/json`.

```bash curl theme={null}
: "${HD_BASE_URL:?Set the API origin explicitly}"
: "${HD_ACCESS_TOKEN:?Supply a token securely}"
case "$HD_BASE_URL" in
  https://api.hi-doctor.ai) ;;
  *) exit 1 ;;
esac
curl --silent --show-error --fail --max-time 15 \
  --output /dev/null --write-out 'Profile HTTP %{http_code}\n' \
  "$HD_BASE_URL/v1/users/profile/me/" \
  -H "Authorization: Bearer $HD_ACCESS_TOKEN" \
  -H "X-Brand-Slug: hi-doctor" \
  -H "Accept: application/json"
```

```javascript JavaScript (Node.js) theme={null}
const base = process.env.HD_BASE_URL;
const token = process.env.HD_ACCESS_TOKEN;
if (base !== "https://api.hi-doctor.ai" || !token) {
  throw new Error("Configure an approved API origin and its access token");
}
const response = await fetch(`${base}/v1/users/profile/me/`, {
  headers: {
    Authorization: `Bearer ${token}`,
    "X-Brand-Slug": "hi-doctor",
    Accept: "application/json",
  },
  redirect: "error",
  signal: AbortSignal.timeout(15000),
});
if (!response.ok) throw new Error(`Profile HTTP ${response.status}`);
if (!response.headers.get("content-type")?.includes("application/json")) {
  throw new Error("Unexpected profile response format");
}
const profile = await response.json();
console.log("Profile loaded"); // Use profile in the application; do not log it.
```

```python Python (standard library) theme={null}
import json
import os
import urllib.error
import urllib.request

base = os.environ["HD_BASE_URL"]
token = os.environ["HD_ACCESS_TOKEN"]
if base != "https://api.hi-doctor.ai" or not token:
    raise ValueError("Configure an approved API origin and its access token")

class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None

request = urllib.request.Request(base + "/v1/users/profile/me/", headers={
    "Authorization": "Bearer " + token,
    "X-Brand-Slug": "hi-doctor",
    "Accept": "application/json",
})
try:
    with urllib.request.build_opener(NoRedirect).open(request, timeout=15) as response:
        if response.headers.get_content_type() != "application/json":
            raise ValueError("Unexpected profile response format")
        profile = json.load(response)
except urllib.error.HTTPError as error:
    raise RuntimeError(f"Profile HTTP {error.code}") from None
print("Profile loaded")  # Use profile in the application; do not log it.
```

Success is HTTP `200` with one account object. `401` requires authentication recovery; it is not evidence that the patient has no account. The [error guide](https://docs.hi-doctor.ai/api-reference/errors.md) explains recovery without logging raw response bodies.

## How do lists work?

REST does not have a universal cursor envelope. Consultations, categories and most collections return `count`, `next`, `previous`, `results` with `limit`/`offset` pagination. The default is 50 rows, maximum 200 on the default paginator. Journal and adverse-event lists have no documented maximum; request a small page. Orders and documents return arrays; pending subscription choices use a `pending` array.

Follow `next` until `null`. Before attaching a bearer token, require the same HTTPS origin and expected collection path, reject credentials/fragments in the URL, and disable redirects. Keep filters and ordering unchanged; cap page count, detect repeated URLs and deduplicate records by ID because offset pages can shift.

MCP list tools have their own schemas and concise fields (`total_count`, `has_more`, `next_offset`); do not assume the REST envelope applies. See [pagination](https://docs.hi-doctor.ai/api-reference/pagination.md) and [MCP workflows](https://docs.hi-doctor.ai/mcp/workflows.md).

## Frequently asked questions

### Can I test the API without a patient account?

Only the public endpoints. The health check, questionnaire categories and questionnaire schemas need no token; everything that reads or changes patient data needs a verified patient account and its access token.

### How long does an access token last?

An access token lasts one day and a refresh token 30 days. Refresh the access token as described in [Authentication](https://docs.hi-doctor.ai/api-reference/authentication.md).

### Why does sign-in return 401 for a new account?

While the emailed code is still valid, password sign-in returns 401 with the verification required code; after the code expires it returns 401 with the invalid credentials code. Finish [sign-up and email verification](https://docs.hi-doctor.ai/api-reference/signup.md) first.

### Can I paste a token into an AI chat to test it?

No. Never paste passwords, verification codes or tokens into an AI chat. An assistant should use the [MCP connector](https://docs.hi-doctor.ai/mcp/connect.md) instead.

### Does this quickstart change any data?

No. Every example is a read. Submitting a questionnaire, paying and sending messages are covered in the guides linked under Next steps.

## Next steps

* [Answer a questionnaire](https://docs.hi-doctor.ai/api-reference/questionnaire-guide.md): Ask one question at a time while Hi Doctor applies the branching and validation.
* [Safe retries](https://docs.hi-doctor.ai/api-reference/idempotency.md): Retry a timed-out write without doing it twice, using Idempotency-Key.
* [Uploads and downloads](https://docs.hi-doctor.ai/api-reference/uploads-downloads.md): Upload photos and documents, and save PDFs safely.
* [API changelog](https://docs.hi-doctor.ai/api-reference/changelog.md): What changed in the patient REST API, and when.


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