Skip to main content
IntakeForm is a dynamic questionnaire widget that renders intake questions from a questionnaire definition and collects patient responses. It handles multiple answer types, supports nested question groups, and auto-saves in-progress responses so patients can complete the intake across multiple sessions. Completed submissions are stored as FHIR QuestionnaireResponse resources through a backend proxy you control.
Your ClinikAPI secret key must stay on the server. The IntakeForm widget posts all responses to your proxyUrl. Your backend proxy is responsible for validating the submission and calling ClinikAPI with your key.

Props

props.proxyUrl
string
required
URL of your backend proxy endpoint. The widget sends GET requests to load the questionnaire definition and any in-progress response, and POST requests to submit completed responses.
props.className
string
CSS class name applied to the widget’s root element for layout and theming control.
props.onError
(error: Error) => void
Callback invoked when a load or submission request to your proxy fails. Use this to notify the patient and offer retry options.

Proxy setup

Your proxy needs to return the questionnaire definition on GET and accept responses on POST. The example below shows a Next.js App Router implementation:
// app/api/clinik/intakes/route.ts
import { Clinik } from '@clinikapi/sdk';

const clinik = new Clinik(process.env.CLINIKAPI_SECRET_KEY!);

// GET: load the questionnaire definition and any saved in-progress response
export async function GET(req: Request) {
  const url = new URL(req.url);
  const questionnaireId = url.searchParams.get('questionnaireId');

  const { data } = await clinik.questionnaires.read(questionnaireId!);
  return Response.json(data);
}

// POST: submit a completed or in-progress intake response
export async function POST(req: Request) {
  const body = await req.json();
  const { data } = await clinik.questionnaireResponses.create(body);

  return Response.json(data);
}
Use the status field in the POST body to distinguish auto-saves (in-progress) from final submissions (completed). Your proxy can apply different validation rules for each status — for example, requiring all required questions to be answered before accepting a completed submission.

Usage

import { IntakeForm } from '@clinikapi/react';

export default function IntakePage() {
  return (
    <IntakeForm
      proxyUrl="/api/clinik/intakes"
      onError={(err) => console.error('Intake form error:', err)}
    />
  );
}

Features

  • Dynamic question rendering based on the questionnaire definition returned by your proxy — no hardcoded form fields
  • Multiple answer types: text, boolean, integer, date, and coded (choice) responses
  • Nested question groups: hierarchical sections render with proper indentation and grouping
  • Auto-save as in-progress: the widget periodically saves partial responses so patients can return later
  • Final submission as completed: submitting the form updates the status to completed in a single request
Responses are stored as FHIR QuestionnaireResponse resources. This means intake data is structured, queryable, and can be linked to the patient’s broader clinical record in ClinikAPI.