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