Production-grade Elixir hex package for the Unit embedded banking API.

Hex.pm Hex Docs

Features

  • ✅ Full Unit API coverage: applications, customers, accounts, cards, payments, transactions, webhooks, and more
  • ✅ JSON:API envelope handling — resources decoded into typed Elixir structs
  • ✅ Three-tier token model: Org, Customer, Cardholder
  • ✅ Automatic retry with exponential back-off and jitter
  • ✅ Idempotency key support on all mutating requests
  • ✅ Telemetry instrumentation ([:unit, :request, :start/stop/exception])
  • ✅ Runtime config resolution ({:system, "ENV_VAR"} and MFA tuples)
  • ✅ Sandbox simulation endpoints for every resource type
  • ✅ Zero-surprise error types via Unit.Error

Installation

# mix.exs
def deps do
  [
    {:unit, "~> 1.0"}
  ]
end

Configuration

# config/runtime.exs
config :unit,
  api_token: System.get_env("UNIT_API_TOKEN"),
  environment: :sandbox    # :sandbox | :production

Quick start

# 1. Onboard an individual customer
{:ok, app} = Unit.API.Applications.create_individual(%{
  full_name: %{first: "Jane", last: "Doe"},
  ssn: "000000002",
  date_of_birth: ~D[1990-01-15],
  address: %{street: "123 Main St", city: "SF", state: "CA", postal_code: "94105", country: "US"},
  email: "jane@example.com",
  phone: %{country_code: "1", number: "5555550100"},
  ip: "127.0.0.1"
})

# 2. Open a checking account
{:ok, account} = Unit.API.Accounts.create_deposit(app.customer_id, "checking")

# 3. Issue a virtual debit card
{:ok, card} = Unit.API.Cards.create_individual_virtual_debit(%{
  customer_id: app.customer_id,
  account_id: account.id
})

# 4. Send an ACH credit
{:ok, payment} = Unit.API.Payments.create_ach(%{
  account_id: account.id,
  amount: 10_000,            # $100.00 in cents
  direction: "Credit",
  description: "Payroll",
  counterparty: %{
    routing_number: "812345678",
    account_number: "1000000002",
    account_type: "Checking",
    name: "Jane Doe"
  }
})

# 5. Listen for events via webhooks
{:ok, _webhook} = Unit.API.Webhooks.create(%{
  label: "my-app",
  url: "https://myapp.com/webhooks/unit",
  token: "my-secret-token",
  delivery_mode: "AtLeastOnce"
})

Error handling

All functions return {:ok, result} or {:error, %Unit.Error{}}:

case Unit.API.Payments.create_ach(params) do
  {:ok, payment} ->
    Logger.info("Payment created: #{payment.id}")

  {:error, %Unit.Error{type: :validation_error, errors: errors}} ->
    Logger.warning("Validation failed: #{inspect(errors)}")

  {:error, %Unit.Error{type: :auth_error}} ->
    Logger.error("Invalid or expired API token")

  {:error, %Unit.Error{type: :network_error, message: msg}} ->
    Logger.error("Network failure: #{msg}")
end

Per-request options

Every API function accepts opts that override global config:

# Use a customer-scoped token for front-end requests
Unit.API.Accounts.list(api_token: customer_token)

# Adjust timeout for a slow operation
Unit.API.Statements.get_pdf(id, timeout: 60_000)

# Use a different environment
Unit.API.Sandbox.receive_ach(params, environment: :sandbox)

Telemetry

Attach to standard telemetry events:

:telemetry.attach(
  "unit-logger",
  [:unit, :request, :stop],
  fn _event, %{duration: d}, %{resource: r, action: a, status: s}, _config ->
    Logger.info("[Unit] #{r}.#{a} → HTTP #{s} (#{div(d, 1_000_000)}ms)")
  end,
  nil
)

Sandbox simulations

# Simulate an incoming ACH credit (sandbox only)
Unit.API.Sandbox.receive_ach(%{
  account_id: account.id,
  amount: 50_000,
  direction: "Credit",
  description: "Test deposit"
})

# Simulate a card purchase
Unit.API.Sandbox.purchase_card(%{
  card_id: card.id,
  amount: 1_500,
  merchant: %{name: "Coffee Shop", type: 5812, category: "Restaurants", location: "SF"}
})

API coverage

ModuleEndpoints
Unit.API.Applicationscreate individual/business, get, list, update, cancel, documents upload
Unit.API.Customersget, list, update, archive, authorized users
Unit.API.Accountscreate deposit, get, list, update, close, freeze/unfreeze, limits, balance history
Unit.API.Cardscreate (all types), get, list, update, freeze/unfreeze, report lost/stolen, close, activate
Unit.API.PaymentsACH, Wire, Book, Bulk, received ACH, return received ACH, cancel
Unit.API.Transactionsget, list, update tags
Unit.API.Counterpartiescreate, get, list, update, delete
Unit.API.Repaymentsbook, ACH, capital partner variants, get, list
Unit.API.CheckDepositscreate, upload front/back, get, list, update
Unit.API.CheckPaymentscreate, get, list, cancel, return, get images
Unit.API.StopPaymentsACH, check, get, list, disable
Unit.API.Chargebackscreate, list
Unit.API.Statementslist, HTML, PDF, bank PDF
Unit.API.Webhookscreate, get, list, update, delete, enable/disable
Unit.API.Eventsget, list, fire
Unit.API.Tokenscustomer token, token verification, cardholder token, org token
Unit.API.Institutionslookup by routing number
Unit.API.Sandboxapprove/deny app, receive ACH/wire, authorize/purchase card, ATM, check deposit, interest

License

MIT