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

# Schedule an Appointment

> Step-by-step guide to booking a blood draw appointment

Use this guide to find a test location, create an appointment for a patient profile, and attach the test panels to run. Complete these steps before the patient arrives for their blood draw.

<Steps>
  <Step title="Browse available locations">
    Retrieve the list of test locations available on your account by sending a `GET` request to `/api/v1/locations`.

    <CodeGroup>
      ```bash cURL theme={null}
      curl --request GET \
        --url https://anivahealth.com/api/v1/locations \
        --header 'x-api-key: YOUR_API_KEY'
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch('https://anivahealth.com/api/v1/locations', {
        headers: {
          'x-api-key': 'YOUR_API_KEY',
        },
      });

      const locations = await response.json();
      ```
    </CodeGroup>

    The response is an array of location objects:

    ```json theme={null}
    [
      {
        "id": "b7e2d914-1c3a-4f08-9e5b-6d0f7a83c421",
        "name": "Aniva Berlin Mitte",
        "company_name": "Aniva GmbH",
        "address_line_1": "Friedrichstraße 112",
        "address_line_2": null,
        "city": "Berlin",
        "state": "Berlin",
        "postal_code": "10117",
        "country_name": "Germany",
        "country_code": "DE",
        "timezone": "Europe/Berlin",
        "contact_phone": "+4930987654321",
        "email": "berlin-mitte@anivahealth.com",
        "website": "https://anivahealth.com",
        "google_maps_url": null,
        "image_url": null,
        "open_hours": {
          "monday": [{ "open": "08:00", "close": "17:00" }],
          "tuesday": [{ "open": "08:00", "close": "17:00" }],
          "wednesday": [{ "open": "08:00", "close": "17:00" }],
          "thursday": [{ "open": "08:00", "close": "17:00" }],
          "friday": [{ "open": "08:00", "close": "15:00" }],
          "saturday": [],
          "sunday": []
        }
      }
    ]
    ```

    <Tip>
      Use the `timezone` field from the location object when constructing your `scheduled_at` timestamp. Converting the appointment time to the location's local timezone helps you avoid scheduling outside of open hours.
    </Tip>
  </Step>

  <Step title="Create the appointment">
    Send a `POST` request to `/api/v1/appointments` with the profile ID, location ID, and your desired appointment time.

    <Note>
      `scheduled_at` must be a future datetime in ISO 8601 format, for example `2026-05-12T07:30:00Z`. Timestamps in the past are rejected with a `400` error.
    </Note>

    <CodeGroup>
      ```bash cURL theme={null}
      curl --request POST \
        --url https://anivahealth.com/api/v1/appointments \
        --header 'Content-Type: application/json' \
        --header 'x-api-key: YOUR_API_KEY' \
        --data '{
          "profile_id": "a3f1c2e4-58b7-4d9e-b012-3c7f8a2e1d56",
          "location_id": "b7e2d914-1c3a-4f08-9e5b-6d0f7a83c421",
          "scheduled_at": "2026-05-12T07:30:00Z"
        }'
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch('https://anivahealth.com/api/v1/appointments', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': 'YOUR_API_KEY',
        },
        body: JSON.stringify({
          profile_id: 'a3f1c2e4-58b7-4d9e-b012-3c7f8a2e1d56',
          location_id: 'b7e2d914-1c3a-4f08-9e5b-6d0f7a83c421',
          scheduled_at: '2026-05-12T07:30:00Z',
        }),
      });

      const appointment = await response.json();
      ```
    </CodeGroup>

    A successful request returns `201 Created` with the appointment object:

    ```json theme={null}
    {
      "id": "c9d4e827-3b6f-4a1c-8d2e-5f0b9c7e3a12",
      "profile_id": "a3f1c2e4-58b7-4d9e-b012-3c7f8a2e1d56",
      "location_id": "b7e2d914-1c3a-4f08-9e5b-6d0f7a83c421",
      "scheduled_at": "2026-05-12T07:30:00Z",
      "status": "confirmed",
      "test_method": "practitioner",
      "created_at": "2026-04-01T11:02:47Z",
      "updated_at": null,
      "profile": {
        "id": "a3f1c2e4-58b7-4d9e-b012-3c7f8a2e1d56",
        "first_name": "Emma",
        "last_name": "Müller",
        "email": "emma.muller@example.com"
      },
      "panels": []
    }
    ```

    Save the appointment `id` — you'll need it to add panels and confirm the blood draw.
  </Step>

  <Step title="Add test panels">
    Attach the test panels you want run on the blood sample by sending a `POST` request to `/api/v1/appointments/{id}/panels`.

    Panel IDs are UUIDs provided by Aniva for your partner account. Contact Aniva if you need the list of available panel IDs.

    <Warning>
      Panels cannot be added after the blood draw has been confirmed. Add all required panels before confirmation — see [Confirm Blood Draw](/guides/confirm-blood-draw) for details.
    </Warning>

    <CodeGroup>
      ```bash cURL theme={null}
      curl --request POST \
        --url https://anivahealth.com/api/v1/appointments/c9d4e827-3b6f-4a1c-8d2e-5f0b9c7e3a12/panels \
        --header 'Content-Type: application/json' \
        --header 'x-api-key: YOUR_API_KEY' \
        --data '{
          "panel_ids": [
            "d1f5a302-7c8e-4b2d-9f1a-0e3c6d4b8a27",
            "e2a7b491-5d9f-4c3e-8a2b-1f4d7e5c9b38"
          ]
        }'
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch(
        'https://anivahealth.com/api/v1/appointments/c9d4e827-3b6f-4a1c-8d2e-5f0b9c7e3a12/panels',
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'x-api-key': 'YOUR_API_KEY',
          },
          body: JSON.stringify({
            panel_ids: [
              'd1f5a302-7c8e-4b2d-9f1a-0e3c6d4b8a27',
              'e2a7b491-5d9f-4c3e-8a2b-1f4d7e5c9b38',
            ],
          }),
        }
      );

      const result = await response.json();
      ```
    </CodeGroup>

    A successful request returns `200 OK` confirming the panels have been added:

    ```json theme={null}
    {
      "success": true
    }
    ```
  </Step>
</Steps>

## Rescheduling or cancelling

After creating an appointment, you can still modify it before the blood draw is confirmed:

* **Reschedule or change location** — Send a `PATCH` request to `/api/v1/appointments/{id}` with the fields to update. See [Update Appointment](/api/appointments/update-appointment).
* **Cancel** — Send a `DELETE` request to `/api/v1/appointments/{id}`. See [Cancel Appointment](/api/appointments/cancel-appointment).

<Note>
  Both operations are only available before the blood draw — i.e. while the appointment is in
  `pending` or `confirmed` status. Once the appointment moves to `blood_drawn`, no further
  modifications are possible.
</Note>

## Error handling

| Status            | Cause                                                                                                  | Resolution                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| `400 Bad Request` | A required field is missing, `scheduled_at` is in the past, or `panel_ids` is empty.                   | Check the error body for the validation message and correct the request. |
| `403 Forbidden`   | Your API key does not have access to this operation.                                                   | Contact Aniva to confirm your API key permissions.                       |
| `404 Not Found`   | The `profile_id` or `location_id` does not exist, or the appointment ID is invalid when adding panels. | Verify the IDs are correct and belong to your account.                   |
| `409 Conflict`    | You attempted to add panels to or modify an appointment that has already been confirmed or cancelled.  | No further changes are possible after confirmation.                      |
