### Install PyMedplum Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Install the base package or with optional MCP server support using pip or uv. ```bash pip install pymedplum # With MCP server support pip install "pymedplum[mcp]" # With uv uv add pymedplum uv add "pymedplum[mcp]" ``` -------------------------------- ### Install and Launch MCP Server Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Install the PyMedplum MCP server and set environment variables for authentication and configuration. Enable writes explicitly if needed and scope to a specific project membership. ```bash pip install "pymedplum[mcp]" export MEDPLUM_CLIENT_ID="your-client-id" export MEDPLUM_CLIENT_SECRET="your-client-secret" export MEDPLUM_BASE_URL="https://api.medplum.com/" # Read-only by default — enable writes explicitly export MEDPLUM_ENABLE_WRITES="true" # Scoped to a specific project membership export MEDPLUM_ON_BEHALF_OF="ProjectMembership/00000000-0000-0000-0000-000000000000" uvx --from "pymedplum[mcp]" pymedplum-mcp ``` -------------------------------- ### Complete Bot Workflow Example Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Demonstrates the full cycle of creating, deploying, and executing a bot using MedplumClient. ```python from pymedplum import MedplumClient # Initialize — auth happens on the first request client = MedplumClient(base_url="https://api.medplum.com") # Create a new Bot resource bot = client.create_bot( name="My Custom Bot", description="A bot that processes patient data", runtime_version="awslambda" ) bot_id = bot["id"] ``` -------------------------------- ### Invite User Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/admin.md This example demonstrates how to invite a new user to the project using the `invite_user` method. ```APIDOC ## Example: invite a new user ### Description Invite a new user to the project with specified details. ### Method invite_user ### Parameters - **project_id** (string) - Required - The ID of the project. - **resource_type** (string) - Required - The type of resource for the user (e.g., Practitioner). - **first_name** (string) - Required - The first name of the user. - **last_name** (string) - Required - The last name of the user. - **email** (string) - Required - The email address of the user. - **send_email** (boolean) - Required - Whether to send an invitation email. ### Request Example ```python membership = client.invite_user( project_id="YOUR_PROJECT_ID", resource_type="Practitioner", first_name="Alice", last_name="Smith", email="alice.smith@example.com", send_email=True, ) print(membership["id"]) ``` ``` -------------------------------- ### Install PyMedplum Source: https://github.com/kinsteadhealth/pymedplum/blob/main/README.md Install the PyMedplum package using pip. For MCP support, use the extended package. ```bash pip install pymedplum ``` ```bash pip install "pymedplum[mcp]" ``` ```bash uv add pymedplum ``` ```bash uv add "pymedplum[mcp]" ``` -------------------------------- ### Install pymedplum Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/faq.md Install the pymedplum package using pip. For development, install with the 'dev' extra. ```bash pip install pymedplum ``` ```bash pip install -e ".[dev]" ``` -------------------------------- ### Basic Synchronous PHI Audit Logger Setup Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/audit_logging.md Configure a Pymedplum client with a synchronous `on_request_complete` callback to log PHI access events. This example uses Python's built-in `logging` module. ```python import logging from pymedplum import MedplumClient from pymedplum.hooks import RequestEvent audit_log = logging.getLogger("kinstead.phi_access") def record_phi_access(event: RequestEvent) -> None: audit_log.info( "phi_access", extra={ "audit": event.to_phi_audit_dict(), "actor": current_user_id(), }, ) client = MedplumClient( base_url="https://api.medplum.com/", client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", on_request_complete=record_phi_access, ) ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/kinsteadhealth/pymedplum/blob/main/README.md Use make commands to install development dependencies for PyMedplum. This is typically the first step before running quality checks or tests. ```bash # Install development dependencies make install-dev ``` -------------------------------- ### Install Core pymedplum Package Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/installation.md Installs the main pymedplum package and its essential dependencies like pydantic and httpx. ```bash pip install pymedplum ``` -------------------------------- ### Create and Execute Batch Bundle (Python) Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/bundles.md Use batch bundles for independent operations where each entry can succeed or fail on its own. This example shows creating a bundle with PUT and DELETE operations and executing it. ```python bundle = { "resourceType": "Bundle", "type": "batch", "entry": [ { "request": {"method": "PUT", "url": "Patient/123"}, "resource": {"resourceType": "Patient", "id": "123", "active": True}, }, { "request": {"method": "PUT", "url": "Patient/456"}, "resource": {"resourceType": "Patient", "id": "456", "active": False}, }, {"request": {"method": "DELETE", "url": "Observation/789"}}, ], } result = client.execute_batch(bundle) ``` -------------------------------- ### Install pymedplum with MCP Support Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/installation.md Installs pymedplum with the optional MCP extra dependencies. This is useful if you need to manage MCP support within your environment. ```bash pip install "pymedplum[mcp]" ``` -------------------------------- ### Standard MCP JSON Configuration Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/mcp.md Example of a standard MCP JSON configuration for the pymedplum server, including direct environment variable assignments. ```json { "mcpServers": { "pymedplum": { "command": "uvx", "args": ["--from", "pymedplum[mcp]", "pymedplum-mcp"], "env": { "MEDPLUM_CLIENT_ID": "your-client-id", "MEDPLUM_CLIENT_SECRET": "your-client-secret", "MEDPLUM_BASE_URL": "https://api.medplum.com/" } } } } ``` -------------------------------- ### Codex CLI MCP Server Setup Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/mcp.md Add a pymedplum MCP server configuration using the Codex CLI, specifying environment variables and the command to run. ```bash codex mcp add \ pymedplum \ -e MEDPLUM_CLIENT_ID=your-client-id \ -e MEDPLUM_CLIENT_SECRET=your-client-secret \ -e MEDPLUM_BASE_URL=https://api.medplum.com/ \ -- \ uvx --from "pymedplum[mcp]" pymedplum-mcp ``` -------------------------------- ### General Error Handling Example Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/api_reference.md This example demonstrates catching common pymedplum exceptions like `NotFoundError`, `AuthorizationError`, `ValidationError`, and `RateLimitError`. ```python from pymedplum import ( AuthorizationError, NotFoundError, RateLimitError, ValidationError, ) try: patient = client.read_resource("Patient", "nonexistent-id") except NotFoundError: ... except AuthorizationError: ... except ValidationError: ... except RateLimitError: ... ``` -------------------------------- ### Codex Config (config.toml) Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/mcp.md Example configuration for the pymedplum MCP server in Codex's config.toml file, using environment variable forwarding. ```toml [mcp_servers.pymedplum] command = "uvx" args = ["--from", "pymedplum[mcp]", "pymedplum-mcp"] env_vars = ["MEDPLUM_CLIENT_ID", "MEDPLUM_CLIENT_SECRET", "MEDPLUM_BASE_URL"] ``` -------------------------------- ### Create and Execute Transaction Bundle (Python) Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/bundles.md Use transaction bundles for atomic operations where all entries must succeed or fail as a single unit. This example demonstrates creating a bundle with patient and observation resources and executing it. ```python bundle = { "resourceType": "Bundle", "type": "transaction", "entry": [ { "request": {"method": "POST", "url": "Patient"}, "resource": { "resourceType": "Patient", "name": [{"family": "Smith", "given": ["John"]}], }, "fullUrl": "urn:uuid:patient-temp-id", }, { "request": {"method": "POST", "url": "Observation"}, "resource": { "resourceType": "Observation", "status": "final", "code": {"text": "Blood Pressure"}, "subject": {"reference": "urn:uuid:patient-temp-id"}, }, }, ], } result = client.execute_transaction(bundle) ``` -------------------------------- ### On-Behalf-Of Functionality Examples Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/faq.md Demonstrates three ways to pass the 'on-behalf-of' context: per-call keyword argument, context manager, and client default. The per-call argument has the highest precedence. ```python # Per-call (wins over ambient state) client.read_resource("Patient", "123", on_behalf_of="ProjectMembership/abc") # Context manager (ambient for a block) with client.on_behalf_of("ProjectMembership/abc"): client.read_resource("Patient", "123") # Client default (baseline for the client's lifetime) client = MedplumClient( base_url="https://api.medplum.com/", client_id="...", client_secret="...", default_on_behalf_of="ProjectMembership/abc", ) ``` -------------------------------- ### Claude Code CLI MCP Server Setup Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/mcp.md Add a pymedplum MCP server configuration using the Claude Code CLI, specifying environment variables and the command to run. ```bash claude mcp add \ -e MEDPLUM_CLIENT_ID=your-client-id \ -e MEDPLUM_CLIENT_SECRET=your-client-secret \ -e MEDPLUM_BASE_URL=https://api.medplum.com/ \ pymedplum -- \ uvx --from "pymedplum[mcp]" pymedplum-mcp ``` -------------------------------- ### Claude Code CLI MCP Server Config (.mcp.json) Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/mcp.md Example of an .mcp.json file for configuring the pymedplum MCP server with environment variable forwarding. ```json { "mcpServers": { "pymedplum": { "command": "uvx", "args": ["--from", "pymedplum[mcp]", "pymedplum-mcp"], "env": { "MEDPLUM_CLIENT_ID": "${MEDPLUM_CLIENT_ID}", "MEDPLUM_CLIENT_SECRET": "${MEDPLUM_CLIENT_SECRET}", "MEDPLUM_BASE_URL": "${MEDPLUM_BASE_URL:-https://api.medplum.com/}" } } } } ``` -------------------------------- ### Async hook for PHI access logging Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/audit_logging.md This example demonstrates an asynchronous hook for logging PHI access using `AsyncMedplumClient`. Ensure you are using `AsyncMedplumClient` as synchronous clients will raise a `TypeError` with async hooks. ```python import asyncio from pymedplum import AsyncMedplumClient from pymedplum.hooks import RequestEvent async def record_phi_access(event: RequestEvent) -> None: await audit_log_writer.write(event.to_phi_audit_dict()) async def main() -> None: async with AsyncMedplumClient( base_url="https://api.medplum.com/", client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", on_request_complete=record_phi_access, ) as client: await client.read_resource("Patient", "123") asyncio.run(main()) ``` -------------------------------- ### Install and Update FHIR Types Source: https://github.com/kinsteadhealth/pymedplum/blob/main/scripts/README.md Manually install or update the `@medplum/fhirtypes` package and then install other project dependencies using npm. ```bash cd scripts # Install/update dependencies npm install "@medplum/fhirtypes@^5.0.0" --save npm install ``` -------------------------------- ### Execute Operation via GET Request Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/operations.md For simple lookups, operations can support GET requests. Specify `method="GET"` and pass parameters as query arguments. ```python result = client.execute_operation( "CodeSystem", "lookup", params={"code": "12345", "system": "http://loinc.org"}, method="GET", ) ``` -------------------------------- ### Launch pymedplum MCP Server with uvx Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/installation.md Launches the optional MCP server directly using uvx. This is the recommended pattern for using the MCP server. ```bash uvx --from "pymedplum[mcp]" pymedplum-mcp ``` -------------------------------- ### Invite User to Project Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Creates a User, profile, and ProjectMembership, optionally sending an email invitation. Set a password directly if not sending an email. ```python from pymedplum import MedplumClient client = MedplumClient(client_id="...", client_secret="...") membership = client.invite_user( project_id="project-abc", resource_type="Practitioner", first_name="Alice", last_name="Smith", email="alice@clinic.example.com", password="Temp@1234!", # set initial password (no email invite) send_email=False, admin=False, access_policy="AccessPolicy/policy-123", ) print(membership["id"]) # ProjectMembership ID ``` -------------------------------- ### Invite User via Client Helper Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/admin.md Invites a new user to the project using the `invite_user` helper method. Specify the resource type, name, email, and whether to send an email notification. ```python membership = client.invite_user( project_id="YOUR_PROJECT_ID", resource_type="Practitioner", first_name="Alice", last_name="Smith", email="alice.smith@example.com", send_email=True, ) print(membership["id"]) ``` -------------------------------- ### Execute Operations via GET Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/operations.md Many operations support GET requests with query parameters for simple lookups. ```APIDOC ## Execute Operations via GET ### Description Executes an operation using the HTTP GET method, suitable for simple lookups where parameters can be passed as query parameters. ### Method `client.execute_operation(resource_type, operation_name, params, method='GET')` ### Parameters - **resource_type** (string): The FHIR resource type (e.g., "CodeSystem"). - **operation_name** (string): The name of the operation (e.g., "lookup"). - **params** (object): An object containing query parameters for the operation. - **method** (string, optional): Explicitly set to 'GET'. Defaults to POST if not specified. ### Request Example ```python result = client.execute_operation( "CodeSystem", "lookup", params={"code": "12345", "system": "http://loinc.org"}, method="GET", ) ``` ``` -------------------------------- ### Create and Activate Virtual Environment Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/installation.md Sets up a Python virtual environment named 'venv' and activates it. This is a standard practice for isolating project dependencies. ```bash python -m venv venv source venv/bin/activate ``` -------------------------------- ### Create and Deploy Bot Source: https://github.com/kinsteadhealth/pymedplum/blob/main/README.md Creates a new bot with a specified runtime and deploys compiled code to it. The runtime_version is required for execution. ```python # Create a bot with AWS Lambda runtime bot = client.create_bot( name="Welcome Email Bot", description="Sends welcome emails to new patients", runtime_version="awslambda" # Required for execution ) # Deploy compiled bot code with open("dist/welcome-bot.js") as f: client.deploy_bot(bot["id"], f.read()) ``` -------------------------------- ### Search Resources with Bundle Options Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/client_design.md Use `search_resources` to query for resources. Set `return_bundle=True` to receive a `FHIRBundle` object for easier resource handling and type conversion. ```python from pymedplum.fhir import Patient bundle = client.search_resources("Patient", {"family": "Smith"}, return_bundle=True) for resource_dict in bundle: print(resource_dict["id"]) patients = bundle.get_resources_typed(Patient) for p in patients: print(p.birth_date) ``` -------------------------------- ### Invite a new user with PyMedplum Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/faq.md Use the `invite_user` method to add a new user to a project. Ensure you provide the correct project ID and user details. ```python # Invite a new user membership = client.invite_user( project_id="PROJECT_ID", resource_type="Practitioner", first_name="Alice", last_name="Smith", email="alice@example.com" ) ``` -------------------------------- ### Make GET Request Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/api_reference.md Use this method to make a GET request to a Medplum API endpoint. Provide the API path and any additional arguments for httpx.request. ```python client.get(path, **kwargs) ``` -------------------------------- ### invite_user Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Creates a `User`, profile resource, and `ProjectMembership` in one call, optionally sending an email invitation. ```APIDOC ## invite_user — Invite a User to a Project Creates a `User`, profile resource, and `ProjectMembership` in one call, optionally sending an email invitation. ```python from pymedplum import MedplumClient client = MedplumClient(client_id="...", client_secret="...") membership = client.invite_user( project_id="project-abc", resource_type="Practitioner", first_name="Alice", last_name="Smith", email="alice@clinic.example.com", password="Temp@1234!", # set initial password (no email invite) send_email=False, admin=False, access_policy="AccessPolicy/policy-123", ) print(membership["id"]) # ProjectMembership ID ``` ``` -------------------------------- ### Install pymedplum in Editable Mode with Dev Extras Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/installation.md Installs the pymedplum package in editable mode, including development dependencies like pytest, ruff, and mypy. This is essential for contributing to the project. ```bash pip install -e ".[dev]" ``` -------------------------------- ### get / post Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Call any Medplum API endpoint (including admin APIs) directly. ```APIDOC ## get / post — Raw Medplum Endpoint Access Call any Medplum API endpoint (including admin APIs) directly. ```python from pymedplum import MedplumClient client = MedplumClient(client_id="...", client_secret="...") # GET admin endpoint project_info = client.get("admin/projects/project-abc") # POST to an arbitrary endpoint result = client.post("admin/projects/project-abc/invite", { "resourceType": "Practitioner", "firstName": "Bob", "lastName": "Jones", "email": "bob@example.com", "sendEmail": True, }) ``` ``` -------------------------------- ### Initialize Medplum Client and Manage Resources Source: https://github.com/kinsteadhealth/pymedplum/blob/main/README.md Demonstrates initializing the MedplumClient and performing basic CRUD operations: creating a Patient, reading a Patient by ID, searching for Patients, and updating a Patient. Ensure you replace placeholder client ID and secret. ```python from pymedplum import MedplumClient client = MedplumClient( # base_url="https://api.medplum.com/", # default; self-hosted? set yours. client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) patient = client.create_resource({ "resourceType": "Patient", "name": [{"given": ["John"], "family": "Doe"}], "gender": "male", "birthDate": "1990-01-01", }) pati ent = client.read_resource("Patient", "patient-123") patients = client.search_resources("Patient", {"family": "Doe"}) pati ent["active"] = True updated = client.update_resource(patient) ``` -------------------------------- ### Save and Deploy Bot Code in One Step Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Conveniently save source code and deploy compiled code simultaneously. ```python # Read both source and compiled code with open("src/my-bot.ts") as f: source_code = f.read() with open("dist/my-bot.js") as f: compiled_code = f.read() # Save and deploy bot, deploy_result = client.save_and_deploy_bot( bot_id="your-bot-id-here", source_code=source_code, compiled_code=compiled_code ) print(f"Bot updated: {bot['id']}") print(f"Deployment result: {deploy_result}") ``` -------------------------------- ### Get Resource Accounts Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/api_reference.md Retrieve a list of account reference strings from a resource's `meta.accounts` field. ```python get_resource_accounts(patient) ``` -------------------------------- ### Add Project Site Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/admin.md Appends a new site configuration to the project. This includes the site name and associated domains. ```python project_id = "YOUR_PROJECT_ID" project = client.get(f"admin/projects/{project_id}") current_sites = project.get("project", {}).get("site", []) new_sites = current_sites + [{"name": "New Site", "domain": ["new-app.example.com"]}] client.post(f"admin/projects/{project_id}/sites", new_sites) ``` -------------------------------- ### Execute FHIR Operation with Query Params Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Use 'execute_operation' for GET requests with query parameters, such as '$lookup'. ```python result = client.execute_operation( "CodeSystem", "lookup", params={"code": "73211009", "system": "http://snomed.info/sct"}, method="GET", ) ``` -------------------------------- ### Basic Search Parameters Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/search.md Demonstrates how to search for resources using single or multiple basic search parameters. ```APIDOC ## Basic Search Parameters All search methods accept a `query` parameter that can be a dictionary of search parameters: ```python # Search by single parameter patients = client.search_resources("Patient", {"family": "Smith"}) # Search by multiple parameters (AND logic) patients = client.search_resources( "Patient", { "family": "Smith", "given": "John", "birthdate": "1980-01-01", }, ) ``` ``` -------------------------------- ### Get Patient Display Name Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/utils.md Extracts a display-friendly full name from a Patient resource. Handles the HumanName data type complexity. ```python from pymedplum.helpers import get_patient_display_name patient = {"name": [{"given": ["John", "B."], "family": "Doe"}]} display_name = get_patient_display_name(patient) print(display_name) ``` -------------------------------- ### Get Async Job Status Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/api_reference.md Retrieve the current status of an asynchronous job. The `job` parameter can be an ID, a full status URL, or an OperationOutcome. ```python # Check once without waiting job = client.get_async_job_status(result) if job["status"] == "completed": print(job["output"]) elif job["status"] in ("accepted", "active"): print("Still running") ``` -------------------------------- ### Error Handling for Bot Deployment Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Illustrates how to wrap bot deployment operations in a try-except block to gracefully handle potential errors during the deployment process. ```python try: result = client.deploy_bot(bot_id, compiled_code) print(f"Deployment successful: {result}") except Exception as e: print(f"Deployment failed: {e}") # Handle error appropriately ``` -------------------------------- ### Create Bot Source: https://github.com/kinsteadhealth/pymedplum/blob/main/README.md Creates a new bot with a specified runtime version. ```APIDOC ## Create Bot ### Description Creates a new bot, which can be used to automate tasks. Requires specifying a `runtime_version`. ### Method ```python client.create_bot(name: str, description: str, runtime_version: str) ``` ### Parameters - **name** (str) - The name of the bot. - **description** (str) - A description of the bot's purpose. - **runtime_version** (str) - The runtime environment for the bot (e.g., 'awslambda'). ### Request Example ```python bot = client.create_bot( name="Welcome Email Bot", description="Sends welcome emails to new patients", runtime_version="awslambda" # Required for execution ) ``` ### Response Returns the created bot resource, including its ID. ``` -------------------------------- ### Make DELETE Request Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/api_reference.md Use this method to make a DELETE request to a Medplum API endpoint. It accepts similar parameters to the GET method. ```python client.delete(path, **kwargs) ``` -------------------------------- ### Get CodeableConcept Display Text Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/utils.md Extracts the display text from a CodeableConcept. Prefers the 'text' field, falling back to the first 'coding.display' value. ```python from pymedplum.helpers import get_code_display concept = { "coding": [{"system": "http://snomed.info/sct", "code": "38341003", "display": "Hypertension"}] } display = get_code_display(concept) print(display) ``` -------------------------------- ### Deploy and Execute Bot with Delay Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Deploys a bot and then waits for a short period before executing it. This accounts for potential propagation delays after deployment. ```python import time # Deploy the bot client.deploy_bot(bot_id, compiled_code) # Wait a moment for deployment to complete time.sleep(2) # Then execute result = client.execute_bot(bot_id, input_data) ``` -------------------------------- ### client.create_bot() Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Creates a new Bot resource with specified properties. ```APIDOC ## client.create_bot() ### Description Create a new Bot resource. ### Parameters #### Path Parameters - `name` (str) - Required - The name of the bot - `description` (str) - Optional - Bot description - `source_code` (str) - Optional - Initial source code - `runtime_version` (str) - Optional - Runtime ("awslambda" or "vmcontext") - `**kwargs` (Any) - Additional Bot resource properties ### Returns `dict[str, Any]` - The created Bot resource ``` -------------------------------- ### Reverse Includes (`_revinclude`) Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/search.md Retrieve resources that reference the search results using `_revinclude`. This allows you to find all observations for a specific patient, for example. ```python bundle = client.search_resources( "Patient", { "family": "Smith", "_revinclude": "Observation:patient", }, ) ``` -------------------------------- ### Search Resources in Python Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/faq.md Three methods for searching resources: iterate through all pages, get a single page of results, or retrieve a single matching resource. ```python # 1. Get all results (handles pagination automatically) for patient in client.search_resource_pages("Patient", {"family": "Smith"}): print(patient["id"]) ``` ```python # 2. Get one page bundle = client.search_resources("Patient", {"family": "Smith"}) ``` ```python # 3. Get single result patient = client.search_one("Patient", {"identifier": "MRN|12345"}) ``` -------------------------------- ### Save Source Code Before Deploying Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Demonstrates the good practice of saving bot source code to the Bot resource before deploying the compiled code. This ensures version control and auditability. ```python # Good: Save source before deploying client.save_and_deploy_bot(bot_id, source_code, compiled_code) # Not recommended: Deploy without saving source client.deploy_bot(bot_id, compiled_code) ``` -------------------------------- ### Search FHIR Resources with Pagination (Dicts) Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/quickstart.md Use `search_resource_pages` to iterate through search results, handling pagination automatically. This example retrieves `Observation` resources as dictionaries. ```python for observation in client.search_resource_pages( "Observation", {"subject": "Patient/some-patient-id", "category": "vital-signs"}, ): print(f"Found Observation {observation['id']} with status: {observation['status']}") ``` -------------------------------- ### Ergonomic Search with `search_with_options` Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/search.md Use `search_with_options` for a more convenient way to handle common search options, including summary views. ```python result = client.search_with_options( "Patient", {"active": "true"}, summary="count", ) print(f"Active patients: {result.get('total', 0)}") ``` -------------------------------- ### execute_operation Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Executes a FHIR operation with optional parameters and method specification. Supports GET requests with query parameters and can auto-wrap simple dictionaries into Parameters resources for other methods. ```APIDOC ## GET with query params (e.g., $lookup) ```python result = client.execute_operation( "CodeSystem", "lookup", params={"code": "73211009", "system": "http://snomed.info/sct"}, method="GET", ) ``` ## Auto-wrap simple dict into Parameters resource ```python result = client.execute_operation( "MedicationRequest", "calculate-dose", resource_id="med-req-456", params={"weight": 70, "unit": "kg"}, wrap_params=True, ) ``` ``` -------------------------------- ### Per-Client Isolation Example Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/on_behalf_of.md Demonstrates that each MedplumClient instance maintains its own independent OBO context. Setting OBO on one client does not affect another, even within the same process. ```python client_a = MedplumClient(base_url="https://api.medplum.com/") client_b = MedplumClient(base_url="https://api.medplum.com/") with client_a.on_behalf_of("ProjectMembership/actor-a"): # client_b still has no OBO set — isolation is per-instance. client_b.read_resource("Patient", "123") ``` -------------------------------- ### Enable MCP Server Writes Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/mcp.md Set this environment variable to true to enable write operations (create, update, patch, delete, etc.) on the MCP server. A warning will be printed at startup. ```bash export MEDPLUM_ENABLE_WRITES="true" ``` -------------------------------- ### Request Event Audit Methods Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/api_reference.md Provides examples of methods available on the RequestEvent object for generating audit dictionaries. These methods help in logging request details for compliance and observability. ```python event.to_phi_audit_dict() # PHI-bearing; for HIPAA-approved audit sinks event.to_phi_audit_dict(include_query_params=True) # also includes parsed search params event.to_non_phi_dict() # shape-only; for metrics / general observability ``` -------------------------------- ### Initialize MedplumClient Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/quickstart.md Instantiate MedplumClient or AsyncMedplumClient with your credentials. HTTPS is enforced by default unless using a loopback address or explicitly allowing insecure HTTP. ```python from pymedplum import MedplumClient client = MedplumClient( base_url="https://api.medplum.com/", client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) ``` -------------------------------- ### Using Sync and Async Clients Together Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/faq.md Both synchronous and asynchronous clients can be used in the same application, but they must be instantiated separately to avoid sharing connections. ```python # Synchronous operations sync_client = MedplumClient(...) # Asynchronous operations async def async_operations(): async with AsyncMedplumClient(...) as async_client: await async_client.read_resource("Patient", "123") ``` -------------------------------- ### Initialize MedplumClient (Synchronous) Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Instantiate the synchronous MedplumClient with client credentials, an access token, or a custom httpx.Client. Handles authentication, token refresh, and retries. ```python from pymedplum import MedplumClient # Basic usage with client credentials (auto-authenticates on first request) client = MedplumClient( base_url="https://api.medplum.com/", # default; override for self-hosted client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", timeout=30.0, failed_refresh_cooldown=1.0, max_retry_delay_seconds=60.0, ) ``` ```python # As a context manager (auto-closes HTTP connections) with MedplumClient(client_id="...", client_secret="...") as client: patient = client.read_resource("Patient", "123") ``` ```python # Pass a pre-obtained access token instead of credentials client = MedplumClient(access_token="eyJ...") ``` ```python # Custom httpx.Client (must have follow_redirects=False) import httpx http = httpx.Client(timeout=60.0, follow_redirects=False) client = MedplumClient(http_client=http, client_id="...", client_secret="...") ``` -------------------------------- ### Illustrative Shape of RequestEvent Attempts Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/audit_logging.md This is an illustrative example of the shape of the `RequestEvent.attempts` list, showing details of each retry attempt including status code, wall time, and OBO information. ```python # attempt 1: 429, 0.05s wall, OBO "ProjectMembership/abc" # attempt 2: 429, 0.12s wall, OBO "ProjectMembership/abc" # attempt 3: 200, 0.08s wall, OBO "ProjectMembership/abc" ``` -------------------------------- ### Search Parameter Chaining on References Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/search.md Filter resources based on fields of referenced resources using dot notation. For example, search for observations by the patient's family name. ```python observations = client.search_resources( "Observation", { "patient.family": "Smith", }, ) appointments = client.search_resources( "Appointment", { "actor.identifier": "NPI|1234567890", }, ) ``` -------------------------------- ### Create Bot Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Creates a new Bot resource. It is crucial to specify the `runtime_version` (e.g., 'awslambda') for the bot to be deployable and executable. ```APIDOC ## Create Bot ### Description Creates a new Bot resource. It is crucial to specify the `runtime_version` (e.g., 'awslambda') for the bot to be deployable and executable. ### Method `client.create_bot(...) ### Parameters - **name** (string) - Required - The name of the bot. - **description** (string) - Optional - A description for the bot. - **runtime_version** (string) - Required - The runtime version for the bot (e.g., 'awslambda', 'vmcontext'). ### Request Example ```python from pymedplum import MedplumClient client = MedplumClient(base_url="https://api.medplum.com") bot = client.create_bot( name="My Bot", description="Processes patient data", runtime_version="awslambda" # This is required! ) ``` ### Response #### Success Response (200) - **Bot resource object** - The created Bot resource. #### Response Example ```json { "resourceType": "Bot", "id": "your-bot-id-here", "name": "My Bot", "description": "Processes patient data", "runtimeVersion": "awslambda" } ``` ``` -------------------------------- ### FHIRBundle Wrapper Usage Source: https://github.com/kinsteadhealth/pymedplum/blob/main/README.md Shows how to use the FHIRBundle wrapper for easier iteration, type casting, and pagination. The `return_bundle=True` parameter is used in search calls. ```python # Get wrapper with helper methods bundle = client.search_resources("Patient", {"family": "Smith"}, return_bundle=True) # Iterate directly over resources for patient in bundle: print(patient['name']) # Get typed resources with as_fhir parameter from pymedplum.fhir import Patient bundle = client.search_resources("Patient", {"family": "Smith"}, return_bundle=True, as_fhir=Patient) patients = bundle.get_resources_typed(Patient) # Or use get_resources_typed on any bundle bundle = client.search_resources("Patient", {"family": "Smith"}, return_bundle=True) patients = bundle.get_resources_typed(Patient) # Check if empty, get total, access pagination if not bundle.is_empty(): print(f"Found {bundle.get_total()} results") next_page = bundle.get_next_link() ``` -------------------------------- ### Raw Medplum Endpoint Access (GET/POST) Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Allows direct access to any Medplum API endpoint, including admin APIs, using GET or POST requests. Requires client initialization. ```python from pymedplum import MedplumClient client = MedplumClient(client_id="...", client_secret="...") # GET admin endpoint project_info = client.get("admin/projects/project-abc") # POST to an arbitrary endpoint result = client.post("admin/projects/project-abc/invite", { "resourceType": "Practitioner", "firstName": "Bob", "lastName": "Jones", "email": "bob@example.com", "sendEmail": True, }) ``` -------------------------------- ### Handling Common PyMedplum Errors Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/faq.md Gracefully handle various exceptions raised by PyMedplum, such as `NotFoundError`, `AuthorizationError`, `ValidationError`, and `OperationOutcomeError`. This example demonstrates a try-except block for robust error management. ```python from pymedplum import ( AuthorizationError, InsecureTransportError, NotFoundError, OperationOutcomeError, PreconditionFailedError, RateLimitError, ServerError, TokenRefreshCooldownError, UnsafeRedirectError, ValidationError, ) try: patient = client.read_resource("Patient", "123") except NotFoundError: ... except AuthorizationError: ... except ValidationError: ... except RateLimitError: ... except PreconditionFailedError: # If-Match / If-None-Exist version mismatch ... except (OperationOutcomeError, ServerError) as exc: # exc.sanitize_for_logging() returns a PHI-safe dict for logs. raise except TokenRefreshCooldownError as exc: # Retry later; exc.retry_after tells you how long to wait. raise ``` -------------------------------- ### Search FHIR Resources with Pagination (Pydantic Models) Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/quickstart.md Use `search_resource_pages` to iterate through search results, handling pagination automatically. This example retrieves `Observation` resources as typed Pydantic models. ```python from pymedplum.fhir import Observation for observation in client.search_resource_pages( "Observation", {"subject": "Patient/some-patient-id", "category": "vital-signs"}, as_fhir=Observation, ): print(f"Found Observation {observation.id} with status: {observation.status}") ``` -------------------------------- ### Initialize MedplumClient for Bot Management Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/bots.md Bot management methods are available directly on the MedplumClient. The client authenticates automatically on the first request. ```python from pymedplum import MedplumClient client = MedplumClient(base_url="https://api.medplum.com") # All bot methods are available on the client client.create_bot(...) client.deploy_bot(...) client.execute_bot(...) ``` -------------------------------- ### FHIRBundle Wrapper for Convenience Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Utilizes the FHIRBundle wrapper for easier access to resources and metadata. This approach provides convenience methods for common operations like getting total counts and next links. ```python bundle = client.search_resources("Patient", {"family": "Smith"}, return_bundle=True) for patient in bundle: print(patient["name"][0]["family"]) print(f"Total: {bundle.get_total()}, Has next: {bundle.get_next_link()}") ``` -------------------------------- ### Managing Project Sites Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/advanced/admin.md This snippet shows how to retrieve current project sites, add a new site, and update the project's sites. ```APIDOC ## Managing project sites ### Description Retrieve current project sites, add a new site, and update the project's sites. ### Method GET, POST ### Endpoint `admin/projects/{project_id}` `admin/projects/{project_id}/sites` ### Request Example ```python project_id = "YOUR_PROJECT_ID" project = client.get(f"admin/projects/{project_id}") current_sites = project.get("project", {}).get("site", []) new_sites = current_sites + [{"name": "New Site", "domain": ["new-app.example.com"]}] client.post(f"admin/projects/{project_id}/sites", new_sites) ``` ``` -------------------------------- ### Read Resource as Dict or Typed Model Source: https://github.com/kinsteadhealth/pymedplum/blob/main/docs/client_design.md Use `read_resource` to retrieve resources. Specify `as_fhir` with a Pydantic model class to get typed model output; otherwise, a dictionary is returned by default. ```python from pymedplum.fhir import Patient patient_dict = client.read_resource("Patient", "some-id") print(patient_dict["name"][0]["family"]) patient_model = client.read_resource("Patient", "some-id", as_fhir=Patient) print(patient_model.name[0].family) ``` -------------------------------- ### Handle Binary Files and Documents Source: https://github.com/kinsteadhealth/pymedplum/blob/main/README.md Upload, download, and link binary FHIR resources like PDFs. Requires `client` object to be initialized. ```python # Upload a PDF with open("lab_report.pdf", "rb") as f: binary = client.upload_binary(f.read(), "application/pdf") ``` ```python # Download binary pdf_bytes = client.download_binary(binary["id"]) ``` ```python # Create DocumentReference linking binary to patient doc_ref = client.create_document_reference( patient_id="patient-123", binary_id=binary["id"], content_type="application/pdf", title="Lab Results", description="CBC performed on 2024-01-15" ) ``` -------------------------------- ### Pydantic v2 Typed FHIR Models Source: https://context7.com/kinsteadhealth/pymedplum/llms.txt Utilizes auto-generated Pydantic v2 models for FHIR resources, supporting both camelCase and snake_case field names. Includes serialization and full workflow examples. ```python from pymedplum.fhir import ( Patient, Observation, Practitioner, Organization, Bundle, Coverage, Condition, HumanName, CodeableConcept, ) from pymedplum.helpers import to_fhir_json # Construct with snake_case (Pythonic) or camelCase (FHIR API) — both work patient_a = Patient(birth_date="1990-06-15", gender="female") patient_b = Patient(birthDate="1990-06-15", gender="female") assert patient_a.birth_date == patient_b.birth_date # Handle Python keyword conflicts with trailing underscore from pymedplum.fhir import Coverage coverage = Coverage( resource_type="Coverage", status="active", class_=[{"type": {"code": "group"}, "value": "GRP001"}], # 'class' is a Python keyword ) # Serialize back to FHIR JSON (camelCase, None fields excluded) fhir_dict = to_fhir_json(patient_a) # {"resourceType": "Patient", "birthDate": "1990-06-15", "gender": "female"} # Full workflow: create model, send to API, get typed response from pymedplum import MedplumClient client = MedplumClient(client_id="...", client_secret="...") new_obs = Observation( status="final", code=CodeableConcept(text="Body Weight"), value_quantity={"value": 70.5, "unit": "kg"}, ) created_obs: Observation = client.create_resource(new_obs, as_fhir=Observation) print(created_obs.id) # server-assigned ID print(created_obs.status) # "final" ```