Create patients
Give each person a stable patient_id, or let the session create one for you.
Open in
Show prompt text
You are an AI coding agent helping integrate Medblocks Patient Access into the codebase that is currently open. Treat the live Medblocks docs and generated API reference as the source of truth. If you are running inside a local repo that contains openapi/medblocks.json, read it too. Do not rely on endpoint names, SDK calls, response fields, or code snippets from memory. Before changing code, read the current docs directly. - Patient Access overview https://medblocks.com/docs/patient-access/overview - Find connections https://medblocks.com/docs/patient-access/find-connections - Create patients https://medblocks.com/docs/patient-access/create-patients - Create a patient session https://medblocks.com/docs/patient-access/create-patient-session - Medblocks-hosted page https://medblocks.com/docs/patient-access/create-patient-session/medblocks-hosted-page - Your own UI https://medblocks.com/docs/patient-access/create-patient-session/your-own-ui - Handle the return https://medblocks.com/docs/patient-access/handle-the-return - After connection https://medblocks.com/docs/patient-access/after-connection - Get the data https://medblocks.com/docs/patient-access/get-the-data - API conventions https://medblocks.com/docs/reference/conventions - API reference https://medblocks.com/docs/reference/api Use the page I copied this from as the immediate task context, then use the rest of the Build pages to understand the full flow. Work in this order. 1. Inspect this codebase first. Identify the app framework, server boundary, environment variable pattern, existing API client pattern, current patient or user identity model, logging style, and test runner. 2. Read the generated API reference before naming any route, field, enum, header, error code, or SDK method. If your tool has local filesystem access and this repo has openapi/medblocks.json, read that too. If the docs and reference disagree, stop and ask the user which source to follow. 3. Decide whether this app should use the Medblocks-hosted page, your own UI, or both. Ask the user if the answer is not obvious from the product. 4. Keep the Medblocks API key server-side. Never expose it through public environment variable prefixes, frontend bundles, browser logs, or client-side fetches. 5. Implement the smallest complete path for the selected page. Follow existing project conventions for file locations, naming, validation, errors, loading states, and tests. 6. After a patient returns from authorization, verify the result from the server using the latest documented Patient Access status flow. Do not trust query string values as the final source of truth. 7. Preserve Medblocks request IDs and documented error details in logs and server responses where safe. Avoid logging PHI unless this codebase already has an approved pattern. 8. Run the relevant type checks and tests before reporting done. If a live smoke test needs credentials the repo does not have, explain the exact manual smoke test steps. If any required detail is missing, ask concise questions before writing code. In a healthcare integration, a correct pause is better than an incorrect assumption.
After you know which connections a patient can choose from, give that person a stable identity in Medblocks. A patient is one person in your app whose health records you want to pull. You provide the patient_id, and Medblocks uses that ID everywhere, for starting a patient session, reading session history, checking connection status, and reading records later.
Use a stable ID from your system. Good choices are an internal user ID, member ID, or chart ID. Avoid IDs that can change, like email addresses.
Option 1: Create the patient first
Create the patient up front when your app has an intake step before the person connects any records. Your API key is a secret, so the call runs on your server. The client just asks your server to do it.
import { mb } from "./medblocks";
export async function createPatient(input: { patientId: string; email?: string; name?: string }) {
return mb.patients.create({
patient_id: input.patientId,
email: input.email,
name: input.name,
metadata: { signup_source: "intake" },
});
}patient_idstringrequiredYour stable identifier for this patient. Unique within your organization.
emailstringPatient email for display and matching in your app.
namestringPatient display name.
metadataobjectAdditional metadata returned with the Patient.
AuthorizationBearer <token>requiredMedblocks API key for server-side requests.
VersionstringDate-pinned API version. If omitted, Medblocks uses the version pinned on your API key.
async function createPatient(values: { patientId: string; email?: string; name?: string }) {
const response = await fetch("/api/patients", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(values),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(error?.message ?? "Could not create patient");
}
return response.json() as Promise<{ id: string; email: string | null; name: string | null }>;
}patient_idstringrequiredYour stable identifier for this patient. Unique within your organization.
emailstringPatient email for display and matching in your app.
namestringPatient display name.
metadataobjectAdditional metadata returned with the Patient.
Only patient_id is required. email and name are optional, and metadata is a free-form object you can use to stash your own fields.
Option 2: Upsert when you start a patient session
You can skip creating the patient and start a patient session directly. If the patient does not exist, Medblocks creates it. If the patient already exists, Medblocks reuses it and updates the patient_email or patient_name you pass when they differ.
const session = await mb.patientSession.init({
patient_id: "user_42",
return_url: "https://your-app.example.com/connected",
});patient_idstringrequiredYour stable identifier for this patient.
return_urlstringrequiredURL to redirect after the patient session.
patient_emailstringPatient email to store or update.
patient_namestringPatient display name to store or update.
metadataobjectAdditional metadata returned with the patient session.
AuthorizationBearer <token>requiredMedblocks API key for server-side requests.
VersionstringDate-pinned API version. If omitted, Medblocks uses the version pinned on your API key.
For most apps, letting the session create the patient is the shortest path. Create a patient session covers it in full.
Read a patient
Read a patient when you need to show which facilities they have connected, or when you need to inspect a recent failed attempt. The response includes a connections array, which lists failed attempts too.
import { mb } from "./medblocks";
export async function getPatient(patientId: string) {
return mb.patients.retrieve(patientId);
}idstringrequiredYour patient_id from Patient creation or Session upsert.
AuthorizationBearer <token>requiredMedblocks API key for server-side requests.
VersionstringDate-pinned API version. If omitted, Medblocks uses the version pinned on your API key.
async function getPatient(patientId: string) {
const response = await fetch(`/api/patients/${encodeURIComponent(patientId)}`);
const body = await response.json();
if (!response.ok) throw new Error(body.error?.message ?? "Could not read patient");
return body as { id: string; connections?: Array<{ connection_id: string; status: string }> };
}idstringrequiredYour patient_id from Patient creation or Session upsert.
A connection carries the facility ID but not its name, logo, or portal link. When you want to render the patient’s connected facilities, use the getConnections helper with hydrate: true. It does that lookup for you and hands back facilities you can show directly. It skips connections whose authorization failed, since those carry no data.
const facilities = await mb.patients.getConnections("user_42", { hydrate: true });
for (const facility of facilities) {
console.log(facility.name, facility.logo_url, facility.fhir_base_url);
}Common errors
| Code | Meaning |
|---|---|
invalid_request | A reserved-prefix patient_id, an ID over 200 characters, or a malformed email. |
external_id_already_exists | The patient_id is already taken by another patient. |
not_found | The patient does not exist. |
missing_api_key | The Authorization header is missing. |
invalid_api_key | The key is invalid or does not belong to your workspace. |
The full list, and how to read the error envelope, lives in Errors.
