Passer au contenu

SDKs and snippets

Code snippets in cURL, TypeScript and Python for every EDFlow API operation, signing helpers for the signed ingest profile with the conformance test vector, the OpenAPI document, Postman collection and typed clients.

Cette page n'est pas encore offerte en français; elle est affichée en anglais.

Snippets on every operation

Every page of the API reference shows cURL, TypeScript (fetch) and Python (httpx) for that operation, generated from the same OpenAPI document the API validates requests against. The quickstart and the developer portal use the same generators, and CI runs them against the sandbox.

curl -sS -X POST 'https://api.sandbox.edflow.space/v1/events/validate' \  -H "Authorization: Bearer $EDFLOW_ACCESS_TOKEN"

Downloads

FileWhere
OpenAPI 3.1 document/openapi/edflow-v1.json, or GET /v1/openapi.json on the API
Postman collection with a token pre-request script/openapi/edflow-v1.postman.json
JSON Schemas for every event typeEvent reference
Mirth Connect and OIE channel templatesEngine configuration

Typed clients

Generate a client from the OpenAPI document with your usual tools (for example @hey-api/openapi-ts for TypeScript, openapi-python-client for Python, or Kiota for C# and Java). A published TypeScript SDK follows the document's version; Python, C# and Java SDKs are planned.

Webhook verification

Use a Standard Webhooks library (TypeScript, Python, C#, Java, Go, PHP, Ruby, Rust, Elixir). No EDFlow SDK is needed. See Webhooks.

Signing helper for the signed ingest profile

TypeScript (WebCrypto, runs in Node 20+, Deno, Bun and browsers):

const enc = new TextEncoder();
const hex = (b: ArrayBuffer) =>
  [...new Uint8Array(b)].map((x) => x.toString(16).padStart(2, "0")).join("");

export async function signRequest(
  keyHex: string,
  req: { timestamp: number; deliveryId: string; method: string; path: string;
         siteCode?: string; input?: string; body: Uint8Array }
): Promise<string> {
  const keyBytes = new Uint8Array(keyHex.match(/../g)?.map((h) => Number.parseInt(h, 16)) ?? []);
  const key = await crypto.subtle.importKey("raw", keyBytes, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
  const bodyHash = hex(await crypto.subtle.digest("SHA-256", req.body));
  const payload = `v2.${req.timestamp}.${req.deliveryId}.${req.method} ${req.path}.${req.siteCode ?? "-"}.${req.input ?? "-"}.${bodyHash}`;
  return `v2=${hex(await crypto.subtle.sign("HMAC", key, enc.encode(payload)))}`;
}

Python (standard library):

import hashlib, hmac

def sign_request(key_hex: str, timestamp: int, delivery_id: str, method: str, path: str,
                 body: bytes, site_code: str | None = None, input_kind: str | None = None) -> str:
    body_hash = hashlib.sha256(body).hexdigest()
    payload = f"v2.{timestamp}.{delivery_id}.{method} {path}.{site_code or '-'}.{input_kind or '-'}.{body_hash}"
    return "v2=" + hmac.new(bytes.fromhex(key_hex), payload.encode(), hashlib.sha256).hexdigest()

cURL with OpenSSL:

BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -r | cut -d' ' -f1)
PAYLOAD="v2.$TS.$DELIVERY_ID.POST /ehr/v1/events.-.-.$BODY_HASH"
SIG=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -mac HMAC -macopt hexkey:"$SOURCE_KEY_HEX" -r | cut -d' ' -f1)
curl -sS "$INGEST_URL/ehr/v1/events" -H "Content-Type: application/json" \
  -H "EDFlow-Source: $SOURCE_ID" -H "EDFlow-Delivery-Id: $DELIVERY_ID" \
  -H "EDFlow-Timestamp: $TS" -H "EDFlow-Signature: v2=$SIG" --data-binary "$BODY"

Test vector

These values are for conformance testing only. Never use this secret anywhere. Your helper must reproduce the expected signature exactly.

InputValue
Deployment secret (test only)test-only-ehr-webhook-secret-0123456789abcdef
Source id, key versiondemo-epic-bridges, 1
Source salt5f0c2a9e7b3d41c8a6e2f19d04b7c3aa
Derived source key (hex)c60acc8548b1d9ac8ba57abf6fb1fa513703e2787cbc942a3ff15618720fbfdc
EDFlow-Timestamp1789398000
EDFlow-Delivery-Id0b9f5c1e-8d0a-4f64-9a51-2d8c9f3e7a10
Body (217 bytes){"events":[{"specVersion":"1.0","id":"demo-epic-bridges:hb:1789398000","type":"system.heartbeat","occurredAt":"2026-09-14T11:00:00-04:00","source":{"kind":"ehr","system":"epic","feed":"adt"},"data":{"queueDepth":0}}]}
SHA-256 of the body76d9b18a75579fe36228573f389d77904b49520b84a68914a22b3dbf5a2638af
Expected for POST /ehr/v1/eventsv2=e5eaca410459497d88e031d034aef07ad4e9e2e323631500349660c007573eb4
Expected for POST /ehr/v1/validate with input eventsv2=b44ef01ad218c1df9dc97c30cfaeef977d58b8bb1c82700693c3bff6573c6356
Expected for /ehr/v1/events with site code demo-edv2=9ef2923903e4751138ab685b1ef6c4ca7f12962d97da1d9d94e6208c0d995346

The last row must not verify against the first signature: v2 binds the site code and input kind.

Dernière mise à jour le

Cette page vous a-t-elle été utile?

Sur cette page