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

# Quickstart

> Create a patient, submit an intake, and place an order end to end.

# Quickstart

This walkthrough runs the complete Vita Clinic loop — patient, intake, order,
webhooks — against a `vr_test_` key. Every call goes to the same base URL you
will use in production:

```
https://vitarelay.com/api/public/v1
```

<Steps>
  <Step title="Get a test key">
    API keys are issued by VitaRelay, not through the API and not self-serve.
    Ask your VitaRelay representative for a **test** key with the
    `patients:write`, `intakes:write`, and `orders:write` scopes. The raw key is shown once — store it in an
    environment variable.

    ```bash theme={null}
    export VITARELAY_API_KEY=vr_test_xxxxxxxxxxxxxxxxxxxx
    ```

    See [API Keys](/getting-started/api-keys) for how keys are issued and
    scoped.
  </Step>

  <Step title="Create a patient">
    Send your own stable identifier as `external_patient_id`. It makes the call
    idempotent and lets you reference the patient later without storing our id.

    <CodeGroup>
      ```bash curl theme={null}
      curl https://vitarelay.com/api/public/v1/patients \
        -H "Authorization: Bearer vr_test_xxxxxxxxxxxxxxxxxxxx" \
        -H "Content-Type: application/json" \
        -d '{
          "external_patient_id": "clinic-patient-001",
          "first_name": "Jane",
          "last_name": "Smith",
          "dob": "1985-04-12",
          "email": "jane.smith@example.com",
          "phone": "+18135550100"
        }'
      ```

      ```javascript JavaScript theme={null}
      const res = await fetch("https://vitarelay.com/api/public/v1/patients", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.VITARELAY_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          external_patient_id: "clinic-patient-001",
          first_name: "Jane",
          last_name: "Smith",
          dob: "1985-04-12",
          email: "jane.smith@example.com",
          phone: "+18135550100",
        }),
      });

      const { data } = await res.json();
      ```
    </CodeGroup>

    Response — `201 Created`:

    ```json theme={null}
    {
      "data": {
        "id": "sandbox_pat_9f2c41d6",
        "external_patient_id": "clinic-patient-001",
        "sandbox": true
      }
    }
    ```

    With a `vr_live_` key, `data.id` is a UUID and `sandbox` is absent.
  </Step>

  <Step title="Submit an intake">
    Reference the patient by the `external_patient_id` you just used.

    <CodeGroup>
      ```bash curl theme={null}
      curl https://vitarelay.com/api/public/v1/intakes \
        -H "Authorization: Bearer vr_test_xxxxxxxxxxxxxxxxxxxx" \
        -H "Content-Type: application/json" \
        -d '{
          "external_intake_id": "clinic-intake-001",
          "external_patient_id": "clinic-patient-001",
          "category": "weight_management",
          "responses": {
            "chief_complaint": "Weight management",
            "current_medications": [],
            "allergies": ["penicillin"]
          }
        }'
      ```

      ```javascript JavaScript theme={null}
      const res = await fetch("https://vitarelay.com/api/public/v1/intakes", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.VITARELAY_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          external_intake_id: "clinic-intake-001",
          external_patient_id: "clinic-patient-001",
          category: "weight_management",
          responses: {
            chief_complaint: "Weight management",
            current_medications: [],
            allergies: ["penicillin"],
          },
        }),
      });

      const { data } = await res.json();
      ```
    </CodeGroup>

    Response — `201 Created`:

    ```json theme={null}
    {
      "data": {
        "id": "sandbox_int_4b7e05a1",
        "external_intake_id": "clinic-intake-001",
        "patient_id": "sandbox_pat_9f2c41d6",
        "status": "submitted",
        "sandbox": true
      }
    }
    ```
  </Step>

  <Step title="Place an order">
    Order items are `product_id` plus `quantity`. Product ids come from
    `GET /products`.

    <CodeGroup>
      ```bash curl theme={null}
      curl https://vitarelay.com/api/public/v1/orders \
        -H "Authorization: Bearer vr_test_xxxxxxxxxxxxxxxxxxxx" \
        -H "Content-Type: application/json" \
        -d '{
          "external_order_id": "clinic-order-001",
          "external_patient_id": "clinic-patient-001",
          "items": [
            { "product_id": "6f1a2b3c-4d5e-4f60-8a71-9b0c1d2e3f40", "quantity": 1 }
          ]
        }'
      ```

      ```javascript JavaScript theme={null}
      const res = await fetch("https://vitarelay.com/api/public/v1/orders", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.VITARELAY_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          external_order_id: "clinic-order-001",
          external_patient_id: "clinic-patient-001",
          items: [
            { product_id: "6f1a2b3c-4d5e-4f60-8a71-9b0c1d2e3f40", quantity: 1 },
          ],
        }),
      });

      const { data } = await res.json();
      ```
    </CodeGroup>

    Response — `201 Created`:

    ```json theme={null}
    {
      "data": {
        "id": "sandbox_ord_1c8d33f7",
        "external_order_id": "clinic-order-001",
        "patient_id": "sandbox_pat_9f2c41d6",
        "status": "paid",
        "sandbox": true
      }
    }
    ```

    <Note>
      With a live key, order creation charges the clinic's card on file
      synchronously. A successful charge returns `201` with `status: "paid"`; a
      failure returns `402` with `card_required` or `payment_declined`. If
      billing dry-run is enabled for the clinic, the order is created with
      `status: "awaiting_payment"` and `billing_dry_run: true`.
    </Note>
  </Step>

  <Step title="Receive webhooks">
    Once a VitaRelay admin has configured your endpoint and subscribed it to the
    events you care about, VitaRelay signs and POSTs each event to you.

    In the sandbox, the simulated lifecycle fires them for you a few seconds
    apart: `intake.reviewed` for the intake, then `order.paid`,
    `order.shipped`, and `order.delivered` for the order — each carrying
    `sandbox: true`.

    ```text theme={null}
    X-VitaRelay-Event: order.shipped
    X-VitaRelay-Delivery: 3d0c9a15-6f2b-4a71-9d8e-5c4b3a2f1e09
    X-VitaRelay-Timestamp: 1780000000
    X-VitaRelay-Signature: sha256=9c1f…
    ```

    Verify the signature before processing — see
    [Webhook Security](/webhooks/security).
  </Step>
</Steps>

## Replaying a request

All three write endpoints are idempotent on their external id. Sending the same
body again returns the original record with `200` instead of `201`, so retries
after a network failure are safe. Reusing an external id with a different body
returns `409 duplicate_request`.

## Next steps

<CardGroup cols={2}>
  <Card title="REST API" href="/getting-started/rest-api">
    Full endpoint reference, pagination, and response fields.
  </Card>

  <Card title="Webhooks" href="/webhooks/overview">
    Event types, signature verification, and retry behavior.
  </Card>

  <Card title="Sandbox" href="/getting-started/sandbox">
    Everything a `vr_test_` key does differently.
  </Card>

  <Card title="Errors" href="/getting-started/errors">
    Every error code and how to handle it.
  </Card>
</CardGroup>
