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

# Get an idempotency key result

> Looks up the stored outcome of a write that was sent with an `Idempotency-Key` header. Use it to reconcile after a timeout or a lost response: it reports the final `state`, the original HTTP status and the identifiers of the resources the request created or changed. It never returns the original response body, so read those resources to recover their content. The lookup reads the primary database and never calls a provider or writes. Unknown keys, keys owned by another account or brand, and keys older than 30 days return 404. A request that is still running is not visible yet, so a 404 during execution does not prove the write did not happen.

### Access, effects and retries
**Ownership:** Keys are scoped to the signed-in account and the request brand.

**Prerequisites:** Authentication required. with a bearer JWT.

**Effects:** None. Read-only; no provider call.

**Retries:** Safe to repeat. Poll with backoff while the original request may still be running.



## OpenAPI

````yaml /api-reference/openapi.json get /v1/users/idempotency/{key}/
openapi: 3.0.3
info:
  title: Hi Doctor API
  version: 1.0.1
  description: >-
    The patient-facing Hi Doctor API supports account management, consultation
    questionnaires, medical documents, messages and billing. Sign-in requires
    X-Brand-Slug: hi-doctor; authenticated requests use Authorization: Bearer
    <access> with a JWT access token. See
    https://docs.hi-doctor.ai/api-reference/introduction for integration guides.
  contact:
    name: Hi Doctor
    email: hello@hi-doctor.ai
    url: https://docs.hi-doctor.ai
servers:
  - url: https://api.hi-doctor.ai
    description: Production
security: []
tags:
  - name: Account
    description: Register, verify, authenticate and manage the signed-in account.
  - name: Questionnaires
    description: Discover, save and submit consultation questionnaires.
  - name: Consultations
    description: Read consultation state and manage consultation photographs.
  - name: Prescriptions
    description: Retrieve issued prescription documents and request reissue.
  - name: Messages
    description: Read and send messages to the medical team, and download attachments.
  - name: Billing
    description: >-
      Create checkout, manage subscriptions and retrieve
      payments/invoices/credit notes.
  - name: Records
    description: Read orders and manage patient health documents.
  - name: Safety reports
    description: Submit and read suspected side-effect reports; no automated diagnosis.
  - name: Progress
    description: Record and review eligible weight-loss progress.
  - name: Referrals
    description: Read the signed-in account's referral summary and referral activity.
paths:
  /v1/users/idempotency/{key}/:
    get:
      tags:
        - Account
      summary: Get an idempotency key result
      description: >-
        Looks up the stored outcome of a write that was sent with an
        `Idempotency-Key` header. Use it to reconcile after a timeout or a lost
        response: it reports the final `state`, the original HTTP status and the
        identifiers of the resources the request created or changed. It never
        returns the original response body, so read those resources to recover
        their content. The lookup reads the primary database and never calls a
        provider or writes. Unknown keys, keys owned by another account or
        brand, and keys older than 30 days return 404. A request that is still
        running is not visible yet, so a 404 during execution does not prove the
        write did not happen.


        ### Access, effects and retries

        **Ownership:** Keys are scoped to the signed-in account and the request
        brand.


        **Prerequisites:** Authentication required. with a bearer JWT.


        **Effects:** None. Read-only; no provider call.


        **Retries:** Safe to repeat. Poll with backoff while the original
        request may still be running.
      operationId: users_idempotency_retrieve
      parameters:
        - in: path
          name: key
          required: true
          schema:
            type: string
            pattern: ^[A-Za-z0-9_-]{8,128}$
          description: >-
            The Idempotency-Key value sent with the original write: 8 to 128
            ASCII letters, digits, underscores or hyphens.
          example: checkout-2026-10-07-7f3a9c
      responses:
        '200':
          description: The stored outcome of the keyed request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IdempotencyReceipt'
              examples:
                example-1:
                  summary: Illustrative response example
                  value:
                    state: succeeded
                    method: POST
                    route: users:create-checkout
                    response_status: 201
                    resource_ids:
                      checkoutsession:
                        - 3f1d2c4b-8a8e-4c1e-9a55-1f2e3d4c5b6a
                    created_at: '2026-10-07T09:15:02.481Z'
        '401':
          description: >-
            No bearer token, or a token that is expired or malformed.
            Re-authenticate; do not retry the same token.
          content:
            application/json:
              schema:
                type: object
                description: >-
                  Error envelope emitted by the source branch or DRF validation.
                  `detail`, `error` and `code` depend on the branch; field
                  validation uses lists keyed by request field.
                additionalProperties: {}
              examples:
                example-1:
                  summary: Illustrative response example
                  value:
                    detail: Authentication credentials were not provided.
        '403':
          description: The account lacks permission for this operation.
          content:
            application/json:
              schema:
                type: object
                description: >-
                  Error envelope emitted by the source branch or DRF validation.
                  `detail`, `error` and `code` depend on the branch; field
                  validation uses lists keyed by request field.
                additionalProperties: {}
              examples:
                example-1:
                  summary: Illustrative response example
                  value:
                    detail: You do not have permission to perform this action.
        '404':
          description: >-
            No stored outcome for this key: it is unknown, belongs to another
            account or brand, has expired, or its request is still running.
          content:
            application/json:
              schema:
                type: object
                description: >-
                  Error envelope emitted by the source branch or DRF validation.
                  `detail`, `error` and `code` depend on the branch; field
                  validation uses lists keyed by request field.
                additionalProperties: {}
              examples:
                example-1:
                  summary: Illustrative response example
                  value:
                    detail: Not found.
        '429':
          description: >-
            Too many requests. Wait before retrying; the response may include
            Retry-After.
          content:
            application/json:
              schema:
                type: object
                description: >-
                  Error envelope emitted by the source branch or DRF validation.
                  `detail`, `error` and `code` depend on the branch; field
                  validation uses lists keyed by request field.
                additionalProperties: {}
              examples:
                example-1:
                  summary: Illustrative response example
                  value:
                    detail: Request was throttled.
      security:
        - bearerAuth: []
      x-codeSamples:
        - lang: Shell
          label: curl
          source: >
            set -eu

            umask 077

            # Path values must be URL-encoded; query string excludes the leading
            question mark.

            url="${HD_BASE_URL:?Set API
            origin}/v1/users/idempotency/${HD_PATH_KEY:?Set the path
            fixture}/${HD_QUERY_STRING:+?${HD_QUERY_STRING}}"

            printf 'X-Brand-Slug: hi-doctor\nAccept: application/json\n' >
            "${HD_REQUEST_HEADERS_FILE:?Private header file}"

            printf 'Authorization: Bearer %s\n' "${HD_ACCESS_TOKEN:?Set backend
            JWT}" >> "$HD_REQUEST_HEADERS_FILE"

            curl --silent --show-error --max-time 30 --request GET \
              --header "@$HD_REQUEST_HEADERS_FILE" \
              --dump-header "${HD_HEADERS_FILE:?Private response header file}" \
              --output "${HD_RESPONSE_FILE:?Private response file}" \
              --write-out '%{http_code}\n%{content_type}\n' \
              "$url"
        - lang: Python
          label: requests
          source: >
            import os, json

            from pathlib import Path

            from urllib.parse import quote

            import requests

            os.umask(0o077)

            url = os.environ["HD_BASE_URL"].rstrip("/") +
            '/v1/users/idempotency/{key}/'

            url = url.replace('{key}', quote(os.environ['HD_PATH_KEY'],
            safe=""))

            if os.environ.get("HD_QUERY_STRING"): url += "?" +
            os.environ["HD_QUERY_STRING"]

            headers = {"X-Brand-Slug": "hi-doctor", "Accept":
            'application/json'}

            headers["Authorization"] = "Bearer " + os.environ["HD_ACCESS_TOKEN"]

            kwargs = {}

            response = requests.request('GET', url, headers=headers, timeout=30,
            allow_redirects=False, **kwargs)

            Path(os.environ["HD_RESPONSE_FILE"]).write_bytes(response.content)

            Path(os.environ["HD_HEADERS_FILE"]).write_text(json.dumps(dict(response.headers)))

            print(response.status_code)

            print(response.headers.get("Content-Type", ""))
        - lang: JavaScript
          label: fetch
          source: >
            import { readFileSync, writeFileSync } from "node:fs";

            const env = process.env;

            let url = env.HD_BASE_URL.replace(/\/$/, "") +
            "/v1/users/idempotency/{key}/";

            url = url.replace("{key}", encodeURIComponent(env.HD_PATH_KEY));

            if (env.HD_QUERY_STRING) url += "?" + env.HD_QUERY_STRING;

            const headers = { "X-Brand-Slug": "hi-doctor", "Accept":
            "application/json" };

            headers.Authorization = "Bearer " + env.HD_ACCESS_TOKEN;

            const options = { method: "GET", headers, redirect: "manual",
            signal: AbortSignal.timeout(30000) };

            const response = await fetch(url, options);

            writeFileSync(env.HD_RESPONSE_FILE, Buffer.from(await
            response.arrayBuffer()), {mode: 0o600});

            writeFileSync(env.HD_HEADERS_FILE,
            JSON.stringify(Object.fromEntries(response.headers)), {mode:
            0o600});

            console.log(response.status);

            console.log(response.headers.get("content-type") ?? "");
components:
  schemas:
    IdempotencyReceipt:
      type: object
      properties:
        state:
          allOf:
            - $ref: '#/components/schemas/StateEnum'
          description: >-
            in_progress, succeeded or failed. A failed request rolled back its
            database changes.
        method:
          type: string
          maxLength: 6
          description: HTTP method of the original request.
        route:
          type: string
          maxLength: 200
          description: Route name of the original request.
        response_status:
          type: integer
          nullable: true
          description: >-
            HTTP status the original request returned; null while it is in
            progress.
        resource_ids:
          type: object
          additionalProperties: {}
          description: >-
            Identifiers of the resources the request created, changed or
            deleted, grouped by resource type.
        created_at:
          type: string
          format: date-time
          readOnly: true
          description: When the key was first used.
      required:
        - created_at
        - method
        - route
    StateEnum:
      enum:
        - in_progress
        - succeeded
        - failed
      type: string
      description: in_progress, succeeded or failed.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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