Current section
Files
Jump to
Current section
Files
lib/loops_elixir/client.ex
defmodule LoopsEx.Client do
@moduledoc """
HTTP client for Loops API.
"""
@typedoc "Response type returned by Loops API calls"
@type response :: {:ok, any()} | {:error, any()}
@typedoc "Raw JSON map returned from API"
@type json :: map()
use Tesla
@base_url "https://app.loops.so/api/v1"
@doc """
Build a Tesla client for the Loops API.
"""
@spec client() :: Tesla.Client.t()
def client do
api_key = Application.get_env(:loops_ex, :api_key)
middleware = [
{Tesla.Middleware.BaseUrl, @base_url},
{Tesla.Middleware.BearerAuth, token: api_key},
{Tesla.Middleware.JSON, engine: Jason}
]
Tesla.client(middleware)
end
@doc """
Execute an API call.
- method: HTTP method atom (e.g. :get, :post)
- path: endpoint path (e.g. "/contacts/create")
- body: JSON body map (default %{})
- query: query params map (default %{})
Returns `response()` tuple.
"""
@spec request_api(atom(), String.t(), json(), map()) :: response()
def request_api(method, path, body \\ %{}, query \\ %{}) do
Tesla.request(client(), method: method, url: path, body: body, query: query)
end
@doc false
@spec handle_response({:ok, Tesla.Env.t()} | {:error, any()}) :: response()
def handle_response({:ok, %Tesla.Env{status: status, body: body}}) when status >= 200 and status < 300, do: {:ok, body}
def handle_response({:ok, %Tesla.Env{status: status, body: body}}), do: {:error, {status, body}}
def handle_response({:error, reason}), do: {:error, reason}
end