Skip to main content

guides/getting-started.md

# Getting Started

This guide covers first client setup and common request patterns.

## Installation

Add package to `mix.exs`:

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

Fetch deps:

```bash
mix deps.get
```

## Credentials

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

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

## Build client

```elixir
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

```elixir
{: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

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

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

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

## JSON Patch example

```elixir
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:

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

Use `operation/5` for FHIR operations:

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

## GraphQL and batch

```elixir
{: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:

```elixir
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

```elixir
# 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")
```

```elixir
client =
  :my_app
  |> Application.fetch_env!(:medplum)
  |> Medplum.new()
```