Return URL

parseReturnUrl. Frontend-safe parser for the query string Medblocks appends to your return_url.

After a PatientFlow finishes, Medblocks redirects the patient to your return_url with query params describing the outcome. parseReturnUrl reads those params and returns a typed discriminated union.

This helper is frontend-safe. It uses only Web-standard APIs, has no module-level side effects, and never touches the secret key. Import it from @medblocks/connect in a browser bundle.

Signature

import { parseReturnUrl, type ReturnUrlResult } from "@medblocks/connect";

function parseReturnUrl(searchParams?: URLSearchParams): ReturnUrlResult | null;

type ReturnUrlResult =
  | { mode: "picker"; patient_id: string; patient_flow_id: string }
  | {
      mode: "direct";
      success: true;
      patient_id: string;
      patient_flow_id: string;
      connection_id: string;
    }
  | {
      mode: "direct";
      success: false;
      patient_id: string;
      patient_flow_id: string;
      error: string;
      error_description?: string;
    };

Every variant carries both ids. patient_id is your developer-supplied external id — pass it to mb.patients.retrieve(patient_id) for the patient’s cumulative connection state. patient_flow_id is the pf_* id of this browser session — pass it to mb.patientFlow.retrieve(patient_flow_id) for this session’s result.

Calling without an argument reads globalThis.location.search. In a browser this is the current URL. In a non-browser runtime without location, the helper returns null.

Returns null when either id is absent (the page was not opened from a Connect flow), or when the params shape is malformed.

Picker Mode

Picker-mode returns carry the two ids and no success flag. Use patient_id to read the patient’s cumulative state from your backend and inspect connections.

connected-page.tsx
import { parseReturnUrl } from "@medblocks/connect";

export function ConnectedPage() {
  const result = parseReturnUrl();
  if (!result) return <p>Not from a Connect flow.</p>;

  if (result.mode === "picker") {
    return <PickerResult patientId={result.patient_id} />;
  }
  // direct mode...
}

Direct Mode

Direct-mode returns carry success plus connection_id on success or error (and optionally error_description) on failure. Use the params for immediate UI copy, but still hit your backend to verify against the PatientFlow.

connected-page.tsx
import { parseReturnUrl } from "@medblocks/connect";

export function ConnectedPage() {
  const result = parseReturnUrl();
  if (!result || result.mode !== "direct") return null;

  if (result.success) {
    return (
      <SuccessPanel
        patientFlowId={result.patient_flow_id}
        connectionId={result.connection_id}
      />
    );
  }

  return (
    <FailurePanel
      patientFlowId={result.patient_flow_id}
      errorCode={result.error}
      errorMessage={result.error_description ?? "Please try again."}
    />
  );
}

Reading From A Different URL

Pass any URLSearchParams. Useful in server-side rendering, route handlers, or tests.

server/routes/connected.ts
import { parseReturnUrl } from "@medblocks/connect";

export function handleConnected(req: Request): Response {
  const url = new URL(req.url);
  const result = parseReturnUrl(url.searchParams);
  if (!result) return new Response("not a return URL", { status: 400 });

  // ...verify on your server: mb.patients.retrieve(result.patient_id) for
  // cumulative state, or mb.patientFlow.retrieve(result.patient_flow_id) for
  // this session.
}

When null Means

CauseWhat you see
patient_id or patient_flow_id missing from the URL.The page wasn’t opened from a Connect flow. Render your default UI.
success=true without connection_id.Treated as malformed. Log it, then fall back.
success value other than true / false.Treated as malformed.
Running in Node/Bun without an explicit searchParams arg.No location to read. Pass the params explicitly.

Why Verify Server-Side

The return URL is a hint, not a source of truth. Always call mb.patients.retrieve(patient_id) (or mb.patientFlow.retrieve(patient_flow_id) for session-specific state) from the server before marking anything as connected. The URL can be replayed by a user with the link, and only the API has the authoritative status.