# `Medplum`
[🔗](https://github.com/CodeDuckers-LLC/medplum_elixir/blob/v0.3.0/lib/medplum.ex#L1)

Concise client for Medplum's FHIR API and OAuth flows.

Build a `Medplum.Client`, then pass it to the resource helpers in this module for
authenticated FHIR requests. Public operations return `{:ok, map()}` for decoded
response bodies or `{:error, %Medplum.Error{}}` for transport, auth, or API failures.

Clients can either reuse cached client-credentials tokens or use an existing bearer
token directly. The module exposes resource helpers, OAuth helpers, and lower-level
request functions for unsupported endpoints.

## Example

    client =
      Medplum.new(
        base_url: "https://api.medplum.com",
        client_id: System.fetch_env!("MEDPLUM_CLIENT_ID"),
        client_secret: System.fetch_env!("MEDPLUM_CLIENT_SECRET")
      )

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

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

# `async_result`

```elixir
@type async_result() :: %{
  required(String.t()) =&gt; term(),
  optional(String.t()) =&gt; term()
}
```

# `binary_result`

```elixir
@type binary_result() :: %{
  body: binary(),
  content_type: String.t() | nil,
  headers: [{String.t(), String.t()}]
}
```

# `client`

```elixir
@type client() :: Medplum.Client.t()
```

# `result`

```elixir
@type result() :: {:ok, map()} | {:error, Medplum.Error.t()}
```

# `api_request`

```elixir
@spec api_request(Medplum.Client.t(), atom(), String.t(), keyword()) :: result()
```

Sends an authenticated request to a non-FHIR Medplum path relative to `base_url`.

# `authorize_url`

```elixir
@spec authorize_url(Medplum.Client.t() | keyword() | map(), keyword() | map()) ::
  String.t()
```

Builds a Medplum OAuth authorize URL for authorization-code flows.

# `batch`

```elixir
@spec batch(Medplum.Client.t(), [map()] | map()) :: result() | {:ok, async_result()}
```

Executes a FHIR batch bundle against the base endpoint.

# `create`

```elixir
@spec create(Medplum.Client.t(), String.t(), map()) :: result()
```

Creates a FHIR resource and fills in `"resourceType"` when it is omitted.

# `create_binary`

```elixir
@spec create_binary(Medplum.Client.t(), binary(), keyword()) :: result()
```

Uploads raw bytes to the Binary endpoint.

# `delete`

```elixir
@spec delete(Medplum.Client.t(), String.t(), String.t()) :: result()
```

Deletes a FHIR resource by resource type and id.

# `exchange_authorization_code`

```elixir
@spec exchange_authorization_code(
  Medplum.Client.t() | keyword() | map(),
  String.t(),
  keyword() | map()
) ::
  result()
```

Exchanges an authorization code for a Medplum OAuth token response.

# `get_binary`

```elixir
@spec get_binary(Medplum.Client.t(), String.t()) ::
  {:ok, binary_result()} | {:error, Medplum.Error.t()}
```

Downloads raw bytes from a Binary resource.

# `graphql`

```elixir
@spec graphql(Medplum.Client.t(), String.t(), keyword()) :: result()
```

Sends a GraphQL request to the FHIR GraphQL endpoint.

# `new`

```elixir
@spec new(keyword() | map()) :: Medplum.Client.t()
```

Builds a reusable Medplum client from base URL and client credentials.

# `new!`

```elixir
@spec new!(keyword() | map()) :: Medplum.Client.t()
```

Builds a reusable Medplum client and raises on invalid configuration.

# `new_with_access_token`

```elixir
@spec new_with_access_token(keyword() | map(), String.t()) :: Medplum.Client.t()
```

Builds a reusable Medplum client that authenticates with an existing bearer token.

# `operation`

```elixir
@spec operation(
  Medplum.Client.t(),
  :system | String.t() | {String.t(), String.t()},
  String.t(),
  map(),
  keyword()
) :: result() | {:ok, async_result()}
```

Invokes a FHIR operation on the system, type, or instance level.

# `patch`

```elixir
@spec patch(Medplum.Client.t(), String.t(), String.t(), [map()]) :: result()
```

Applies a JSON Patch document to a resource by type and id.

# `poll_async`

```elixir
@spec poll_async(Medplum.Client.t(), String.t(), keyword()) ::
  result() | {:ok, async_result()}
```

Polls an async status URL until a final response is available.

# `read`

```elixir
@spec read(Medplum.Client.t(), String.t(), String.t()) :: result()
```

Fetches one FHIR resource by resource type and id.

# `request`

```elixir
@spec request(Medplum.Client.t(), atom(), String.t(), keyword()) :: result()
```

Sends an authenticated request to any FHIR-relative path or absolute Medplum URL.

# `search`

```elixir
@spec search(Medplum.Client.t(), String.t(), map()) :: result()
```

Searches a FHIR resource type with query parameters encoded from the given map.

# `stream_search`

```elixir
@spec stream_search(Medplum.Client.t(), String.t(), map()) :: Enumerable.t()
```

Streams Bundle entries across paginated search results.

The stream yields each Bundle `entry` map and raises `Medplum.Error` if a later page fails.

# `transaction`

```elixir
@spec transaction(Medplum.Client.t(), [map()] | map()) ::
  result() | {:ok, async_result()}
```

Executes a FHIR transaction bundle against the base endpoint.

# `update`

```elixir
@spec update(Medplum.Client.t(), String.t(), String.t(), map()) :: result()
```

Replaces a FHIR resource by type and id, forcing the outgoing body to match both.

# `upsert`

```elixir
@spec upsert(Medplum.Client.t(), String.t(), map()) :: result()
```

Performs an official Medplum conditional upsert using a query embedded in attrs.

# `userinfo`

```elixir
@spec userinfo(
  Medplum.Client.t(),
  keyword()
) :: result()
```

Fetches OpenID Connect userinfo from `/oauth2/userinfo`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
