This guide covers first client setup and common request patterns.

Installation

Add package to mix.exs:

def deps do
  [
    {:medplum_elixir, "~> 0.2.0"}
  ]
end

Fetch deps:

mix deps.get

Credentials

This client uses Medplum OAuth client credentials flow. Typical env vars:

export MEDPLUM_BASE_URL="https://api.medplum.com"
export MEDPLUM_CLIENT_ID="..."
export MEDPLUM_CLIENT_SECRET="..."

Build client

client =
  Medplum.new(
    base_url: System.fetch_env!("MEDPLUM_BASE_URL"),
    client_id: System.fetch_env!("MEDPLUM_CLIENT_ID"),
    client_secret: System.fetch_env!("MEDPLUM_CLIENT_SECRET")
  )

Client struct is reusable across requests. Token caching is enabled by default.

CRUD example

{:ok, created} =
  Medplum.create(client, "Patient", %{
    "name" => [%{"family" => "Smith", "given" => ["Ada"]}]
  })

{:ok, fetched} = Medplum.read(client, "Patient", created["id"])

{:ok, updated} =
  Medplum.update(client, "Patient", created["id"], %{
    "active" => true
  })

:ok =
  case Medplum.delete(client, "Patient", created["id"]) do
    {:ok, _resource} -> :ok
    {:error, error} -> raise error
  end

Search example

{:ok, bundle} =
  Medplum.search(client, "Patient", %{
    "family" => "Smith",
    "_count" => "10"
  })

Use stream_search/3 when result set may span many pages:

entries =
  client
  |> Medplum.stream_search("Observation", %{"subject" => "Patient/123"})
  |> Enum.to_list()

JSON Patch example

ops = [
  %{"op" => "replace", "path" => "/active", "value" => true}
]

{:ok, patient} = Medplum.patch(client, "Patient", "123", ops)

Lower-level requests

Use request/4 for unsupported endpoints or custom headers:

{:ok, result} =
  Medplum.request(client, :get, "/Patient/123/$everything", params: %{"_count" => "20"})

Use operation/5 for FHIR operations:

{:ok, export_result} =
  Medplum.operation(client, {"Claim", "claim-123"}, "export", %{}, method: :get)

GraphQL and batch

{:ok, graphql_result} =
  Medplum.graphql(client, "query Demo { PatientList { id } }")

{:ok, batch_result} =
  Medplum.batch(client, [
    %{"request" => %{"method" => "GET", "url" => "Patient/123"}},
    %{"request" => %{"method" => "GET", "url" => "Observation?subject=Patient/123"}}
  ])

Error handling

Public functions return {:error, %Medplum.Error{}} on failure:

case Medplum.read(client, "Patient", "missing-id") do
  {:ok, patient} ->
    patient

  {:error, %Medplum.Error{type: :api_error, status: 404}} ->
    nil

  {:error, %Medplum.Error{} = error} ->
    raise error
end

Phoenix config

# config/runtime.exs
config :my_app, :medplum,
  base_url: System.fetch_env!("MEDPLUM_BASE_URL"),
  client_id: System.fetch_env!("MEDPLUM_CLIENT_ID"),
  client_secret: System.fetch_env!("MEDPLUM_CLIENT_SECRET")
client =
  :my_app
  |> Application.fetch_env!(:medplum)
  |> Medplum.new()