Create patients
Give each person a stable patient_id, or let the session create one for you.
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.
