defmodule Triple do @moduledoc """ Elixir client for the [Triple](https://jointriple.com) transaction data enrichment API. ## Quick start client = Triple.new(api_key: System.fetch_env!("TRIPLE_API_KEY")) {:ok, enriched} = Triple.enrich_transaction(client, %{ merchant_name: "AMZN MKTP UK", transaction_type: :CARD_TRANSACTION, transaction_id: Triple.Util.generate_transaction_id(), transaction_amount: 24.99, transaction_currency: "GBP" }) `client` is a plain `Triple.Config` struct — pass it explicitly everywhere. There's no global or process-dictionary state, which keeps the library safe to use with multiple Triple accounts/environments (e.g. sandbox and production) side by side in the same application. ## Configuration Every option can be passed to `new/1` directly, or set application-wide: config :triple, api_key: System.fetch_env!("TRIPLE_API_KEY") See `Triple.Config` for the full list of options (timeouts, retries, custom `Req` options, an optional client-side rate limiter, etc). ## Error handling Every call returns `{:ok, result} | {:error, %Triple.Error{}}`. Each function also has a `!` counterpart that raises `Triple.Error` instead — e.g. `enrich_transaction!/2`. See `Triple.Error` for the fields available on failure (HTTP status, field-level validation errors, retry-after, etc). ## Context modules Every resource also has its own module if you'd rather call it directly: `Triple.Enrich`, `Triple.Brands`, `Triple.Feedback`, `Triple.Stocks`, `Triple.Cryptos`, `Triple.TLS`. """ alias Triple.{Config, Error} alias Triple.Types.{Brand, Crypto, Stock, TLSCertificate} alias Triple.Types.Enrich.{V1, V2} @type client :: Config.t() @doc "Builds a client (a `Triple.Config` struct). See `Triple.Config.new/1` for all options." @spec new(keyword()) :: client() defdelegate new(opts \\ []), to: Config @doc "See `Triple.Enrich.transaction/2`." @spec enrich_transaction(client(), map() | keyword()) :: {:ok, V1.Response.t()} | {:error, Error.t()} defdelegate enrich_transaction(client, attrs), to: Triple.Enrich, as: :transaction @doc "See `Triple.Enrich.transaction!/2`." @spec enrich_transaction!(client(), map() | keyword()) :: V1.Response.t() defdelegate enrich_transaction!(client, attrs), to: Triple.Enrich, as: :transaction! @doc "See `Triple.Enrich.unstructured_transaction/2`." @spec enrich_unstructured_transaction(client(), map() | keyword()) :: {:ok, V2.Response.t()} | {:error, Error.t()} defdelegate enrich_unstructured_transaction(client, attrs), to: Triple.Enrich, as: :unstructured_transaction @doc "See `Triple.Enrich.unstructured_transaction!/2`." @spec enrich_unstructured_transaction!(client(), map() | keyword()) :: V2.Response.t() defdelegate enrich_unstructured_transaction!(client, attrs), to: Triple.Enrich, as: :unstructured_transaction! @doc "See `Triple.Brands.fetch/2`." @spec fetch_brand(client(), String.t()) :: {:ok, Brand.t()} | {:error, Error.t()} defdelegate fetch_brand(client, id), to: Triple.Brands, as: :fetch @doc "See `Triple.Brands.fetch!/2`." @spec fetch_brand!(client(), String.t()) :: Brand.t() defdelegate fetch_brand!(client, id), to: Triple.Brands, as: :fetch! @doc "See `Triple.Feedback.report/2`." @spec report_feedback(client(), map() | keyword()) :: {:ok, :no_content} | {:error, Error.t()} defdelegate report_feedback(client, attrs), to: Triple.Feedback, as: :report @doc "See `Triple.Feedback.report!/2`." @spec report_feedback!(client(), map() | keyword()) :: :no_content defdelegate report_feedback!(client, attrs), to: Triple.Feedback, as: :report! @doc "See `Triple.Stocks.fetch/3`." @spec fetch_stock(client(), String.t(), keyword()) :: {:ok, Stock.t()} | {:error, Error.t()} defdelegate fetch_stock(client, isin, opts \\ []), to: Triple.Stocks, as: :fetch @doc "See `Triple.Stocks.fetch!/3`." @spec fetch_stock!(client(), String.t(), keyword()) :: Stock.t() defdelegate fetch_stock!(client, isin, opts \\ []), to: Triple.Stocks, as: :fetch! @doc "See `Triple.Cryptos.fetch/2`." @spec fetch_crypto(client(), String.t()) :: {:ok, Crypto.t()} | {:error, Error.t()} defdelegate fetch_crypto(client, slug), to: Triple.Cryptos, as: :fetch @doc "See `Triple.Cryptos.fetch!/2`." @spec fetch_crypto!(client(), String.t()) :: Crypto.t() defdelegate fetch_crypto!(client, slug), to: Triple.Cryptos, as: :fetch! @doc "See `Triple.TLS.issue_certificate/2`." @spec issue_tls_certificate(client(), map() | keyword()) :: {:ok, TLSCertificate.t()} | {:error, Error.t()} defdelegate issue_tls_certificate(client, attrs), to: Triple.TLS, as: :issue_certificate @doc "See `Triple.TLS.issue_certificate!/2`." @spec issue_tls_certificate!(client(), map() | keyword()) :: TLSCertificate.t() defdelegate issue_tls_certificate!(client, attrs), to: Triple.TLS, as: :issue_certificate! end