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

# Create Appointment

> Schedule a blood draw appointment for a profile at a test location

Schedule a blood draw appointment for a patient profile at a specific test location. Once created, the appointment enters `confirmed` status by default (some locations may instead default to `pending` — this is a per-location setting). Use [Add Panels](/api/appointments/add-panels) to attach blood test panels before [confirming the blood draw](/api/appointments/confirm-blood-draw).

## Request

### Body parameters

<ParamField body="profile_id" type="string" required>
  UUID of the patient profile to create the appointment for.
</ParamField>

<ParamField body="location_id" type="string" required>
  UUID of the test location where the blood draw will take place. Use [List
  Locations](/api/locations/list-locations) to find available location IDs.
</ParamField>

<ParamField body="scheduled_at" type="string" required>
  Date and time of the appointment in ISO 8601 format (e.g., `2026-05-15T10:30:00Z` or
  `2026-05-15T12:30:00+02:00`). **Must include a timezone designator** — either `Z` or an explicit
  offset like `+02:00`; naive datetimes are rejected. Must be in the future.
</ParamField>

## Response

On success, the API returns `201 Created` with the new appointment.

<ResponseField name="id" type="string" required>
  Unique appointment identifier (UUID).
</ResponseField>

<ResponseField name="profile_id" type="string" required>
  UUID of the profile this appointment belongs to.
</ResponseField>

<ResponseField name="location_id" type="string">
  UUID of the test location. `null` for home kit appointments.
</ResponseField>

<ResponseField name="scheduled_at" type="string">
  Scheduled appointment datetime as a UTC instant (ISO 8601 with `Z` suffix, e.g.
  `2026-05-15T10:30:00Z`). May be `null`.
</ResponseField>

<ResponseField name="status" type="string" required>
  Current appointment status. One of `pending`, `confirmed`, `blood_drawn`, or `cancelled`.
  Lab-result completion granularity is derived from [Get Results](/api/appointments/get-results);
  finer-grained shipment progression from each entry in the inline `shipments` array (see below)
  followed to [Get Shipment](/api/shipments/get-shipment).
</ResponseField>

<ResponseField name="test_method" type="string">
  Method used for the blood draw. One of `practitioner` or `home`. May be `null`.
</ResponseField>

<ResponseField name="cancellation_reason" type="string">
  Free-text reason captured when the appointment was cancelled (e.g. no-show, late cancellation,
  'Failed. Repeat required'). `null` unless `status` is `cancelled`.
</ResponseField>

<ResponseField name="profile" type="object" required>
  The patient profile associated with this appointment.

  <Expandable title="profile">
    <ResponseField name="id" type="string">
      Unique profile identifier (UUID).
    </ResponseField>

    <ResponseField name="handle" type="string">
      Profile handle or username. May be `null`.
    </ResponseField>

    <ResponseField name="first_name" type="string">
      First name. May be `null`.
    </ResponseField>

    <ResponseField name="last_name" type="string">
      Last name. May be `null`.
    </ResponseField>

    <ResponseField name="email" type="string">
      Email address. May be `null`.
    </ResponseField>

    <ResponseField name="phone" type="string">
      Phone number in E.164 format. May be `null`.
    </ResponseField>

    <ResponseField name="sex" type="integer">
      Biological sex per ISO/IEC 5218. May be `null`.
    </ResponseField>

    <ResponseField name="date_of_birth" type="string">
      Date of birth in `YYYY-MM-DD` format. May be `null`.
    </ResponseField>

    <ResponseField name="height" type="number">
      Height in centimeters. May be `null`.
    </ResponseField>

    <ResponseField name="weight" type="number">
      Weight in kilograms. May be `null`.
    </ResponseField>

    <ResponseField name="language" type="string">
      Preferred language (`en`, `de`, or `fi`).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="panels" type="AppointmentPanel[]" required>
  Panels currently attached to this appointment. Empty for newly-created appointments — attach via
  [Add Panels](/api/appointments/add-panels). Look up panel details (name, biomarkers) via
  [List Panels](/api/panels/list-panels).

  <Expandable title="Panel attachment fields">
    <ResponseField name="panel_id" type="string">
      Panel UUID — cross-reference against [List Panels](/api/panels/list-panels).
    </ResponseField>

    <ResponseField name="added_at" type="string">
      ISO 8601 timestamp the panel was first attached to this appointment.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="individual_biomarkers" type="AppointmentIndividualBiomarker[]" required>
  À-la-carte biomarkers attached to this appointment outside any panel. Empty for newly-created
  appointments — attach via [Add Individual Biomarkers](/api/appointments/add-individual-biomarkers).
  Cross-reference each `biomarker_id` against [List Biomarkers](/api/biomarkers/list-biomarkers)
  for display data.

  <Expandable title="Individual biomarker fields">
    <ResponseField name="biomarker_id" type="integer">
      Biomarker identifier — cross-reference against
      [List Biomarkers](/api/biomarkers/list-biomarkers).
    </ResponseField>

    <ResponseField name="added_at" type="string">
      ISO 8601 timestamp the biomarker was first attached to this appointment.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="shipments" type="AppointmentShipmentLink[]" required>
  Shipments linked to this appointment, oldest-link first. Empty for newly-created appointments —
  link via [Create Shipment](/api/shipments/create-shipment) (with `appointment_id`) or
  [Attach Shipments to Appointment](/api/appointments/attach-shipments-to-appointment).

  <Expandable title="Shipment link fields">
    <ResponseField name="id" type="string">
      Shipment reference identifier — cross-reference against
      [Get Shipment](/api/shipments/get-shipment).
    </ResponseField>

    <ResponseField name="added_at" type="string">
      ISO 8601 timestamp the shipment was first linked to this appointment.
    </ResponseField>
  </Expandable>
</ResponseField>

## Error responses

| Status | Description                                                      |
| ------ | ---------------------------------------------------------------- |
| `400`  | Validation error — e.g., `scheduled_at` is in the past.          |
| `403`  | Forbidden — your API key does not have access to this operation. |
| `404`  | Profile or location not found.                                   |
| `500`  | Internal server error.                                           |

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://anivahealth.com/api/v1/appointments \
    --header 'x-api-key: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "profile_id": "a3f1c2d4-8b7e-4f2a-9c1d-2e3f4a5b6c7d",
      "location_id": "b7e2d1f5-3c4a-4e8b-a2f1-9d0c1e2f3a4b",
      "scheduled_at": "2026-05-15T10:30:00Z"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "id": "c9f3e2a1-7d6b-4c5e-b3a2-1f0e9d8c7b6a",
    "profile_id": "a3f1c2d4-8b7e-4f2a-9c1d-2e3f4a5b6c7d",
    "location_id": "b7e2d1f5-3c4a-4e8b-a2f1-9d0c1e2f3a4b",
    "scheduled_at": "2026-05-15T10:30:00Z",
    "status": "confirmed",
    "test_method": "practitioner",
    "cancellation_reason": null,
    "created_at": "2026-04-01T09:45:00Z",
    "updated_at": null,
    "profile": {
      "id": "a3f1c2d4-8b7e-4f2a-9c1d-2e3f4a5b6c7d",
      "handle": null,
      "first_name": "Maria",
      "last_name": "Schmidt",
      "email": "maria.schmidt@example.com",
      "phone": "+4930123456789",
      "sex": 2,
      "date_of_birth": "1985-03-22",
      "height": 168,
      "weight": 65,
      "language": "de",
      "created_at": "2026-04-01T09:14:32Z",
      "updated_at": null
    },
    "panels": [],
    "individual_biomarkers": [],
    "shipments": []
  }
  ```

  ```json 400 theme={null}
  {
    "error": "scheduled_at must be a datetime in the future"
  }
  ```

  ```json 404 theme={null}
  {
    "error": "Location not found"
  }
  ```
</ResponseExample>
