> ## 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.

# Partner API questionnaires: schema and answer format

> Fetch a Hi Doctor questionnaire schema with the Partner API, render its steps and display rules, and send answers in the entries-v1 format.

The Partner API serves the same questionnaire that the reviewing doctor reads, as a versioned schema of ordered steps. You fetch it per product, render its steps and display rules in your own interface, and send the patient's answers back in the entries-v1 format with the schema version and hash. Nothing is translated or remapped between the patient's answer and the doctor's screen.

Last reviewed: 2026-11-04

There is no separate partner format. The doctor sees exactly the questions and answers your patient saw, so render every step the schema asks for and apply its display rules before you [submit the consultation](https://docs.hi-doctor.ai/partners/submit-a-consultation.md).

## Fetch the schema

`GET /v1/partner/questionnaires/{slug}?product_id=<product_id>&locale=<locale>`

The `slug` is the product's `questionnaire_slug` from `GET /v1/partner/products`. The optional `product_id` query parameter picks the product the schema is served for, when several of your products share a slug. The endpoint does not read `country`.

### Labels and `locale`

* Without `locale`, labels carry message keys only, and `locale` in the response is `null`.
* With `locale=en`, `locale=es` or `locale=zh`, labels and help text are written in that language. Any other value falls back to English (`en`), and so does any single message missing in the requested language. The response's `locale` says which language was used.
* Every localisable field keeps its message key in a `<field>Key` sibling (for example `labelKey`) either way, so you can use your own translations.
* `schema_hash` is the hash of exactly the schema in the response, so it differs per locale. Submit `schema_version` with the hash you received: the current version's hash is accepted with or without a locale and in any supported locale.

```json theme={null}
{
  "slug": "weight-management",
  "schema_version": "<published version id>",
  "schema_hash": "<sha256 of the served schema>",
  "locale": "es",
  "answer_format": "entries-v1",
  "upload_answer": { "value": "<upload_id>" },
  "schema": {
    "steps": [
      {
        "key": "<question_key>",
        "kind": "single",
        "title": "<localised title>",
        "options": [
          { "value": "<option value>", "label": "<localised label>", "labelKey": "<message key>" }
        ]
      }
    ]
  }
}
```

| Field | Meaning |
| - | - |
| `schema_version` | Identifier of the published questionnaire version. Send it back when you submit. |
| `schema_hash` | SHA-256 of the served schema, localised when `locale` is set. Send it back when you submit. |
| `locale` | The language the labels are written in, or `null` when you did not ask for one. |
| `answer_format` | Always `entries-v1` in API v1. |
| `upload_answer` | Reminder of the upload answer shape: a scalar `value` holding an `upload_id`. |
| `schema.steps` | Ordered list of steps. Render them in this order. The step above is shortened; real steps carry the properties described in [Steps](#steps). |

## Versions and `schema_outdated`

Hi Doctor's medical team updates questionnaires from time to time. Cache the schema by `schema_version`, and send both `schema_version` and `schema_hash` with every submission. If they no longer match the published version, the submission fails with `409 schema_outdated` and nothing is created:

```json theme={null}
{
  "error": {
    "type": "conflict",
    "code": "schema_outdated",
    "message": "The questionnaire schema has changed; fetch it again.",
    "current": { "schema_version": "<new version id>", "schema_hash": "<new hash>" },
    "request_id": "req_2b8e41d0"
  }
}
```

Fetch the new schema, ask the patient any new or changed questions, and submit again. Do not map answers from an old version onto a new one without showing the patient the new questions.

## Steps

Every step has a `key` (the `question_key` you answer with), a `kind`, a `title` or label, and an optional `required` flag (steps are required unless `required` is `false`). Kind-specific properties are listed below.

| `kind` | What the patient does | Answer shape |
| - | - | - |
| `single` or `select` | Picks one option from `options`. | `"value": "<option value>"` |
| `confirm` | Confirms a statement, or picks one confirmation option. | `"value": true`, or `"value": "<option value>"` when the step has `options` |
| `multi` | Picks one or more options. | `"value": ["<option value>", ...]` |
| `multi-with-input` | Picks options, some of which ask for extra text. | `"value": [...]` plus `"option_inputs": {...}` |
| `input` | Fills one or more `fields`, such as height and weight. | `"values": { "<field name>": <value>, ... }` |
| `likert-grid` or `iief5` | Rates each grid question on the grid's scale. | `"values": { "<question key>": <scale value>, ... }` |
| `upload` | Provides a photo or document. | `"value": "<upload_id>"` |

### Options

Option steps carry `options: [{ value, label, ... }]`; some group them under `sections[].options`. An option can be marked as excluding: when the patient picks it, the questionnaire stops because treatment is not possible through this route. Show the step's exclusion message and do not submit. If you do, the submission fails with `422 clinical_ineligibility`. An option that needs extra detail asks for it through `option_inputs`, keyed by option value.

### Fields and validation

`input` steps carry `fields: [{ name, label, validation }]`. `validation` can include `required` (default true), `type` (for example `number`), and bounds such as `min` and `max`. Values outside plain bounds fail with `422 out_of_range`. Bounds that also carry a `reasonKey` or `blockedReasonKey` are eligibility rules, not typing guards: a value outside them fails with `422 clinical_ineligibility`, so treat it as an exclusion. Some steps carry step-level validation, such as a body-mass-index threshold computed from height and weight; when it fails, treat it as an exclusion.

### Conditional display

A step with `conditionalDisplay` is shown only when an earlier answer matches:

```json theme={null}
{
  "key": "pregnancy_status",
  "kind": "single",
  "conditionalDisplay": { "questionKey": "sex", "operator": "equals", "value": "female" }
}
```

| Operator | Shown when the earlier answer |
| - | - |
| `equals` (default) | equals `value`, or for a list answer contains `value` |
| `not_equals` | differs from `value`, or for a list answer does not contain it |
| `in` | is one of `values`, or for a list answer shares any item with `values` |
| `not_in` | is none of `values`, or for a list answer shares no item with `values` |

A step can also carry `bmiConditionalDisplay` with `minBMI` and/or `maxBMI`: it is shown only when the body-mass index computed from the height and weight step is at least `minBMI` and below `maxBMI`. If the step it depends on was skipped or has no answer, the dependent step is not shown either.

Hi Doctor decides which steps apply from the answers you send. Steps that apply and are required must be answered. Answer only the steps that apply: an answer to a step that the other answers hide is refused with `422 unexpected_question_key`, with one error item per hidden `question_key`. This follows dependency chains, so a step hidden because the step it depends on is hidden is refused too. Apply the display rules yourself before you submit.

### Conditional fields

`conditionalFields` adds follow-up `fields` inside a multiple-choice step. The follow-up fields apply when **any** selected value is outside `dismissValues` (for example, anything other than "none of these"). Send each follow-up value in the same entry under `option_inputs`, with the key `__cf_<field name>`:

```json theme={null}
{ "question_key": "prior_treatments", "value": ["minoxidil"], "option_inputs": { "__cf_treatment_duration": "6 months" } }
```

Follow-up values sent under `values`, or under `option_inputs` without the `__cf_` prefix, are not found, and a required follow-up field then fails validation.

## The `entries-v1` answer format

`answers` is an array with one entry per answered step. Each entry has `question_key` and exactly one of `value`, `values` or `skip`. At submission `question_key` is required and must be a non-empty string: an entry without one fails with `422 invalid_answers`. Answers to an information request also accept the alias `key` and use their own error codes; see [Information requests](https://docs.hi-doctor.ai/partners/information-requests.md#answer-the-request).

```json theme={null}
[
  { "question_key": "sex", "value": "female" },
  { "question_key": "conditions", "value": ["hypertension", "type_2_diabetes"] },
  { "question_key": "height_weight", "values": { "height": 172, "weight": 96 } },
  { "question_key": "medication_history", "value": ["other"], "option_inputs": { "other": "Name and dose of the medicine" } },
  { "question_key": "safety_statement", "value": true },
  { "question_key": "body_photo", "value": "1f0e8f5c-6a1b-4d0b-9a55-0c2f1e9a7b31" },
  { "question_key": "optional_notes_photo", "skip": true }
]
```

The keys above are illustrative. Use the keys from the schema you fetched.

* Upload answers are a scalar `value` holding the `upload_id` returned by `POST /v1/partner/files`. See [Photos and files](https://docs.hi-doctor.ai/partners/photos.md).
* `skip: true` is only accepted for steps whose `required` is `false`. A skipped entry carries just `question_key`, `skip` and, optionally, the step's own `step_id`. Any other member alongside it, such as `value`, `values` or `option_inputs`, fails with `422 invalid_answers`.
* Do not send answers for steps that are not shown. An answer to a hidden step is refused with `422 unexpected_question_key`, one error item per hidden `question_key` (see [Conditional display](#conditional-display)).
* A key that is neither a step in the schema nor an envelope key fails validation. See [Envelope keys](#envelope-keys).

### Envelope keys

Envelope keys are answer entries that sit outside the schema's steps. Each has its own fixed shape:

| `question_key` | Shape | Use |
| - | - | - |
| `pickup_location` | `values` holding exactly `country`, `city` and `postal_code`, as strings | Where the patient will use the prescription. Its country must match the request `country` (see [Country binding](https://docs.hi-doctor.ai/partners/submit-a-consultation.md#country-binding)). |
| `pharmacy_selection` | Exactly `question_key` and `values` | The pharmacy the patient chose, in countries where the prescription goes to a pharmacy the patient picks. It is checked against the patient's pickup country; an invalid one is refused. Leave it out unless Hi Doctor has asked you to send it. |

## How are answer errors reported?

Answer problems return `422`. When the API can tie a problem to a step, `errors` names its `question_key`, so you can point the patient back to the right step. Not every answer error carries `errors` or a `question_key`: when it is missing, show a general error and let the patient review their answers. Range errors name the `field` and its bounds:

```json theme={null}
{
  "error": {
    "type": "validation_error",
    "code": "out_of_range",
    "message": "A value is outside the schema's input bounds.",
    "errors": [
      {
        "question_key": "height_weight",
        "field": "weight",
        "code": "out_of_range",
        "message": "The value is outside the allowed range.",
        "min": 30,
        "max": 300
      }
    ],
    "request_id": "req_91ad0c7e"
  }
}
```

Every code and its meaning is listed in [Partner API errors](https://docs.hi-doctor.ai/partners/errors.md#submission).

## Frequently asked questions

### Is the partner questionnaire different from Hi Doctor's own?

No. The Partner API serves the same questionnaire the doctor's review is based on, so you render it instead of designing your own questions.

### Which languages can the schema be served in?

Labels and help text are served in English (en), Spanish (es) or Chinese (zh) when you pass the locale parameter; any other value falls back to English. Every label also keeps its message key, so you can use your own translations.

### How do I know the questionnaire has changed?

Send schema\_version and schema\_hash with every submission. If they are no longer the published ones, the submission fails with 409 schema\_outdated and nothing is created, so fetch the schema again and ask the patient any new questions.

### Do I have to apply the conditional display rules myself?

Yes. Hi Doctor works out which steps apply from the answers you send and refuses answers to hidden steps, so apply the conditionalDisplay and bmiConditionalDisplay rules before you submit.

### What should I do when the patient picks an excluding option?

Stop the questionnaire and show the step's exclusion message. Treatment is not possible through this route, and submitting anyway fails with 422 clinical\_ineligibility.

### Can the patient skip a question?

Only a step marked as not required. Send it as an entry with its question\_key and skip set to true, and nothing else.

### How do I answer a photo step?

Upload the file with POST /v1/partner/files first, then answer the step with the returned upload\_id as a single value. See [Photos and files](https://docs.hi-doctor.ai/partners/photos.md).

## Next steps

> [card] [Submit a consultation](https://docs.hi-doctor.ai/partners/submit-a-consultation.md)
>
> Send the answers with the product, patient and consent in one request.

> [card] [Photos and files](https://docs.hi-doctor.ai/partners/photos.md)
>
> Upload photos and documents before you answer upload steps.

> [card] [Partner API errors](https://docs.hi-doctor.ai/partners/errors.md)
>
> Every error code, including answer validation errors.

> [card] [Partnership FAQ](https://docs.hi-doctor.ai/partnerships/faq.md)
>
> Commercial questions about partnering with Hi Doctor.


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