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

# Get the intake form for products

> **Vita Clinic only.** Requires the `intakes:read` scope. Returns the intake form a patient fills in for the
products you name, so your site can show the same questions our own link does. Nothing about a patient is read
or stored.

Every product has its own form. Products that use **different** forms get **one combined form**: its sections
run form by form, and a question two forms ask in the same way (name, email, date of birth, consents) appears
once, so the patient never answers it twice. The same set of products always gives the same `form_key`. The
form is the same for a test key and a live key.

Use `stage=followup` for the follow-up form a patient answers before a refill. Products that do not need an
intake are listed with `needs_intake: false`. When no product form applies (the standard intake is used, a
product has no confirmed form yet, or forms are not switched on for your account) `form` is `null`, `reason`
says why, and `note` points to the standard intake (`POST /intakes`).

Every question lists its attributes (`kind`, `options`, `required`, `answer_format`, `conditional`, `pii`). The
full list for every form, including when each question is asked, is in the
[Intake forms reference](/getting-started/intake-forms-reference).

Draw the questions from `sections`, then send the answers to
[Evaluate an intake form](/api-reference/intakes/evaluate-an-intake-form) after each step to learn which
questions show next and what is still missing.




## OpenAPI

````yaml /openapi.yaml get /intake-forms
openapi: 3.1.0
info:
  title: VitaRelay API
  version: 2.0.0
  description: |
    The VitaRelay REST API.

    **Base URL:** `https://vitarelay.com/api/public/v1`

    ## Authentication
    All requests require a Bearer API key:

    ```text
    Authorization: Bearer vr_live_xxxxxxxxxxxxxxxx
    ```

    Keys are issued per organization. `vr_live_` keys act on production data.
    `vr_test_` keys operate a fully-isolated **sandbox** (see below).

    ## Pagination
    List endpoints are cursor-based. Pass `limit` (default 50, max 100) and
    `cursor` (the `next_cursor` from the previous page). When `next_cursor`
    is `null` there are no further pages. All resource ids are UUIDs.

    ## Idempotency
    Write endpoints accept your own external identifiers —
    `external_patient_id`, `external_intake_id`, `external_order_id`. These act
    as idempotency keys: replaying a request with the same external id returns
    the original resource (HTTP `200` instead of `201`) rather than creating a
    duplicate.

    ## Rate limiting
    Write endpoints are rate limited per API key — default **60 requests per
    minute** (fixed window). Exceeding the limit returns `429 rate_limited`
    with `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and
    `X-RateLimit-Reset` headers. Read endpoints are not rate limited in v1.

    ## Sandbox
    With a `vr_test_` key, writes never create real patients, intakes or orders
    and never charge a card. They return synthetic ids (`sandbox_pat_…`,
    `sandbox_int_…`, `sandbox_ord_…`) and include `"sandbox": true` in the
    response. Sandbox objects advance through a simulated lifecycle that fires
    real webhook deliveries to your endpoint (`intake.reviewed`, `order.paid` →
    `order.shipped` → `order.delivered`) with `"sandbox": true` in the payload.
    In sandbox, reference a patient by `external_patient_id` or by the returned
    `sandbox_pat_…` id.

    ## Webhooks
    Outbound webhooks are configured in the VitaRelay admin UI (there is no
    webhook management API). Events: `order.paid`, `order.shipped`,
    `order.delivered`, `order.exception`, `intake.reviewed`. Each delivery is
    signed with HMAC-SHA256 over the raw body and carries the headers
    `X-VitaRelay-Signature: sha256=<hex>`, `X-VitaRelay-Event`,
    `X-VitaRelay-Delivery` (event id) and `X-VitaRelay-Timestamp`. Failed
    deliveries are retried with exponential backoff and dead-lettered after the
    maximum attempts.
  contact:
    name: VitaRelay Support
    email: info@vitarelay.com
servers:
  - url: https://vitarelay.com/api/public/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Patients
    description: Patient records scoped to your organization.
  - name: Intakes
    description: >-
      The health questionnaire a prescriber reviews. There are two ways to
      complete one, and each has a Vita Clinic endpoint and a referral (Rx)
      endpoint. **Patient fills it in on our page:** `POST
      /patients/{patientId}/intake/send-link` (Vita Clinic) or `POST
      /rx/patients/{patientId}/intake` (referral). **You collect the answers and
      send them to us:** `POST /intakes` (Vita Clinic) or `POST
      /rx/patients/{patientId}/intake/submit` (referral). Check progress with
      `GET /patients/{patientId}/intake/status` and the `intake.submitted` /
      `intake.reviewed` webhooks. See [Intakes and prescriber
      review](/getting-started/intakes-and-prescriptions) and the [Intake
      answers reference](/getting-started/intake-responses).
  - name: Orders
    description: >-
      Orders and fulfillment status. Two billing modes: `card_on_file` (default)
      charges the clinic's stored card synchronously, and `patient_checkout`
      creates the order unpaid and returns a checkout block so the patient can
      pay on your own page via Authorize.Net Accept.js (see POST
      /orders/{id}/pay).
  - name: Products
    description: Catalog products available to your organization.
  - name: Prescriptions
    description: >-
      Prescriptions written by your organization (read only). Refer patients
      into the Internal Doctor Network (IDN). You refer; an IDN doctor evaluates
      and prescribes. Requires IDN activation and rx scopes.
  - name: Storefront
    description: >-
      Build and manage your clinic's patient storefront — settings, curated
      product listings and bundles. Requires the `shop:read` / `shop:write`
      scopes.
  - name: Subscriptions
    description: >-
      Patient-shop subscription lifecycle. Requires `subscriptions:read` or
      `subscriptions:write`.
paths:
  /intake-forms:
    get:
      tags:
        - Intakes
      summary: Get the intake form for products
      description: >
        **Vita Clinic only.** Requires the `intakes:read` scope. Returns the
        intake form a patient fills in for the

        products you name, so your site can show the same questions our own link
        does. Nothing about a patient is read

        or stored.


        Every product has its own form. Products that use **different** forms
        get **one combined form**: its sections

        run form by form, and a question two forms ask in the same way (name,
        email, date of birth, consents) appears

        once, so the patient never answers it twice. The same set of products
        always gives the same `form_key`. The

        form is the same for a test key and a live key.


        Use `stage=followup` for the follow-up form a patient answers before a
        refill. Products that do not need an

        intake are listed with `needs_intake: false`. When no product form
        applies (the standard intake is used, a

        product has no confirmed form yet, or forms are not switched on for your
        account) `form` is `null`, `reason`

        says why, and `note` points to the standard intake (`POST /intakes`).


        Every question lists its attributes (`kind`, `options`, `required`,
        `answer_format`, `conditional`, `pii`). The

        full list for every form, including when each question is asked, is in
        the

        [Intake forms reference](/getting-started/intake-forms-reference).


        Draw the questions from `sections`, then send the answers to

        [Evaluate an intake
        form](/api-reference/intakes/evaluate-an-intake-form) after each step to
        learn which

        questions show next and what is still missing.
      operationId: getIntakeForms
      parameters:
        - name: product_ids
          in: query
          required: true
          description: Catalog product ids, comma separated (at most 25).
          schema:
            type: string
        - name: stage
          in: query
          required: false
          schema:
            type: string
            enum:
              - initial
              - followup
            default: initial
      responses:
        '200':
          description: The form for these products, or null with the reason.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      stage:
                        type: string
                        enum:
                          - initial
                          - followup
                      reason:
                        type: string
                        enum:
                          - single_form
                          - combined
                          - no_products
                          - unconfirmed
                          - standard
                          - mixed
                          - not_enabled
                      note:
                        type:
                          - string
                          - 'null'
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: string
                              format: uuid
                            needs_intake:
                              type: boolean
                            form_key:
                              type:
                                - string
                                - 'null'
                            schedule:
                              type:
                                - object
                                - 'null'
                              description: >-
                                How to time this product's intakes and refills,
                                from the fulfillment matrix. `null` when the
                                product needs no intake or has no mapping yet.
                              properties:
                                intake_valid_days:
                                  type: integer
                                  description: >-
                                    Days an initial intake keeps counting for
                                    new orders of this product.
                                followup:
                                  type: object
                                  properties:
                                    form_key:
                                      type:
                                        - string
                                        - 'null'
                                    ask_days_before_ship:
                                      type: integer
                                      description: >-
                                        The follow-up is asked this many days
                                        before the next fill can ship.
                                    needed_only_when_refills_used_up:
                                      type: boolean
                                      description: >-
                                        No follow-up is asked while the
                                        prescription still has refills.
                                cadences:
                                  type: object
                                  description: >-
                                    One entry per refill cadence (`monthly`,
                                    `quarterly`, `semi_annual`, `annual`):
                                    whether the product supports it and the
                                    first day, counted from the last shipment,
                                    the next fill can ship.
                                  additionalProperties:
                                    type: object
                                    properties:
                                      supported:
                                        type: boolean
                                      ship_available_day:
                                        type:
                                          - integer
                                          - 'null'
                      form:
                        type:
                          - object
                          - 'null'
                        description: >-
                          The form to show. Send its `form_key` to the evaluate
                          call.
                        properties:
                          form_key:
                            type: string
                            example: combined:wizlo.glp.initial+wizlo.hair.initial
                          version:
                            type: integer
                          title:
                            type: string
                          stage:
                            type: string
                          combined_from:
                            type:
                              - array
                              - 'null'
                            items:
                              type: string
                          sections:
                            type: array
                            items:
                              type: object
                              properties:
                                title:
                                  type: string
                                description:
                                  type: string
                                questions:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      id:
                                        type: string
                                        description: The key to answer under.
                                      question:
                                        type: string
                                      subquestion:
                                        type:
                                          - string
                                          - 'null'
                                      kind:
                                        type: string
                                        description: >-
                                          The answer type (text, radio,
                                          checkbox_multi, date, height_weight,
                                          file, consent and so on).
                                      options:
                                        type: array
                                        items:
                                          type: string
                                      placeholder:
                                        type:
                                          - string
                                          - 'null'
                                      required:
                                        type: boolean
                                        description: Required when the question is shown.
                                      answer_format:
                                        type: string
                                        description: >-
                                          The JSON to send as the answer (a
                                          string, an array of strings, or an
                                          object for height and weight).
                                        example: array of strings (the chosen options)
                                      conditional:
                                        type: boolean
                                        description: >-
                                          Shown only for some answers. Use the
                                          evaluate call to learn which.
                                      pii:
                                        type: boolean
                                        description: >-
                                          The answer may carry personal
                                          information.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: A product id does not exist (`not_found`).
        '422':
          description: >-
            product_ids missing, not UUIDs, over 25, or an unknown stage
            (`validation_failed`).
components:
  responses:
    Unauthorized:
      description: Missing, invalid or revoked API key (`unauthorized`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: |
                One of `invalid_body`, `validation_failed`, `unauthorized`,
                `insufficient_scope`, `not_vita_clinic`, `patient_not_found`,
                `product_not_found`, `product_not_allowed`, `duplicate_request`,
                `rate_limited`, `card_required`, `payment_declined`,
                `internal_error`, `not_found`.
            message:
              type: string
      example:
        error:
          code: validation_failed
          message: One or more fields are invalid
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        API key issued by VitaRelay. Send as `Authorization: Bearer vr_live_…`
        (production) or `Authorization: Bearer vr_test_…` (sandbox).

````

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