Handle the return
Read the return_url params, then show the connected facilities in your app.
After the patient finishes the hosted page or the direct portal flow, their browser lands back on the return_url you set when you started the patient session. That URL is a route in your app, usually something like /connected. This page handles the return for both paths, the Medblocks-hosted page and your own UI.
What comes back
Every return URL carries patient_id and patient_session_id. When your own UI sends the patient straight to one connection, Medblocks also includes success or failure details for that connection.
| Parameter | Meaning |
|---|---|
patient_id | The stable ID you gave the patient. Use it to read the patient’s current connections. |
patient_session_id | The ID of this patient session. Store it if you want to inspect this browser journey later. |
success | Present when your own UI sent the patient straight to one connection. true means the facility connected, false means the portal returned an error. |
connection_id | Present on success when your own UI sent the patient straight to one connection. |
error and error_description | Present when the portal returned the patient without a connected facility. |
parseReturnUrl reads those parameters and returns a typed object. If the current page was not opened from a Medblocks return URL, it returns null.
On your landing page
You can handle the return entirely on the server. Parse the URL, show a retry path when the portal returned an error, and read the patient’s connected facilities when the connection succeeded.
import { parseReturnUrl } from "@medblocks/connect";
import { mb } from "./medblocks";
export async function connected(req: Request): Promise<Response> {
const result = parseReturnUrl(new URL(req.url).searchParams);
if (!result) return new Response("Missing return parameters", { status: 400 });
if ("success" in result && !result.success) {
return Response.json({
status: "retry",
message: result.error_description ?? "Connection failed. Please try again.",
});
}
const connections = await mb.patients.getConnections(result.patient_id, {
hydrate: true,
});
return Response.json({
status: "connected",
patientId: result.patient_id,
sessionId: result.patient_session_id,
connections: connections.map((facility) => ({
id: facility.id,
name: facility.name,
logo_url: facility.logo_url,
})),
});
}import { parseReturnUrl } from "@medblocks/connect";
export function ConnectedPage() {
const result = parseReturnUrl();
if (!result) return <Dashboard />;
if ("success" in result && !result.success) {
return <RetryPanel message={result.error_description ?? "Please try again."} />;
}
return <ConnectedFacilities patientId={result.patient_id} />;
}Show connected facilities
The server example uses mb.patients.getConnections(result.patient_id, { hydrate: true }). That reads the patient, filters to connected facilities, and hydrates their names, logos, and portal URLs so your UI can display them immediately.
import { mb } from "./medblocks";
const facilities = await mb.patients.getConnections("user_42", { hydrate: true });
for (const facility of facilities) {
console.log(facility.name, facility.logo_url);
}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.
Common errors
| Code | Meaning |
|---|---|
not_found | No patient matches the patient_id in the return URL. |
missing_api_key | The Authorization header is missing from your server’s request. |
invalid_api_key | The key is invalid or does not belong to your organization. |
Read the full envelope and code list in Errors.
