Advanced
Client options, retries, timeouts, AbortSignal, custom fetch, and runtime notes.
new Medblocks(apiKey, options?) takes a second argument with knobs you can tune per process. Defaults are sensible for most apps. Only override when you have a reason.
Client Options
import { Medblocks } from "@medblocks/connect";
const mb = new Medblocks(process.env.MEDBLOCKS_API_KEY!, {
baseUrl: "https://app.medblocks.com",
apiVersion: "2026-04-25",
timeout: 30_000,
maxNetworkRetries: 3,
fetch: globalThis.fetch,
});| Option | Type | Default | Purpose |
|---|---|---|---|
baseUrl | string | https://app.medblocks.com | Override only for staging / a local mock. |
apiVersion | string | 2026-04-25 | Sent as the Version header on every request. Pinned per SDK release. |
timeout | number (ms) | 30_000 | Per-request timeout. Composes with caller-supplied AbortSignal. |
maxNetworkRetries | number | 3 | Transient-failure retries. 0 disables retries. |
fetch | typeof globalThis.fetch | globalThis.fetch.bind(globalThis) | Injectable fetch. Useful for tests, mocking, or runtimes with a non-global fetch. |
The defaults are exported as constants for tests and assertions:
import {
DEFAULT_BASE_URL,
DEFAULT_MAX_RETRIES,
DEFAULT_TIMEOUT_MS,
LATEST_API_VERSION,
} from "@medblocks/connect";Retries
The SDK retries on:
- Network errors (
fetchrejected, abort caused by timeout). - HTTP
429. Honors the server’sRetry-Afterheader. - HTTP
502,503,504.
It does not retry on 4xx other than 429, or on 500. Those surface as the appropriate MedblocksError subclass.
Backoff is exponential with jitter:
| Attempt | Backoff (ms) |
|---|---|
| 0 | 250 – 500 |
| 1 | 500 – 750 |
| 2 | 1 000 – 1 250 |
| 3 | 2 000 – 2 250 |
Set maxNetworkRetries: 0 to disable retries entirely. Useful in integration tests against a mock server so failures surface immediately.
const mb = new Medblocks("mb_sk_live_test", {
baseUrl: fixtureUrl,
maxNetworkRetries: 0,
});AbortSignal
Every resource method takes an optional { signal } as its last argument. Pass an AbortSignal to cancel the request. Useful inside a route handler that’s already wired to the request’s abort signal.
export async function startConnect(req: Request): Promise<Response> {
const body = await req.json();
const flow = await mb.patientFlow.init(
{
patient_id: body.patientId,
return_url: body.returnUrl,
},
{ signal: req.signal },
);
return Response.json({ url: flow.url });
}The SDK composes your signal with its internal timeout signal. Whichever aborts first wins. A timeout abort surfaces as MedblocksApiError with code: "invalid_response" or as the thrown AbortError from fetch, depending on the runtime.
Custom Fetch
Override fetch to inject logging, tracing, or a per-request header.
import { Medblocks } from "@medblocks/connect";
import { trace } from "./tracing";
export const mb = new Medblocks(process.env.MEDBLOCKS_API_KEY!, {
fetch: async (input, init) => {
const span = trace.start("medblocks.fetch");
try {
return await globalThis.fetch(input, init);
} finally {
span.end();
}
},
});The custom fetch is called for every request the SDK makes, including retry attempts. Do not throw from inside it; let fetch errors propagate.
Bundle Size
The browser-safe entry (just parseReturnUrl and the discriminated ReturnUrlResult type) is intentionally small. Importing only the helper, modern bundlers tree-shake out everything else:
import { parseReturnUrl } from "@medblocks/connect"; // tinyImporting Medblocks in browser code pulls the full HTTP client and error hierarchy. Don’t. It exposes your secret key to end users.
Runtime Notes
| Runtime | Required version | Notes |
|---|---|---|
| Node.js | ≥ 20 | Global fetch is required. |
| Bun | ≥ 1.0 | Native. |
